tx · 8XZjmSv9YmBVodmaa5FhmYk9s7crxSb3CvXwCLDRiFeb

3MtoZUczzB13W1FBwFat4qUsPvZTmfbPgfD:  -0.07500000 Waves

2022.12.16 16:03 [2362899] smart account 3MtoZUczzB13W1FBwFat4qUsPvZTmfbPgfD > SELF 0.00000000 Waves

{ "type": 13, "id": "8XZjmSv9YmBVodmaa5FhmYk9s7crxSb3CvXwCLDRiFeb", "fee": 7500000, "feeAssetId": null, "timestamp": 1671195912498, "version": 2, "chainId": 84, "sender": "3MtoZUczzB13W1FBwFat4qUsPvZTmfbPgfD", "senderPublicKey": "A4SEfMUg91Ajmn3tCGwsoA6fGedNdTgs5GdAo5JdeP79", "proofs": [ "2SVPAT6uQxmuf1vu4864RJ77aq6tLoaMyHboWUh693yFHftthjvXVXEjbKkAJHArqZk4zHs9sBu4a4FKXb6nHnFN" ], "script": "base64:BgJ6CAISABIAEgASABIDCgEBEgMKAQESDgoMAQEBAQEBAQEBAQEBEhQKEgEBAQEBAQEICAgIAQEBAQEBARIFCgMBAQESBgoEAQEBCBIAEgMKAQESBAoCAQESAwoBCBIAEgASAwoBCBIDCgEBEgASABIDCgEIEgASBAoCCAjBAQAJa19vcmFfa2V5AglrX29yYV9rZXkAD2tfb3JhX2Jsb2NrX2tleQIPa19vcmFfYmxvY2tfa2V5AAVrX29yYQIFa19vcmEACWtfYmFsYW5jZQIJa19iYWxhbmNlAAprX3NlcXVlbmNlAgprX3NlcXVlbmNlAA5rX3Bvc2l0aW9uU2l6ZQIOa19wb3NpdGlvblNpemUAEGtfcG9zaXRpb25NYXJnaW4CEGtfcG9zaXRpb25NYXJnaW4AFmtfcG9zaXRpb25PcGVuTm90aW9uYWwCFmtfcG9zaXRpb25PcGVuTm90aW9uYWwALmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CEmtfcG9zaXRpb25GcmFjdGlvbgASa19wb3NpdGlvblNlcXVlbmNlAhJrX3Bvc2l0aW9uU2VxdWVuY2UAD2tfcG9zaXRpb25Bc3NldAIPa19wb3NpdGlvbkFzc2V0AA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQAC2tfY2xvc2VPbmx5AgtrX2Nsb3NlT25seQAFa19mZWUCBWtfZmVlAA9rX2Z1bmRpbmdQZXJpb2QCD2tfZnVuZGluZ1BlcmlvZAARa19pbml0TWFyZ2luUmF0aW8CEWtfaW5pdE1hcmdpblJhdGlvABhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8CBWtfbW1yABVrX2xpcXVpZGF0aW9uRmVlUmF0aW8CFWtfbGlxdWlkYXRpb25GZWVSYXRpbwAZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwIWa19wYXJ0TGlxdWlkYXRpb25SYXRpbwANa19zcHJlYWRMaW1pdAINa19zcHJlYWRMaW1pdAAQa19tYXhQcmljZUltcGFjdAIQa19tYXhQcmljZUltcGFjdAAQa19tYXhQcmljZVNwcmVhZAIQa19tYXhQcmljZVNwcmVhZAARa19tYXhPcGVuTm90aW9uYWwCEWtfbWF4T3Blbk5vdGlvbmFsABVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQCFWtfZmVlVG9TdGFrZXJzUGVyY2VudAAQa19tYXhPcmFjbGVEZWxheQIQa19tYXhPcmFjbGVEZWxheQANa19sYXN0RGF0YVN0cgINa19sYXN0RGF0YVN0cgAOa19sYXN0TWludXRlSWQCDmtfbGFzdE1pbnV0ZUlkAB1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UAE2tfdHdhcERhdGFMYXN0UHJpY2UCE2tfdHdhcERhdGFMYXN0UHJpY2UAGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAhprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIba19sYXRlc3RMb25nUHJlbWl1bUZyYWN0aW9uACZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIca19sYXRlc3RTaG9ydFByZW1pdW1GcmFjdGlvbgASa19uZXh0RnVuZGluZ0Jsb2NrAh5rX25leHRGdW5kaW5nQmxvY2tNaW5UaW1lc3RhbXAAEWtfbG9uZ0Z1bmRpbmdSYXRlAhFrX2xvbmdGdW5kaW5nUmF0ZQASa19zaG9ydEZ1bmRpbmdSYXRlAhJrX3Nob3J0RnVuZGluZ1JhdGUAE2tfcXVvdGVBc3NldFJlc2VydmUCCGtfcXRBc3RSABJrX2Jhc2VBc3NldFJlc2VydmUCCGtfYnNBc3RSABJrX3F1b3RlQXNzZXRXZWlnaHQCCGtfcXRBc3RXABFrX2Jhc2VBc3NldFdlaWdodAIIa19ic0FzdFcAE2tfdG90YWxQb3NpdGlvblNpemUCE2tfdG90YWxQb3NpdGlvblNpemUAF2tfdG90YWxMb25nUG9zaXRpb25TaXplAhdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAYa190b3RhbFNob3J0UG9zaXRpb25TaXplAhhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAE2tfb3BlbkludGVyZXN0U2hvcnQCE2tfb3BlbkludGVyZXN0U2hvcnQAEmtfb3BlbkludGVyZXN0TG9uZwISa19vcGVuSW50ZXJlc3RMb25nABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MAD2tfdmF1bHRfYWRkcmVzcwIPa192YXVsdF9hZGRyZXNzAA9rX2FkbWluX2FkZHJlc3MCD2tfYWRtaW5fYWRkcmVzcwASa19hZG1pbl9wdWJsaWNfa2V5AhJrX2FkbWluX3B1YmxpY19rZXkADWtfcXVvdGVfYXNzZXQCDWtfcXVvdGVfYXNzZXQAD2tfcXVvdGVfc3Rha2luZwIPa19xdW90ZV9zdGFraW5nABFrX3N0YWtpbmdfYWRkcmVzcwIRa19zdGFraW5nX2FkZHJlc3MAD2tfbWluZXJfYWRkcmVzcwIPa19taW5lcl9hZGRyZXNzABBrX29yZGVyc19hZGRyZXNzAhBrX29yZGVyc19hZGRyZXNzABJrX3JlZmVycmFsX2FkZHJlc3MCEmtfcmVmZXJyYWxfYWRkcmVzcwAUa19jb2xsYXRlcmFsX2FkZHJlc3MCFGtfY29sbGF0ZXJhbF9hZGRyZXNzABJrX2V4Y2hhbmdlX2FkZHJlc3MCEmtfZXhjaGFuZ2VfYWRkcmVzcwAVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhVrX25mdF9tYW5hZ2VyX2FkZHJlc3MAIGtfdHJhZGVyX21hcmtldF9hc3NldF9jb2xsYXRlcmFsAiBrX3RyYWRlcl9tYXJrZXRfYXNzZXRfY29sbGF0ZXJhbAEOdG9Db21wb3NpdGVLZXkCBF9rZXkIX2FkZHJlc3MJAKwCAgkArAICBQRfa2V5AgFfBQhfYWRkcmVzcwELY29vcmRpbmF0b3IACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MCE0Nvb3JkaW5hdG9yIG5vdCBzZXQBDGFkbWluQWRkcmVzcwAJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19hZG1pbl9hZGRyZXNzAQ5hZG1pblB1YmxpY0tleQAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19hZG1pbl9wdWJsaWNfa2V5AQpxdW90ZUFzc2V0AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ1rX3F1b3RlX2Fzc2V0ARFxdW90ZUFzc2V0U3Rha2luZwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3F1b3RlX3N0YWtpbmcCG1F1b3RlIGFzc2V0IHN0YWtpbmcgbm90IHNldAEOc3Rha2luZ0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAURa19zdGFraW5nX2FkZHJlc3MCD1N0YWtpbmcgbm90IHNldAEMdmF1bHRBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfdmF1bHRfYWRkcmVzcwINVmF1bHQgbm90IHNldAEMbWluZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfbWluZXJfYWRkcmVzcwINTWluZXIgbm90IHNldAENb3JkZXJzQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRBrX29yZGVyc19hZGRyZXNzAg5PcmRlcnMgbm90IHNldAEPcmVmZXJyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfcmVmZXJyYWxfYWRkcmVzcwIQUmVmZXJyYWwgbm90IHNldAERbmZ0TWFuYWdlckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhNORlQgTWFuYWdlciBub3Qgc2V0ARFjb2xsYXRlcmFsQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRRrX2NvbGxhdGVyYWxfYWRkcmVzcwIaQ29sbGF0ZXJhbCBNYW5hZ2VyIG5vdCBzZXQBC3N3YXBBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCCQELY29vcmRpbmF0b3IABRJrX2V4Y2hhbmdlX2FkZHJlc3MCD05vIHN3YXAgYWRkcmVzcwIUSW52YWxpZCBzd2FwIGFkZHJlc3MAEWtfd2hpdGVsaXN0X2Fzc2V0AhFrX3doaXRlbGlzdF9hc3NldAEQaXNXaGl0ZWxpc3RBc3NldAEIX2Fzc2V0SWQJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBEWNvbGxhdGVyYWxBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgURa193aGl0ZWxpc3RfYXNzZXQFCF9hc3NldElkBwANa190b2tlbl9wYXJhbQINa190b2tlbl9wYXJhbQAMa190b2tlbl90eXBlAgxrX3Rva2VuX3R5cGUAGEZFRV9SRURVQ1RJT05fVE9LRU5fVFlQRQINZmVlX3JlZHVjdGlvbgAIRElSX0xPTkcAAQAJRElSX1NIT1JUAAIADVRXQVBfSU5URVJWQUwADwAPT1JBQ0xFX0lOVEVSVkFMAA8AB1NFQ09ORFMA6AcAD0RFQ0lNQUxfTlVNQkVSUwAGAAxERUNJTUFMX1VOSVQJAGgCAAEJAGgCCQBoAgkAaAIJAGgCCQBoAgAKAAoACgAKAAoACgAHT05FX0RBWQkAaAIAgKMFBQxERUNJTUFMX1VOSVQACEFMTF9GRUVTAGQAD1BOTF9PUFRJT05fU1BPVAABABFQTkxfT1BUSU9OX09SQUNMRQACAQFzAQJfeAkArAICCQCkAwEFAl94AgEsAQRkaXZkAgJfeAJfeQkAbgQFAl94BQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEEbXVsZAICX3gCX3kJAG4EBQJfeAUCX3kFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBXNxcnRkAQJfeAkBBHNxcnQEBQJfeAUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQRwb3dkAgJfeAJfeQkAbAYFAl94BQ9ERUNJTUFMX05VTUJFUlMFAl95BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BBWJkaXZkAgJfeAJfeQkAvQIEBQJfeAkAtgIBBQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEFYm11bGQCAl94Al95CQC9AgQFAl94BQJfeQkAtgIBBQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQZic3FydGQBAl94CQEKc3FydEJpZ0ludAQFAl94BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BBWJwb3dkAgJfeAJfeQkAdgYFAl94BQ9ERUNJTUFMX05VTUJFUlMFAl95BQ9ERUNJTUFMX05VTUJFUlMFD0RFQ0lNQUxfTlVNQkVSUwUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQlsaXN0VG9TdHIBBV9saXN0CgEFX2pvaW4CC2FjY3VtdWxhdG9yA3ZhbAkArAICCQCsAgIFC2FjY3VtdWxhdG9yBQN2YWwCASwECm5ld0xpc3RTdHIKAAIkbAUFX2xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBV9qb2luAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQEC25ld0xpc3RTdHJVCQCzAgIFCm5ld0xpc3RTdHIAAQQLbmV3TGlzdFN0clIDCQAAAgkArwICBQtuZXdMaXN0U3RyVQABAgEsCQCwAgIFC25ld0xpc3RTdHJVAAEFC25ld0xpc3RTdHJVBQtuZXdMaXN0U3RyUgEJc3RyVG9MaXN0AQRfc3RyCQC1CQIFBF9zdHICASwBC3B1c2hUb1F1ZXVlAwVfbGlzdAhfbWF4U2l6ZQZfdmFsdWUDCQBmAgkAkAMBBQVfbGlzdAUIX21heFNpemUJAM0IAgkA0QgCBQVfbGlzdAAABQZfdmFsdWUJAM0IAgUFX2xpc3QFBl92YWx1ZQEDaW50AQFrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUEdGhpcwUBawkArAICAg1ubyB2YWx1ZSBmb3IgBQFrAQVpbnRPcgIBawNkZWYJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBawUDZGVmAQRzdHJBAghfYWRkcmVzcwRfa2V5BAN2YWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQhfYWRkcmVzcwUEX2tleQkArAICAhFObyB2YWx1ZSBmb3Iga2V5IAUEX2tleQUDdmFsAQRpbnRBAghfYWRkcmVzcwRfa2V5BAN2YWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQhfYWRkcmVzcwUEX2tleQkArAICAhFObyB2YWx1ZSBmb3Iga2V5IAUEX2tleQUDdmFsAQhjYmFsYW5jZQAJAQNpbnQBBQlrX2JhbGFuY2UBA2ZlZQAJAQNpbnQBBQVrX2ZlZQEPaW5pdE1hcmdpblJhdGlvAAkBA2ludAEFEWtfaW5pdE1hcmdpblJhdGlvAQZxdEFzdFIACQEDaW50AQUTa19xdW90ZUFzc2V0UmVzZXJ2ZQEGYnNBc3RSAAkBA2ludAEFEmtfYmFzZUFzc2V0UmVzZXJ2ZQEGcXRBc3RXAAkBBWludE9yAgUSa19xdW90ZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBBmJzQXN0VwAJAQVpbnRPcgIFEWtfYmFzZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBEXRvdGFsUG9zaXRpb25TaXplAAkBA2ludAEFE2tfdG90YWxQb3NpdGlvblNpemUBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAkBA2ludAEFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBEW9wZW5JbnRlcmVzdFNob3J0AAkBA2ludAEFE2tfb3BlbkludGVyZXN0U2hvcnQBEG9wZW5JbnRlcmVzdExvbmcACQEDaW50AQUSa19vcGVuSW50ZXJlc3RMb25nARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAkBA2ludAEFEmtfbmV4dEZ1bmRpbmdCbG9jawEQZnVuZGluZ1BlcmlvZFJhdwAJAQNpbnQBBQ9rX2Z1bmRpbmdQZXJpb2QBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUMREVDSU1BTF9VTklUARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFB1NFQ09ORFMBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ACQEDaW50AQUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkBA2ludAEFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQEDaW50AQUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwELc3ByZWFkTGltaXQACQEDaW50AQUNa19zcHJlYWRMaW1pdAEObWF4UHJpY2VJbXBhY3QACQEDaW50AQUQa19tYXhQcmljZUltcGFjdAEObWF4UHJpY2VTcHJlYWQACQEDaW50AQUQa19tYXhQcmljZVNwcmVhZAEPbWF4T3Blbk5vdGlvbmFsAAkBA2ludAEFEWtfbWF4T3Blbk5vdGlvbmFsASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEDaW50AQUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEDaW50AQUXa190b3RhbExvbmdQb3NpdGlvblNpemUBDGxhc3RTZXF1ZW5jZQAJAQVpbnRPcgIFCmtfc2VxdWVuY2UAAAETZmVlVG9TdGFrZXJzUGVyY2VudAAJAQNpbnQBBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQBDm1heE9yYWNsZURlbGF5AAkBA2ludAEFEGtfbWF4T3JhY2xlRGVsYXkBD2dldEFjdHVhbENhbGxlcgEBaQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQENb3JkZXJzQWRkcmVzcwACCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcJAAIBAg5JbnZhbGlkIG1hcmdpbgMDCQEBIQEFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBnAgUUcmVtYWluaW5nTWFyZ2luUmF0aW8AAAcJAAIBAg5JbnZhbGlkIG1hcmdpbgYBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BDV9wb3NpdGlvblNpemUDCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIsU2hvdWxkIG5vdCBiZSBjYWxsZWQgd2l0aCBfcG9zaXRpb25TaXplID09IDADCQBmAgUNX3Bvc2l0aW9uU2l6ZQAACQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAELZ2V0UG9zaXRpb24BB190cmFkZXIED3Bvc2l0aW9uU2l6ZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgQHJG1hdGNoMAUPcG9zaXRpb25TaXplT3B0AwkAAQIFByRtYXRjaDACA0ludAQMcG9zaXRpb25TaXplBQckbWF0Y2gwCQCWCgQFDHBvc2l0aW9uU2l6ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgkAlgoEAAAAAAAAAAABEGdldFBvc2l0aW9uQXNzZXQBB190cmFkZXIEEHBvc2l0aW9uQXNzZXRPcHQJAJ0IAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQdfdHJhZGVyBAckbWF0Y2gwBRBwb3NpdGlvbkFzc2V0T3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQNcG9zaXRpb25Bc3NldAUHJG1hdGNoMAUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAABE3JlcXVpcmVPcGVuUG9zaXRpb24BB190cmFkZXIDCQAAAggJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEAAAkAAgECEE5vIG9wZW4gcG9zaXRpb24GAQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUNa19pbml0aWFsaXplZAcBBnBhdXNlZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUIa19wYXVzZWQHAQljbG9zZU9ubHkACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFC2tfY2xvc2VPbmx5BwENdXBkYXRlUmVzZXJ2ZQMGX2lzQWRkEV9xdW90ZUFzc2V0QW1vdW50EF9iYXNlQXNzZXRBbW91bnQDBQZfaXNBZGQEB25ld0Jhc2UJAGUCCQEGYnNBc3RSAAUQX2Jhc2VBc3NldEFtb3VudAMJAGcCAAAFB25ld0Jhc2UJAAIBAipUeCBsZWFkIHRvIGJhc2UgYXNzZXQgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwkAZAIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAUHbmV3QmFzZQkAZAIJARF0b3RhbFBvc2l0aW9uU2l6ZQAFEF9iYXNlQXNzZXRBbW91bnQECG5ld1F1b3RlCQBlAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50AwkAZwIAAAUIbmV3UXVvdGUJAAIBAipUeCBsZWFkIHRvIGJhc2UgcXVvdGUgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwUIbmV3UXVvdGUJAGQCCQEGYnNBc3RSAAUQX2Jhc2VBc3NldEFtb3VudAkAZQIJARF0b3RhbFBvc2l0aW9uU2l6ZQAFEF9iYXNlQXNzZXRBbW91bnQBDWNhbGNJbnZhcmlhbnQEB19xdEFzdFIHX3F0QXN0VwdfYnNBc3RSB19ic0FzdFcEB2JxdEFzdFIJALYCAQUHX3F0QXN0UgQHYnF0QXN0VwkAtgIBBQdfcXRBc3RXBAdiYnNBc3RSCQC2AgEFB19ic0FzdFIEB2Jic0FzdFcJALYCAQUHX2JzQXN0VwkBBWJtdWxkAgkBBWJtdWxkAgUHYnF0QXN0UgUHYnF0QXN0VwkBBWJtdWxkAgUHYmJzQXN0UgUHYmJzQXN0VwEJc3dhcElucHV0AgZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAFrCQENY2FsY0ludmFyaWFudAQFB19xdEFzdFIFB19xdEFzdFcFB19ic0FzdFIFB19ic0FzdFcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIDBQZfaXNBZGQJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAkAZQIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBCQEEbXVsZAIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFB19xdEFzdFcEGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBBGRpdmQCCQEDYWJzAQkAZQIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUHX2JzQXN0UgUHX3F0QXN0VwQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AwUGX2lzQWRkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQEtAQUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBA0kdDAxNjk0NjE3MTA5CQENdXBkYXRlUmVzZXJ2ZQMFBl9pc0FkZAURX3F1b3RlQXNzZXRBbW91bnQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjk0NjE3MTA5Al8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTY5NDYxNzEwOQJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxNjk0NjE3MTA5Al8zBAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLbWFya2V0UHJpY2UJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmBBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QAAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUHX3F0QXN0UgIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQUHX2JzQXN0UgIhIHF1b3RlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEV9xdW90ZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDiBtYXJrZXRQcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCWCgQFFWFtb3VudEJhc2VBc3NldEJvdWdodAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BBBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCBQxfbWFyZ2luRGVsdGEFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE4NTk2MTg3MjMDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTg1OTYxODcyMwJfMQQHYmFkRGVidAgFDSR0MDE4NTk2MTg3MjMCXzIJAJUKAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQENY2FsY0ludmFyaWFudAQFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BBhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIDBQZfaXNBZGQJAGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAkAZQIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50BA9xdW90ZUFzc2V0QWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBCQEEbXVsZAIFGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgUQX2Jhc2VBc3NldFdlaWdodAQOcXVvdGVBc3NldFNvbGQJAQNhYnMBCQBlAgUPcXVvdGVBc3NldEFmdGVyCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAAEDSR0MDE5OTExMjAwNzIJAQ11cGRhdGVSZXNlcnZlAwkBASEBBQZfaXNBZGQFDnF1b3RlQXNzZXRTb2xkBRBfYmFzZUFzc2V0QW1vdW50BBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE5OTExMjAwNzICXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxOTkxMTIwMDcyAl8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE5OTExMjAwNzICXzMEC21hcmtldFByaWNlCQEEZGl2ZAIFDnF1b3RlQXNzZXRTb2xkBRBfYmFzZUFzc2V0QW1vdW50BAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYDAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlBRRfY2hlY2tNYXhQcmljZUltcGFjdAcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBRJfcXVvdGVBc3NldFJlc2VydmUCFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFEV9iYXNlQXNzZXRSZXNlcnZlAiAgYmFzZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRBfYmFzZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDyBtYXJrZXQgcHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAmQoHBQ5xdW90ZUFzc2V0U29sZAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAULcHJpY2VJbXBhY3QBCnN3YXBPdXRwdXQDBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0CQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcFBl9pc0FkZAUQX2Jhc2VBc3NldEFtb3VudAUUX2NoZWNrTWF4UHJpY2VJbXBhY3QJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcAARJnZXRPcmFjbGVUd2FwUHJpY2UABAZvcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQVrX29yYQIABAhwcmljZUtleQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUJa19vcmFfa2V5BAlsYXN0VmFsdWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgcHJpY2UuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhwcmljZUtleQQIYmxvY2tLZXkJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUPa19vcmFfYmxvY2tfa2V5AgADCQECIT0CBQhibG9ja0tleQIABAxjdXJyZW50QmxvY2sIBQlsYXN0QmxvY2sGaGVpZ2h0BA9sYXN0T3JhY2xlQmxvY2sJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCGJsb2NrS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgYmxvY2suIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhibG9ja0tleQMJAGYCCQBlAgUMY3VycmVudEJsb2NrBQ9sYXN0T3JhY2xlQmxvY2sJAQ5tYXhPcmFjbGVEZWxheQAJAAIBCQCsAgIJAKwCAgkArAICAiZPcmFjbGUgc3RhbGUgZGF0YS4gTGFzdCBvcmFjbGUgYmxvY2s6IAkApAMBBQ9sYXN0T3JhY2xlQmxvY2sCECBjdXJyZW50IGJsb2NrOiAJAKQDAQUMY3VycmVudEJsb2NrBQlsYXN0VmFsdWUFCWxhc3RWYWx1ZQEMYWJzUHJpY2VEaWZmBQxfb3JhY2xlUHJpY2USX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlB19xdEFzdFcHX2JzQXN0VwQKcHJpY2VBZnRlcgkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwQMYXZlcmFnZVByaWNlCQEEZGl2ZAIJAGQCBQxfb3JhY2xlUHJpY2UFCnByaWNlQWZ0ZXIJAGgCAAIFDERFQ0lNQUxfVU5JVAQMYWJzUHJpY2VEaWZmCQEEZGl2ZAIJAQNhYnMBCQBlAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UFDGFic1ByaWNlRGlmZgEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAISX3F1b3RlQXNzZXRSZXNlcnZlEV9iYXNlQXNzZXRSZXNlcnZlBAtvcmFjbGVQcmljZQkBEmdldE9yYWNsZVR3YXBQcmljZQAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQSYWJzUHJpY2VEaWZmQmVmb3JlCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UJAQZxdEFzdFIACQEGYnNBc3RSAAUHX3F0QXN0VwUHX2JzQXN0VwQRYWJzUHJpY2VEaWZmQWZ0ZXIJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwUHX2JzQXN0VwMDCQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIJAQ5tYXhQcmljZVNwcmVhZAAJAGYCBRFhYnNQcmljZURpZmZBZnRlcgUSYWJzUHJpY2VEaWZmQmVmb3JlBwkAAgEJAKwCAgkArAICCQCsAgICDVByaWNlIHNwcmVhZCAJAKQDAQURYWJzUHJpY2VEaWZmQWZ0ZXICFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIRX2xvbmdPcGVuTm90aW9uYWwSX3Nob3J0T3Blbk5vdGlvbmFsBBBfbWF4T3Blbk5vdGlvbmFsCQEPbWF4T3Blbk5vdGlvbmFsAAMJAGYCBRFfbG9uZ09wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICE0xvbmcgb3BlbiBub3Rpb25hbCAJAKQDAQURX2xvbmdPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsAwkAZgIFEl9zaG9ydE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICFFNob3J0IG9wZW4gbm90aW9uYWwgCQCkAwEFEl9zaG9ydE9wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwGAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYNX3Bvc2l0aW9uU2l6ZQdfb3B0aW9uEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ1fcG9zaXRpb25TaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsAwkAAAIFB19vcHRpb24FD1BOTF9PUFRJT05fU1BPVAQNJHQwMjQ2MzUyNDg1NQkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHCQEBIQEFB2lzU2hvcnQFD3Bvc2l0aW9uU2l6ZUFicwcFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BBNvdXRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMjQ2MzUyNDg1NQJfMQQCeDEIBQ0kdDAyNDYzNTI0ODU1Al8yBAJ4MggFDSR0MDI0NjM1MjQ4NTUCXzMEAngzCAUNJHQwMjQ2MzUyNDg1NQJfNAUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJARJnZXRPcmFjbGVUd2FwUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjYyODAyNjQwOAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjYyODAyNjQwOAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNjI4MDI2NDA4Al8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI2MjgwMjY0MDgCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjYyODAyNjQwOAJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjY5MjEyNzAzMgkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjY5MjEyNzAzMgJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNjkyMTI3MDMyAl8yBANwb24IBQ0kdDAyNjkyMTI3MDMyAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI2OTIxMjcwMzICXzQEDSR0MDI3MDM4MjcxMzEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNzAzODI3MTMxAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjcwMzgyNzEzMQJfMgQNJHQwMjcxMzYyNzMwMgkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjcxMzYyNzMwMgJfMQQHYmFkRGVidAgFDSR0MDI3MTM2MjczMDICXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI4NTQyMjg2NzAJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI4NTQyMjg2NzACXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjg1NDIyODY3MAJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyODU0MjI4NjcwAl8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI4NTQyMjg2NzACXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI4NzY1Mjg5MzMJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI4NzY1Mjg5MzMCXzEEB2JhZERlYnQIBQ0kdDAyODc2NTI4OTMzAl8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI5MDYwMjkzMzQJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI5MDYwMjkzMzQCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTA2MDI5MzM0Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyOTA2MDI5MzM0Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjkwNjAyOTMzNAJfNAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDAyOTA2MDI5MzM0Al81BA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDAyOTA2MDI5MzM0Al82BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUUcG9zaXRpb25PcGVuTm90aW9uYWwJAJ8KDQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBQdiYWREZWJ0BQtyZWFsaXplZFBubAUNbWFyZ2luVG9WYXVsdAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFDHBvc2l0aW9uU2l6ZQAABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAAACQBlAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwAAAEQZ2V0VHdhcFNwb3RQcmljZQAECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEDXN0YXJ0TWludXRlSWQJAGUCBQhtaW51dGVJZAUNVFdBUF9JTlRFUlZBTAQHbGlzdFN0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAEBGxpc3QJALUJAgUHbGlzdFN0cgIBLAoBCGZpbHRlckZuAgthY2N1bXVsYXRvcgRuZXh0AwkAZwIFDXN0YXJ0TWludXRlSWQJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAkAzQgCBQthY2N1bXVsYXRvcgkBDXBhcnNlSW50VmFsdWUBBQRuZXh0BQthY2N1bXVsYXRvcgQFbGlzdEYKAAIkbAUEbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmlsdGVyRm4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQIbWF4SW5kZXgDCQBmAgkAkAMBBQVsaXN0RgAACQCWAwEFBWxpc3RGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbGlzdAAABAxsYXN0TWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAQWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEDGVuZExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQSbm93Q3VtdWxhdGl2ZVByaWNlCQBkAgUWZW5kTGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQxlbmRMYXN0UHJpY2UEGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQOc3RhcnRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUIbWF4SW5kZXgAAAQUc3RhcnRDdW11bGF0aXZlUHJpY2UJAGQCBRhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUNc3RhcnRNaW51dGVJZAUIbWF4SW5kZXgFDnN0YXJ0TGFzdFByaWNlCQBpAgkAZQIFEm5vd0N1bXVsYXRpdmVQcmljZQUUc3RhcnRDdW11bGF0aXZlUHJpY2UFDVRXQVBfSU5URVJWQUwBE2dldFRlcm1pbmFsQW1tU3RhdGUABA1fcG9zaXRpb25TaXplCQERdG90YWxQb3NpdGlvblNpemUAAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAlAoCCQEGcXRBc3RSAAkBBmJzQXN0UgAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQNJHQwMzE0NTczMTYzNgkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwQVY3VycmVudE5ldE1hcmtldFZhbHVlCAUNJHQwMzE0NTczMTYzNgJfMQQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNDU3MzE2MzYCXzIEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDMxNDU3MzE2MzYCXzMJAJQKAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlARNnZXRRdW90ZUFzc2V0V2VpZ2h0BBBiYXNlQXNzZXRSZXNlcnZlEXRvdGFsUG9zaXRpb25TaXplEXF1b3RlQXNzZXRSZXNlcnZlC3RhcmdldFByaWNlBAFiCQC2AgEFEGJhc2VBc3NldFJlc2VydmUEAnN6CQC2AgEFEXRvdGFsUG9zaXRpb25TaXplBAFxCQC2AgEFEXF1b3RlQXNzZXRSZXNlcnZlBAFwCQC2AgEFC3RhcmdldFByaWNlBANiczIJAQVicG93ZAIJALcCAgUBYgUCc3oJALYCAQkAaAIAAgUMREVDSU1BTF9VTklUBARxYnMyCQEFYm11bGQCBQFxBQNiczIEA3BzNAkAuQICCQC2AgEABAkBBWJtdWxkAgUBcAUCc3oEA3NxcgkBBmJzcXJ0ZAEJAQVibXVsZAIFBHFiczIJALgCAgUBcQUDcHM0BAJicQkBBWJtdWxkAgUBYgUBcQQCcXMJAQVibXVsZAIFAXEFAnN6BAN0b3AJALcCAgkAtwICCQC+AgEFA3NxcgUCYnEFAnFzBANib3QJALkCAgkAtgIBAAIJAQVibXVsZAIFAXEFAnN6BAZyZXN1bHQJAQViZGl2ZAIFA3RvcAUDYm90CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQNc3BvdFR3YXBQcmljZQkBEGdldFR3YXBTcG90UHJpY2UABAdwcmVtaXVtCQBlAgUNc3BvdFR3YXBQcmljZQUPdW5kZXJseWluZ1ByaWNlAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAACQCUCgIAAAAAAwkAZgIAAAUHcHJlbWl1bQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAJQKAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24EE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAJQKAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24BDmdldEFkanVzdGVkRmVlAgtfYXJ0aWZhY3RJZBBfYmFzZUZlZURpc2NvdW50BApiYXNlRmVlUmF3CQEDZmVlAAQHYmFzZUZlZQkBBG11bGQCBQpiYXNlRmVlUmF3BRBfYmFzZUZlZURpc2NvdW50BA0kdDAzNDY1NTM1MTUwAwkBAiE9AgULX2FydGlmYWN0SWQCAAQMYXJ0aWZhY3RLaW5kCQEEc3RyQQIJARFuZnRNYW5hZ2VyQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFDGtfdG9rZW5fdHlwZQULX2FydGlmYWN0SWQDCQAAAgUMYXJ0aWZhY3RLaW5kBRhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUECXJlZHVjdGlvbgkBBGludEECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Rva2VuX3BhcmFtBQtfYXJ0aWZhY3RJZAQLYWRqdXN0ZWRGZWUJAQRtdWxkAgUHYmFzZUZlZQUJcmVkdWN0aW9uCQCUCgIFC2FkanVzdGVkRmVlBgkAAgECGUludmFsaWQgYXR0YWNoZWQgYXJ0aWZhY3QJAJQKAgUHYmFzZUZlZQcEC2FkanVzdGVkRmVlCAUNJHQwMzQ2NTUzNTE1MAJfMQQMYnVybkFydGlmYWN0CAUNJHQwMzQ2NTUzNTE1MAJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0ARdpc1NhbWVBc3NldE9yTm9Qb3NpdGlvbgIHX3RyYWRlcghfYXNzZXRJZAQPb2xkUG9zaXRpb25TaXplCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQMJAAACBQ9vbGRQb3NpdGlvblNpemUAAAYJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAQtpc1NhbWVBc3NldAIHX3RyYWRlcghfYXNzZXRJZAkAAAIJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgUIX2Fzc2V0SWQBHmdldEJvcnJvd2VkQnlUcmFkZXJJbk1hcmtldEtleQMEX2FtbQhfYXNzZXRJZAdfdHJhZGVyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICBSBrX3RyYWRlcl9tYXJrZXRfYXNzZXRfY29sbGF0ZXJhbAIBXwUEX2FtbQIBXwUIX2Fzc2V0SWQCAV8FB190cmFkZXIBE2dldEJvcnJvd2VkQnlUcmFkZXIBB190cmFkZXIEDXBvc2l0aW9uQXNzZXQJARBnZXRQb3NpdGlvbkFzc2V0AQUHX3RyYWRlcgMJAAACBQ1wb3NpdGlvbkFzc2V0CQDYBAEJAQpxdW90ZUFzc2V0AAkAlAoCAAAFDXBvc2l0aW9uQXNzZXQEA2tleQkBHmdldEJvcnJvd2VkQnlUcmFkZXJJbk1hcmtldEtleQMJAKUIAQUEdGhpcwUNcG9zaXRpb25Bc3NldAUHX3RyYWRlcgQGYm9ycm93CQELdmFsdWVPckVsc2UCCQCaCAIJARFjb2xsYXRlcmFsQWRkcmVzcwAFA2tleQAACQCUCgIFBmJvcnJvdwUNcG9zaXRpb25Bc3NldAEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBBBkb0dldEZlZURpc2NvdW50CQD8BwQJAQxtaW5lckFkZHJlc3MAAhJjb21wdXRlRmVlRGlzY291bnQJAMwIAgUHX3RyYWRlcgUDbmlsBQNuaWwDCQAAAgUQZG9HZXRGZWVEaXNjb3VudAUQZG9HZXRGZWVEaXNjb3VudAQLZmVlRGlzY291bnQEByRtYXRjaDAFEGRvR2V0RmVlRGlzY291bnQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIhSW52YWxpZCBjb21wdXRlRmVlRGlzY291bnQgcmVzdWx0BA0kdDAzNjM4MTM2NDU1CQEOZ2V0QWRqdXN0ZWRGZWUCBQtfYXJ0aWZhY3RJZAULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwMzYzODEzNjQ1NQJfMQQMYnVybkFydGlmYWN0CAUNJHQwMzYzODEzNjQ1NQJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1nZXRBcnRpZmFjdElkAQFpBAphcnRpZmFjdElkAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkA2AQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAISSW52YWxpZCBhcnRpZmFjdElkAgAFCmFydGlmYWN0SWQBDWRpc3RyaWJ1dGVGZWUBCl9mZWVBbW91bnQEDGZlZVRvU3Rha2VycwkBBG11bGQCBQpfZmVlQW1vdW50CQETZmVlVG9TdGFrZXJzUGVyY2VudAAECmZlZVRvVmF1bHQJAGUCBQpfZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMJAJQKAgUMZmVlVG9TdGFrZXJzBQpmZWVUb1ZhdWx0AQ51cGRhdGVTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2luaXRNYXJnaW5SYXRpbwUQX2luaXRNYXJnaW5SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvBQRfbW1yCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8FFF9saXF1aWRhdGlvbkZlZVJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2Z1bmRpbmdQZXJpb2QFDl9mdW5kaW5nUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQVrX2ZlZQUEX2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19zcHJlYWRMaW1pdAUMX3NwcmVhZExpbWl0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlSW1wYWN0BQ9fbWF4UHJpY2VJbXBhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZVNwcmVhZAUPX21heFByaWNlU3ByZWFkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX21heE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19mZWVUb1N0YWtlcnNQZXJjZW50BRRfZmVlVG9TdGFrZXJzUGVyY2VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhPcmFjbGVEZWxheQUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFA25pbAENdXBkYXRlRnVuZGluZwURX25leHRGdW5kaW5nQmxvY2skX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24QX2xvbmdGdW5kaW5nUmF0ZRFfc2hvcnRGdW5kaW5nUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19uZXh0RnVuZGluZ0Jsb2NrBRFfbmV4dEZ1bmRpbmdCbG9jawkAzAgCCQEMSW50ZWdlckVudHJ5AgUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUkX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19sb25nRnVuZGluZ1JhdGUFEF9sb25nRnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfc2hvcnRGdW5kaW5nUmF0ZQURX3Nob3J0RnVuZGluZ1JhdGUFA25pbAETdXBkYXRlUG9zaXRpb25Bc3NldAIIX2FkZHJlc3MIX2Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQhfYWRkcmVzcwUIX2Fzc2V0SWQFA25pbAEfaW5jcmVtZW50UG9zaXRpb25TZXF1ZW5jZU51bWJlcgINaXNOZXdQb3NpdGlvbghfYWRkcmVzcwMFDWlzTmV3UG9zaXRpb24ED2N1cnJlbnRTZXF1ZW5jZQkBDGxhc3RTZXF1ZW5jZQAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEmtfcG9zaXRpb25TZXF1ZW5jZQUIX2FkZHJlc3MJAGQCBQ9jdXJyZW50U2VxdWVuY2UAAQkAzAgCCQEMSW50ZWdlckVudHJ5AgUKa19zZXF1ZW5jZQkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABBQNuaWwFA25pbAEOdXBkYXRlUG9zaXRpb24FCF9hZGRyZXNzBV9zaXplB19tYXJnaW4NX29wZW5Ob3Rpb25hbCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzBQVfc2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUIX2FkZHJlc3MFB19tYXJnaW4JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzBQ1fb3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FA25pbAEKYXBwZW5kVHdhcAEGX3ByaWNlBAhtaW51dGVJZAkAaQIJAGkCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcADoBwA8BBBwcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFDmtfbGFzdE1pbnV0ZUlkAAADCQBmAgUQcHJldmlvdXNNaW51dGVJZAUIbWludXRlSWQJAAIBAhFUV0FQIG91dC1vZi1vcmRlcgQMbGFzdE1pbnV0ZUlkAwkAAAIFEHByZXZpb3VzTWludXRlSWQAAAUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQDCQBmAgUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFEHByZXZpb3VzTWludXRlSWQAAAQJcHJldlByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFEHByZXZpb3VzTWludXRlSWQFBl9wcmljZQQTbGFzdEN1bXVsYXRpdmVQcmljZQkAZAIFE3ByZXZDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFDGxhc3RNaW51dGVJZAUJcHJldlByaWNlBARsaXN0CQELcHVzaFRvUXVldWUDCQEJc3RyVG9MaXN0AQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQ1rX2xhc3REYXRhU3RyAgAFDVRXQVBfSU5URVJWQUwJAKQDAQUIbWludXRlSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFCG1pbnV0ZUlkBRNsYXN0Q3VtdWxhdGl2ZVByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFCG1pbnV0ZUlkBQZfcHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5rX2xhc3RNaW51dGVJZAUIbWludXRlSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUNa19sYXN0RGF0YVN0cgkBCWxpc3RUb1N0cgEFBGxpc3QFA25pbAQYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkAAAEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUGX3ByaWNlBBNsYXN0Q3VtdWxhdGl2ZVByaWNlCQBkAgUTcHJldkN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkBQlwcmV2UHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFCG1pbnV0ZUlkBRNsYXN0Q3VtdWxhdGl2ZVByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFCG1pbnV0ZUlkBQZfcHJpY2UFA25pbAERdXBkYXRlQW1tUmVzZXJ2ZXMCB19xdEFzdFIHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa19xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RSBQNuaWwBEHVwZGF0ZUFtbVdlaWdodHMCB19xdEFzdFcHX2JzQXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19xdW90ZUFzc2V0V2VpZ2h0BQdfcXRBc3RXCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2Jhc2VBc3NldFdlaWdodAUHX2JzQXN0VwUDbmlsAQl1cGRhdGVBbW0IB19xdEFzdFIHX2JzQXN0UhdfdG90YWxQb3NpdGlvblNpemVBZnRlchVfb3BlbkludGVyZXN0Tm90aW9uYWwWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZRZfdG90YWxMb25nT3Blbk5vdGlvbmFsF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwADCQECIT0CCQBlAgUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGEludmFsaWQgQU1NIHN0YXRlIGRhdGE6IAkApAMBBRZfdG90YWxMb25nUG9zaXRpb25TaXplAgQgKyAgCQCkAwEFF190b3RhbFNob3J0UG9zaXRpb25TaXplAgQgIT0gCQCkAwEFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDOCAIJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgUHX3F0QXN0UgUHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa190b3RhbFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwFFV9vcGVuSW50ZXJlc3ROb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXa190b3RhbExvbmdQb3NpdGlvblNpemUFFl90b3RhbExvbmdQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfb3BlbkludGVyZXN0TG9uZwUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa19vcGVuSW50ZXJlc3RTaG9ydAUXX3RvdGFsU2hvcnRPcGVuTm90aW9uYWwFA25pbAkBCmFwcGVuZFR3YXABCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MFA25pbAEId2l0aGRyYXcCCF9hZGRyZXNzB19hbW91bnQEB2JhbGFuY2UJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAZgIFB19hbW91bnQFB2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICAhNVbmFibGUgdG8gd2l0aGRyYXcgCQCkAwEFB19hbW91bnQCFyBmcm9tIGNvbnRyYWN0IGJhbGFuY2UgCQCkAwEFB2JhbGFuY2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUIX2FkZHJlc3MFB19hbW91bnQJAQpxdW90ZUFzc2V0AAUDbmlsAQ11cGRhdGVCYWxhbmNlAQFpAwkAZgIAAAUBaQkAAgECB0JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUBaQUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbBcBaQEFcGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFEludmFsaWQgcGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAYFA25pbAFpAQd1bnBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIHVucGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAcFA25pbAFpAQxzZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECG0ludmFsaWQgc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkGBQNuaWwBaQEOdW5zZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgdW5zZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQcFA25pbAFpAQxhZGRMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECG0ludmFsaWQgYWRkTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBRiYXNlQXNzZXRBbW91bnRUb0FkZAkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBkAgUHX2JzQXN0UgUUYmFzZUFzc2V0QW1vdW50VG9BZGQEDSR0MDQ1NDc3NDU2MzIJARRnZXRTeW5jVGVybWluYWxQcmljZQMJARJnZXRPcmFjbGVUd2FwUHJpY2UABQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA0NTQ3NzQ1NjMyAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA0NTQ3NzQ1NjMyAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwNDU0Nzc0NTYzMgJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9yZW1vdmVMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECHkludmFsaWQgcmVtb3ZlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBBdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUFcHJpY2UEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUJARF1cGRhdGVBbW1SZXNlcnZlcwIFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgFpAQ5jaGFuZ2VTZXR0aW5ncwwQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MMBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQFpAQppbml0aWFsaXplEgdfcXRBc3RSB19ic0FzdFIOX2Z1bmRpbmdQZXJpb2QQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvBF9mZWUHX29yYWNsZQpfb3JhY2xlS2V5D19vcmFjbGVCbG9ja0tleQxfY29vcmRpbmF0b3IMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5AwMDAwMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQELaW5pdGlhbGl6ZWQACQACAQIdSW52YWxpZCBpbml0aWFsaXplIHBhcmFtZXRlcnMJAM4IAgkAzggCCQDOCAIJAM4IAgkBCXVwZGF0ZUFtbQgFB19xdEFzdFIFB19ic0FzdFIAAAAAAAAAAAAAAAAJAQ51cGRhdGVTZXR0aW5ncwwFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkBRBfbWF4T3Blbk5vdGlvbmFsBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUPX21heE9yYWNsZURlbGF5CQENdXBkYXRlRnVuZGluZwUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWtfb3JhBQdfb3JhY2xlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtfb3JhX2tleQUKX29yYWNsZUtleQkAzAgCCQELU3RyaW5nRW50cnkCBQ9rX29yYV9ibG9ja19rZXkFD19vcmFjbGVCbG9ja0tleQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQZGVjcmVhc2VQb3NpdGlvbgMHX2Ftb3VudAlfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBBnBhdXNlZAAJAAIBAiNJbnZhbGlkIGRlY3JlYXNlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNDk0NzU0OTYxNQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNDk0NzU0OTYxNQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA0OTQ3NTQ5NjE1Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDQ5NDc1NDk2MTUCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNDk0NzU0OTYxNQJfNAQKX2RpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAUJRElSX1NIT1JUBQhESVJfTE9ORwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNDk3ODg0OTg5MgkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNDk3ODg0OTg5MgJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDQ5Nzg4NDk4OTICXzIEDSR0MDQ5ODk4NTI1NTYDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsBA0kdDA1MDMxMzUwNDk3CQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCAUNJHQwNTAzMTM1MDQ5NwJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDUwMzEzNTA0OTcCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUwMzEzNTA0OTcCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1MDMxMzUwNDk3Al80BBhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAUYZXhjaGFuZ2VkUG9zaXRpb25TaXplQWJzBwkAAgEJAKwCAgkArAICCQCsAgICJVRvbyBsaXR0bGUgYmFzZSBhc3NldCBleGNoYW5nZWQsIGdvdCAJAKQDAQUYZXhjaGFuZ2VkUG9zaXRpb25TaXplQWJzAgogZXhwZWN0ZWQgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQEC3JlYWxpemVkUG5sCQEEZGl2ZAIJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUYZXhjaGFuZ2VkUG9zaXRpb25TaXplQWJzCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBA0kdDA1MDkzNDUxMTc5CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBQtyZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwNTA5MzQ1MTE3OQJfMQQHYmFkRGVidAgFDSR0MDUwOTM0NTExNzkCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNTA5MzQ1MTE3OQJfMwQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUMb3Blbk5vdGlvbmFsBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQCeCgwFD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABQxvcGVuTm90aW9uYWwAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAACQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDQ5ODk4NTI1NTYCXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNDk4OTg1MjU1NgJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA0OTg5ODUyNTU2Al8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDQ5ODk4NTI1NTYCXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ5ODk4NTI1NTYCXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA0OTg5ODUyNTU2Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNDk4OTg1MjU1NgJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDQ5ODk4NTI1NTYCXzgEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNDk4OTg1MjU1NgJfOQQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNDk4OTg1MjU1NgNfMTAEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNDk4OTg1MjU1NgNfMTEEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDQ5ODk4NTI1NTYDXzEyBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQUXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxhdGVzdENQRgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBpbmNyZWFzZVBvc2l0aW9uBApfZGlyZWN0aW9uCV9sZXZlcmFnZRNfbWluQmFzZUFzc2V0QW1vdW50CF9yZWZMaW5rBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBApfcmF3QW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQIX2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLX2Fzc2V0SWRTdHIJANgEAQkBBXZhbHVlAQUIX2Fzc2V0SWQEDGlzUXVvdGVBc3NldAkAAAIFCF9hc3NldElkCQEKcXVvdGVBc3NldAAEEWlzQ29sbGF0ZXJhbEFzc2V0CQEQaXNXaGl0ZWxpc3RBc3NldAEFC19hc3NldElkU3RyAwMDAwMDAwMDCQECIT0CBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkBAiE9AgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBwYJAGcCAAAFCl9yYXdBbW91bnQGCQEBIQEJAQtpbml0aWFsaXplZAAGAwkBASEBBQxpc1F1b3RlQXNzZXQJAQEhAQURaXNDb2xsYXRlcmFsQXNzZXQHBgkBASEBCQEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkACQACAQIjSW52YWxpZCBpbmNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDUzOTk0NTQwNzkJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyCQENZ2V0QXJ0aWZhY3RJZAEFAWkEC2FkanVzdGVkRmVlCAUNJHQwNTM5OTQ1NDA3OQJfMQQMYnVybkFydGlmYWN0CAUNJHQwNTM5OTQ1NDA3OQJfMgQMcmF3RmVlQW1vdW50CQEEbXVsZAIFCl9yYXdBbW91bnQFC2FkanVzdGVkRmVlBAdfYW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUMcmF3RmVlQW1vdW50BBNkaXN0cmlidXRlRmVlQW1vdW50AwURaXNDb2xsYXRlcmFsQXNzZXQECGRvQm9ycm93CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBmJvcnJvdwkAzAgCBQdfdHJhZGVyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQdfYW1vdW50BQNuaWwDCQAAAgUIZG9Cb3Jyb3cFCGRvQm9ycm93BA1iYWxhbmNlQmVmb3JlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQ1iYWxhbmNlQmVmb3JlBQ1iYWxhbmNlQmVmb3JlBAZkb1N3YXAJAPwHBAkBC3N3YXBBZGRyZXNzAAIEc3dhcAkAzAgCCQDYBAEJAQpxdW90ZUFzc2V0AAkAzAgCAAAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFDHJhd0ZlZUFtb3VudAUDbmlsAwkAAAIFBmRvU3dhcAUGZG9Td2FwBAxiYWxhbmNlQWZ0ZXIJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDGJhbGFuY2VBZnRlcgUMYmFsYW5jZUFmdGVyBA9leGNoYW5nZWRBbW91bnQJAGUCBQxiYWxhbmNlQWZ0ZXIFDWJhbGFuY2VCZWZvcmUDCQAAAgUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUMcmF3RmVlQW1vdW50AwkAAAIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFE2Rpc3RyaWJ1dGVGZWVBbW91bnQEDnJlZmVycmVyRmVlQW55CQD8BwQJAQ9yZWZlcnJhbEFkZHJlc3MAAhVhY2NlcHRQYXltZW50V2l0aExpbmsJAMwIAgUHX3RyYWRlcgkAzAgCBQhfcmVmTGluawUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNTUzOTU1NTUzNQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNTUzOTU1NTUzNQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA1NTM5NTU1NTM1Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU1Mzk1NTU1MzUCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNTUzOTU1NTUzNQJfNAQNaXNOZXdQb3NpdGlvbgkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABA9pc1NhbWVEaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkAAAIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAQOZXhwYW5kRXhpc3RpbmcDCQEBIQEFDWlzTmV3UG9zaXRpb24FD2lzU2FtZURpcmVjdGlvbgcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDU1ODI0NTg4NjUDAwUNaXNOZXdQb3NpdGlvbgYFDmV4cGFuZEV4aXN0aW5nBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1NjI4NjU2NDU5CQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0CAUNJHQwNTYyODY1NjQ1OQJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDU2Mjg2NTY0NTkCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDU2Mjg2NTY0NTkCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1NjI4NjU2NDU5Al80AwMJAQIhPQIFE19taW5CYXNlQXNzZXRBbW91bnQAAAkAZgIFE19taW5CYXNlQXNzZXRBbW91bnQJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AgMgPCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCQBkAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABQxvcGVuTm90aW9uYWwAAAQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQBkAgkBEW9wZW5JbnRlcmVzdFNob3J0AAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQUMb3Blbk5vdGlvbmFsAAAEGWluY3JlYXNlTWFyZ2luUmVxdWlyZW1lbnQJAQRkaXZkAgUMb3Blbk5vdGlvbmFsBQlfbGV2ZXJhZ2UEDSR0MDU3MDY3NTczMDYJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFGWluY3JlYXNlTWFyZ2luUmVxdWlyZW1lbnQEDHJlbWFpbk1hcmdpbggFDSR0MDU3MDY3NTczMDYCXzEEAngxCAUNJHQwNTcwNjc1NzMwNgJfMgQCeDIIBQ0kdDA1NzA2NzU3MzA2Al8zAwkBASEBCQEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAAgECFU92ZXIgbWF4IHNwcmVhZCBsaW1pdAMJAQEhAQkBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECFk92ZXIgbWF4IG9wZW4gbm90aW9uYWwJAJ4KDAUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAGQCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBkAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBkAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAkAZAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAABRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1ODU2NTU4NjgxCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCCQClCAEIBQFpBmNhbGxlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNTg1NjU1ODY4MQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDU4NTY1NTg2ODECXzIDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQACAQIuVXNlIGRlY3JlYXNlUG9zaXRpb24gdG8gZGVjcmVhc2UgcG9zaXRpb24gc2l6ZQkAAgECFENsb3NlIHBvc2l0aW9uIGZpcnN0BA9uZXdQb3NpdGlvblNpemUIBQ0kdDA1NTgyNDU4ODY1Al8xBBduZXdQb3NpdGlvblJlbWFpbk1hcmdpbggFDSR0MDU1ODI0NTg4NjUCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTU4MjQ1ODg2NQJfMwQUbmV3UG9zaXRpb25MYXRlc3RDUEYIBQ0kdDA1NTgyNDU4ODY1Al80BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1NTgyNDU4ODY1Al81BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNTU4MjQ1ODg2NQJfNgQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDU1ODI0NTg4NjUCXzcEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA1NTgyNDU4ODY1Al84BA50b3RhbExvbmdBZnRlcggFDSR0MDU1ODI0NTg4NjUCXzkED3RvdGFsU2hvcnRBZnRlcggFDSR0MDU1ODI0NTg4NjUDXzEwBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDU1ODI0NTg4NjUDXzExBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1NTgyNDU4ODY1A18xMgQNJHQwNTg4NzE1ODkyOAkBDWRpc3RyaWJ1dGVGZWUBBQlmZWVBbW91bnQEDGZlZVRvU3Rha2VycwgFDSR0MDU4ODcxNTg5MjgCXzEECmZlZVRvVmF1bHQIBQ0kdDA1ODg3MTU4OTI4Al8yBAVzdGFrZQMFDGlzUXVvdGVBc3NldAQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAkAzAgCBwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQlmZWVBbW91bnQFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYJAR9pbmNyZW1lbnRQb3NpdGlvblNlcXVlbmNlTnVtYmVyAgUNaXNOZXdQb3NpdGlvbgUHX3RyYWRlcgkBE3VwZGF0ZVBvc2l0aW9uQXNzZXQCBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQENdXBkYXRlQmFsYW5jZQEJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50CQEOZG9CdXJuQXJ0aWZhY3QCBQxidXJuQXJ0aWZhY3QFAWkJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJYWRkTWFyZ2luAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQABBFpc0NvbGxhdGVyYWxBc3NldAkBEGlzV2hpdGVsaXN0QXNzZXQBBQtfYXNzZXRJZFN0cgMDAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2lzU2FtZUFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjA4NzY2MDk2MQkBGGdldEZvclRyYWRlcldpdGhBcnRpZmFjdAIFB190cmFkZXIJAQ1nZXRBcnRpZmFjdElkAQUBaQQLYWRqdXN0ZWRGZWUIBQ0kdDA2MDg3NjYwOTYxAl8xBAxidXJuQXJ0aWZhY3QIBQ0kdDA2MDg3NjYwOTYxAl8yBAxyYXdGZWVBbW91bnQJAQRtdWxkAgUKX3Jhd0Ftb3VudAULYWRqdXN0ZWRGZWUEB19hbW91bnQJAGUCBQpfcmF3QW1vdW50BQxyYXdGZWVBbW91bnQEE2Rpc3RyaWJ1dGVGZWVBbW91bnQDBRFpc0NvbGxhdGVyYWxBc3NldAQIZG9Cb3Jyb3cJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIGYm9ycm93CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFB19hbW91bnQFA25pbAMJAAACBQhkb0JvcnJvdwUIZG9Cb3Jyb3cEDWJhbGFuY2VCZWZvcmUJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDWJhbGFuY2VCZWZvcmUFDWJhbGFuY2VCZWZvcmUEBmRvU3dhcAkA/AcECQELc3dhcEFkZHJlc3MAAgRzd2FwCQDMCAIJANgEAQkBCnF1b3RlQXNzZXQACQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUMcmF3RmVlQW1vdW50BQNuaWwDCQAAAgUGZG9Td2FwBQZkb1N3YXAEDGJhbGFuY2VBZnRlcgkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUMYmFsYW5jZUFmdGVyBQxiYWxhbmNlQWZ0ZXIED2V4Y2hhbmdlZEFtb3VudAkAZQIFDGJhbGFuY2VBZnRlcgUNYmFsYW5jZUJlZm9yZQMJAAACBQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQxyYXdGZWVBbW91bnQDCQAAAgUTZGlzdHJpYnV0ZUZlZUFtb3VudAUTZGlzdHJpYnV0ZUZlZUFtb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACDWFjY2VwdFBheW1lbnQJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNjIyNjA2MjQwMAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjIyNjA2MjQwMAJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2MjI2MDYyNDAwAl8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDYyMjYwNjI0MDACXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjIyNjA2MjQwMAJfNAQNJHQwNjI0MDY2MjQ2MwkBDWRpc3RyaWJ1dGVGZWUBBQlmZWVBbW91bnQEDGZlZVRvU3Rha2VycwgFDSR0MDYyNDA2NjI0NjMCXzEECmZlZVRvVmF1bHQIBQ0kdDA2MjQwNjYyNDYzAl8yBAVzdGFrZQMFDGlzUXVvdGVBc3NldAQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAkAzAgCBwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQlmZWVBbW91bnQFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24FBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUJAGQCBRFvbGRQb3NpdGlvbk1hcmdpbgUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxyZW1vdmVNYXJnaW4BB19hbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgECH0ludmFsaWQgcmVtb3ZlTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDYzNTc1NjM3MTUJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDYzNTc1NjM3MTUCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjM1NzU2MzcxNQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2MzU3NTYzNzE1Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDYzNTc1NjM3MTUCXzQEC21hcmdpbkRlbHRhCQEBLQEFB19hbW91bnQEDSR0MDYzNzUyNjM5MzEJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC21hcmdpbkRlbHRhBAxyZW1haW5NYXJnaW4IBQ0kdDA2Mzc1MjYzOTMxAl8xBAdiYWREZWJ0CAUNJHQwNjM3NTI2MzkzMQJfMgMJAQIhPQIFB2JhZERlYnQAAAkAAgECHUludmFsaWQgcmVtb3ZlZCBtYXJnaW4gYW1vdW50BAttYXJnaW5SYXRpbwkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwULbWFyZ2luUmF0aW8JAQ9pbml0TWFyZ2luUmF0aW8ABgkAAgEJAKwCAgkArAICCQCsAgICGVRvbyBtdWNoIG1hcmdpbiByZW1vdmVkOiAJAKQDAQULbWFyZ2luUmF0aW8CAyA8IAkApAMBCQEPaW5pdE1hcmdpblJhdGlvAAQNcXVvdGVBc3NldFN0cgkA2AQBCQEKcXVvdGVBc3NldAAEDSR0MDY0Mzc1NjQ0MjkJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA2NDM3NTY0NDI5Al8xBAdhc3NldElkCAUNJHQwNjQzNzU2NDQyOQJfMgQHdG9SZXBheQMJAGYCBQdfYW1vdW50BQhib3Jyb3dlZAUIYm9ycm93ZWQFB19hbW91bnQECnRvV2l0aGRyYXcDCQBmAgUIYm9ycm93ZWQFB19hbW91bnQAAAkAZQIFB19hbW91bnQFCGJvcnJvd2VkBAtmaW5hbEJvcnJvdwkAZQIFCGJvcnJvd2VkBQd0b1JlcGF5BBVzd2l0Y2hQb3NpdGlvblRvUXVvdGUDCQBmAgULZmluYWxCb3Jyb3cAAAUDbmlsCQETdXBkYXRlUG9zaXRpb25Bc3NldAIFB190cmFkZXIFDXF1b3RlQXNzZXRTdHIEDWRvU2FuaXR5Q2hlY2sDCQECIT0CCQBkAgUHdG9SZXBheQUKdG9XaXRoZHJhdwUHX2Ftb3VudAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgh0b1JlcGF5PQkApAMBBQd0b1JlcGF5Ag4gKyB0b1dpdGhkcmF3PQkApAMBBQp0b1dpdGhkcmF3AgQgIT0gCQCkAwEFB19hbW91bnQFA25pbAMJAAACBQ1kb1Nhbml0eUNoZWNrBQ1kb1Nhbml0eUNoZWNrBAlkb1Vuc3Rha2UDCQBmAgUKdG9XaXRoZHJhdwAABAlkb1Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFCnRvV2l0aGRyYXcFA25pbAUDbmlsAwkAAAIFCWRvVW5zdGFrZQUJZG9VbnN0YWtlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQlkb1Vuc3Rha2UFCWRvVW5zdGFrZQQWcmV0dXJuQ29sbGF0ZXJhbEFjdGlvbgMJAGYCBQd0b1JlcGF5AAAEB2RvUmVwYXkJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIFcmVwYXkJAMwIAgUHX3RyYWRlcgkAzAgCBQd0b1JlcGF5CQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFB2RvUmVwYXkFB2RvUmVwYXkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQd0b1JlcGF5CQDZBAEFB2Fzc2V0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFnJldHVybkNvbGxhdGVyYWxBY3Rpb24FFnJldHVybkNvbGxhdGVyYWxBY3Rpb24JAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4FF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD29sZFBvc2l0aW9uU2l6ZQMJAGYCBQp0b1dpdGhkcmF3AAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUKdG9XaXRoZHJhdwUDbmlsCQENdXBkYXRlQmFsYW5jZQEJAGUCCQEIY2JhbGFuY2UABQdfYW1vdW50BRVzd2l0Y2hQb3NpdGlvblRvUXVvdGUFFnJldHVybkNvbGxhdGVyYWxBY3Rpb24JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY2xvc2VQb3NpdGlvbgIFX3NpemUUX21pblF1b3RlQXNzZXRBbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkEDl90cmFkZXJBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUHX3RyYWRlcgIOSW52YWxpZCBjYWxsZXIDAwMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAGcCAAAFBV9zaXplBgkAZgIAAAUUX21pblF1b3RlQXNzZXRBbW91bnQJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNjY1ODc2NjcyNwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjY1ODc2NjcyNwJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2NjU4NzY2NzI3Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY2NTg3NjY3MjcCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjY1ODc2NjcyNwJfNAQNJHQwNjY3MzM3MTE3MAMJAGYCCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBQVfc2l6ZQQKX2RpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAUJRElSX1NIT1JUBQhESVJfTE9ORwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQNJHQwNjczMjQ2NzU0NgkBCnN3YXBPdXRwdXQDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFBV9zaXplBgQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDY3MzI0Njc1NDYCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2NzMyNDY3NTQ2Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2NzMyNDY3NTQ2Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjczMjQ2NzU0NgJfNAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQEBLQEFBV9zaXplBQVfc2l6ZQQNJHQwNjc2Mzc2Nzc5MQkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNjc2Mzc2Nzc5MQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDY3NjM3Njc3OTECXzIEAm1yCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQNcmVhbGl6ZWRSYXRpbwkBBGRpdmQCCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBQ1yZWFsaXplZFJhdGlvBA0kdDA2ODA3MDY4MzA4CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBQtyZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwNjgwNzA2ODMwOAJfMQQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNjgwNzA2ODMwOAJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA2ODA3MDY4MzA4Al8zBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsBBFuZXdQb3NpdGlvbk1hcmdpbgkBBG11bGQCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUCbXIED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBBRuZXdQb3NpdGlvbkxzdFVwZENQRgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIFFF9taW5RdW90ZUFzc2V0QW1vdW50AAAJAGYCBRRfbWluUXVvdGVBc3NldEFtb3VudAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQCAyA8IAkApAMBBRRfbWluUXVvdGVBc3NldEFtb3VudAkAoQoPBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYFD3Bvc2l0aW9uQmFkRGVidAULcmVhbGl6ZWRQbmwJAGQCCQEDYWJzAQkAZQIFDHJlbWFpbk1hcmdpbgURbmV3UG9zaXRpb25NYXJnaW4FC3JlYWxpemVkUG5sBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEQb3BlbkludGVyZXN0TG9uZwADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQAAAMJAGYCBQVfc2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQkAAgECIEludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA3MDExMTcwNTMwCQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uAgUHX3RyYWRlcgYEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA3MDExMTcwNTMwAl8xBA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA3MDExMTcwNTMwAl8yBAtyZWFsaXplZFBubAgFDSR0MDcwMTExNzA1MzACXzMEDW1hcmdpblRvVmF1bHQIBQ0kdDA3MDExMTcwNTMwAl80BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzAxMTE3MDUzMAJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzAxMTE3MDUzMAJfNgQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDcwMTExNzA1MzACXzcEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MDExMTcwNTMwAl84BAJ4MggFDSR0MDcwMTExNzA1MzACXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzAxMTE3MDUzMANfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDcwMTExNzA1MzADXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDcwMTExNzA1MzADXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MDExMTcwNTMwA18xMwMDCQECIT0CBRRfbWluUXVvdGVBc3NldEFtb3VudAAACQBmAgUUX21pblF1b3RlQXNzZXRBbW91bnQFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQHCQACAQkArAICCQCsAgIJAKwCAgINTGltaXQgZXJyb3I6IAkApAMBBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AgMgPCAJAKQDAQUUX21pblF1b3RlQXNzZXRBbW91bnQJAKEKDwAAAAAAAAAABQ9wb3NpdGlvbkJhZERlYnQFC3JlYWxpemVkUG5sBQ1tYXJnaW5Ub1ZhdWx0BRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDY2NzMzNzExNzACXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNjY3MzM3MTE3MAJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2NjczMzcxMTcwAl8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY2NzMzNzExNzACXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDY2NzMzNzExNzACXzUEC3JlYWxpemVkUG5sCAUNJHQwNjY3MzM3MTE3MAJfNgQNbWFyZ2luVG9WYXVsdAgFDSR0MDY2NzMzNzExNzACXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2NjczMzcxMTcwAl84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2NjczMzcxMTcwAl85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjY3MzM3MTE3MANfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA2NjczMzcxMTcwA18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA2NjczMzcxMTcwA18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNjY3MzM3MTE3MANfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNjY3MzM3MTE3MANfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDY2NzMzNzExNzADXzE1AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAACQACAQImVW5hYmxlIHRvIGNsb3NlIHBvc2l0aW9uIHdpdGggYmFkIGRlYnQEDndpdGhkcmF3QW1vdW50CQEDYWJzAQUNbWFyZ2luVG9WYXVsdAQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA0kdDA3MTM3OTcxNTg2AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNYW1tTmV3QmFsYW5jZQgFDSR0MDcxMzc5NzE1ODYCXzEEA3gxMQgFDSR0MDcxMzc5NzE1ODYCXzIEDSR0MDcxNTkzNzE2NDcJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA3MTU5MzcxNjQ3Al8xBAdhc3NldElkCAUNJHQwNzE1OTM3MTY0NwJfMgQNJHQwNzE2NjI3MjUyMQMJAGYCBQhib3Jyb3dlZAAAAwkAZwIFDndpdGhkcmF3QW1vdW50BQhib3Jyb3dlZAQHZG9SZXBheQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgVyZXBheQkAzAgCBQdfdHJhZGVyCQDMCAIFCGJvcnJvd2VkCQDMCAIFB2Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFB2RvUmVwYXkFB2RvUmVwYXkJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ5fdHJhZGVyQWRkcmVzcwUIYm9ycm93ZWQJANkEAQUHYXNzZXRJZAUDbmlsCQBlAgUOd2l0aGRyYXdBbW91bnQFCGJvcnJvd2VkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIYcmVhbGl6ZVBhcnRpYWxseUFuZENsb3NlCQDMCAIFB190cmFkZXIJAMwIAgUOd2l0aGRyYXdBbW91bnQJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ5fdHJhZGVyQWRkcmVzcwUOd2l0aGRyYXdBbW91bnQJANkEAQUHYXNzZXRJZAUDbmlsAAAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAJQKAgUDbmlsBQ53aXRoZHJhd0Ftb3VudAMJAAACBQ0kdDA3MTY2MjcyNTIxBQ0kdDA3MTY2MjcyNTIxBBNxdW90ZVdpdGhkcmF3QW1vdW50CAUNJHQwNzE2NjI3MjUyMQJfMgQUc2VuZENvbGxhdGVyYWxBY3Rpb24IBQ0kdDA3MTY2MjcyNTIxAl8xBAd1bnN0YWtlAwkAZgIFE3F1b3RlV2l0aGRyYXdBbW91bnQAAAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUTcXVvdGVXaXRoZHJhd0Ftb3VudAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgMJAAACBQ9uZXdQb3NpdGlvblNpemUAAAkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyAwkAZgIFE3F1b3RlV2l0aGRyYXdBbW91bnQAAAkBCHdpdGhkcmF3AgUOX3RyYWRlckFkZHJlc3MFE3F1b3RlV2l0aGRyYXdBbW91bnQFA25pbAkBDXVwZGF0ZUJhbGFuY2UBBQ1hbW1OZXdCYWxhbmNlBRRzZW5kQ29sbGF0ZXJhbEFjdGlvbgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlsaXF1aWRhdGUBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQPc3BvdE1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQLbWFyZ2luUmF0aW8DCQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEEW9yYWNsZU1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFEVBOTF9PUFRJT05fT1JBQ0xFCQEEdm1heAIFD3Nwb3RNYXJnaW5SYXRpbwURb3JhY2xlTWFyZ2luUmF0aW8FD3Nwb3RNYXJnaW5SYXRpbwMDAwMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BBQdfdHJhZGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAJAAIBAhNVbmFibGUgdG8gbGlxdWlkYXRlAwMDCQBmAgUPc3BvdE1hcmdpblJhdGlvCQETbGlxdWlkYXRpb25GZWVSYXRpbwAJAGYCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AAAAHCQBmAgUMREVDSU1BTF9VTklUCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABwQNJHQwNzQ4MTg3NDk2OAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNzQ4MTg3NDk2OAJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA3NDgxODc0OTY4Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDc0ODE4NzQ5NjgCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNzQ4MTg3NDk2OAJfNAQKX2RpcmVjdGlvbgMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAUJRElSX1NIT1JUBQhESVJfTE9ORwQFaXNBZGQJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQQNJHQwNzUxOTM3NTI5NwkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNzUxOTM3NTI5NwJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDc1MTkzNzUyOTcCXzIEDSR0MDc1MzA1NzU0OTIJAQlzd2FwSW5wdXQCBQVpc0FkZAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCAUNJHQwNzUzMDU3NTQ5MgJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDc1MzA1NzU0OTICXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDc1MzA1NzU0OTICXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3NTMwNTc1NDkyAl80BBBsaXF1aWRhdGlvblJhdGlvCQEEZGl2ZAIJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEC3JlYWxpemVkUG5sCQEEbXVsZAIFDXVucmVhbGl6ZWRQbmwFEGxpcXVpZGF0aW9uUmF0aW8EDSR0MDc1NzgxNzYwMTQJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3NTc4MTc2MDE0Al8xBAdiYWREZWJ0CAUNJHQwNzU3ODE3NjAxNAJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3NTc4MTc2MDE0Al8zBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQEEmxpcXVpZGF0aW9uUGVuYWx0eQkBBG11bGQCBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQETbGlxdWlkYXRpb25GZWVSYXRpbwAED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IEEW5ld1Bvc2l0aW9uTWFyZ2luCQBlAgUMcmVtYWluTWFyZ2luBRJsaXF1aWRhdGlvblBlbmFsdHkED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAQUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNzcxODM3NzMxMgMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA3NzE4Mzc3MzEyAl8xBAN4MTEIBQ0kdDA3NzE4Mzc3MzEyAl8yBA0kdDA3NzMyMDc3Mzc0CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzczMjA3NzM3NAJfMQQHYXNzZXRJZAgFDSR0MDc3MzIwNzczNzQCXzIEFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAMJAGYCBQhib3Jyb3dlZAAABBBjb2xsYXRlcmFsVG9TZWxsCQEEbXVsZAIFCGJvcnJvd2VkBRBsaXF1aWRhdGlvblJhdGlvBA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIQcmVhbGl6ZVBhcnRpYWxseQkAzAgCBQdfdHJhZGVyCQDMCAIFB2Fzc2V0SWQJAMwIAgUQY29sbGF0ZXJhbFRvU2VsbAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBRJsaXF1aWRhdGlvblBlbmFsdHkFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQpmZWVUb1ZhdWx0BQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAABRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AAAJAGUCCQERb3BlbkludGVyZXN0U2hvcnQAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50AAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4EDSR0MDc5MDY5Nzk1NjQJARVpbnRlcm5hbENsb3NlUG9zaXRpb24CBQdfdHJhZGVyBwQCeDEIBQ0kdDA3OTA2OTc5NTY0Al8xBAdiYWREZWJ0CAUNJHQwNzkwNjk3OTU2NAJfMgQCeDIIBQ0kdDA3OTA2OTc5NTY0Al8zBAJ4MwgFDSR0MDc5MDY5Nzk1NjQCXzQEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3OTA2OTc5NTY0Al81BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3OTA2OTc5NTY0Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzkwNjk3OTU2NAJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDc5MDY5Nzk1NjQCXzgEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDA3OTA2OTc5NTY0Al85BA50b3RhbExvbmdBZnRlcggFDSR0MDc5MDY5Nzk1NjQDXzEwBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDA3OTA2OTc5NTY0A18xMQQadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3OTA2OTc5NTY0A18xMgQbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzkwNjk3OTU2NANfMTMEEmxpcXVpZGF0aW9uUGVuYWx0eQkBBG11bGQCBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQETbGlxdWlkYXRpb25GZWVSYXRpbwAED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDSR0MDc5OTcyODAxMDEDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1uZXdBbW1CYWxhbmNlCAUNJHQwNzk5NzI4MDEwMQJfMQQDeDExCAUNJHQwNzk5NzI4MDEwMQJfMgQNJHQwODAxMDk4MDE2MwkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDgwMTA5ODAxNjMCXzEEB2Fzc2V0SWQIBQ0kdDA4MDEwOTgwMTYzAl8yBBVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwDCQBmAgUIYm9ycm93ZWQAAAQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACGHJlYWxpemVQYXJ0aWFsbHlBbmRDbG9zZQkAzAgCBQdfdHJhZGVyCQDMCAIAAAkAzAgCBQdhc3NldElkBQNuaWwFA25pbAMJAAACBQ9yZWFsaXplQW5kQ2xvc2UFD3JlYWxpemVBbmRDbG9zZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwEAXgDCQBmAgUHYmFkRGVidAAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFB2JhZERlYnQFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUBeAUBeAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQEOZGVsZXRlUG9zaXRpb24BBQdfdHJhZGVyCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAAAwMDCQBmAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQkArAICCQCsAgIJAKwCAgIhSW52YWxpZCBmdW5kaW5nIGJsb2NrIHRpbWVzdGFtcDogCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgMgPCAJAKQDAQUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wBA91bmRlcmx5aW5nUHJpY2UJARJnZXRPcmFjbGVUd2FwUHJpY2UABA0kdDA4MjAzOTgyMTAxCQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwODIwMzk4MjEwMQJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDgyMDM5ODIxMDECXzIJAQ11cGRhdGVGdW5kaW5nBQkAZAIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAZAIJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFE2xvbmdQcmVtaXVtRnJhY3Rpb24JAGQCCQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQAEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQNJHQwODI1MzM4MjY3MgkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBEmdldE9yYWNsZVR3YXBQcmljZQAFB19xdEFzdFIFB19ic0FzdFIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA4MjUzMzgyNjcyAl8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA4MjUzMzgyNjcyAl8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwODI1MzM4MjY3MgJfMwQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFDW1hcmdpblRvVmF1bHQAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFDW1hcmdpblRvVmF1bHQFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAQphcHBlbmRUd2FwAQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFE25ld1F1b3RlQXNzZXRXZWlnaHQJAQRtdWxkAgUHX2JzQXN0UgUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBJ3ZpZXdfY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA0kdDA4MzI0MTgzMzQyCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDA4MzI0MTgzMzQyAl8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDgzMjQxODMzNDICXzIEA3BvbggFDSR0MDgzMjQxODMzNDICXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwODMyNDE4MzM0MgJfNAQNJHQwODMzNDU4MzQ0NgkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBBwb3NpdGlvbk5vdGlvbmFsCAUNJHQwODMzNDU4MzQ0NgJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDgzMzQ1ODM0NDYCXzIEDSR0MDgzNDQ5ODM2MjEJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDgzNDQ5ODM2MjECXzEEB2JhZERlYnQIBQ0kdDA4MzQ0OTgzNjIxAl8yBA5mdW5kaW5nUGF5bWVudAgFDSR0MDgzNDQ5ODM2MjECXzMJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkBAXMBBQxyZW1haW5NYXJnaW4JAQFzAQUOZnVuZGluZ1BheW1lbnQJAQFzAQkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkBAXMBBQ11bnJlYWxpemVkUG5sCQEBcwEFB2JhZERlYnQJAQFzAQUQcG9zaXRpb25Ob3Rpb25hbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARV2aWV3X2dldFBlZ0FkanVzdENvc3QBBl9wcmljZQQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAZyZXN1bHQJARRnZXRTeW5jVGVybWluYWxQcmljZQMFBl9wcmljZQUHX3F0QXN0UgUHX2JzQXN0UgkAAgEJAKQDAQgFBnJlc3VsdAJfMwFpARh2aWV3X2dldFRlcm1pbmFsQW1tUHJpY2UABA0kdDA4NDAzNzg0MTE4CQETZ2V0VGVybWluYWxBbW1TdGF0ZQAEGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUIBQ0kdDA4NDAzNzg0MTE4Al8xBBh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUIBQ0kdDA4NDAzNzg0MTE4Al8yBAVwcmljZQkBBGRpdmQCCQEEbXVsZAIFGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFcACQEEbXVsZAIFGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0VwAJAAIBCQCkAwEFBXByaWNlAWkBD3ZpZXdfZ2V0RnVuZGluZwAED3VuZGVybHlpbmdQcmljZQkBEmdldE9yYWNsZVR3YXBQcmljZQAEDSR0MDg0MzM3ODQzOTkJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4NDMzNzg0Mzk5Al8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODQzMzc4NDM5OQJfMgQLbG9uZ0Z1bmRpbmcJAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlBAxzaG9ydEZ1bmRpbmcJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgEJAKwCAgkArAICCQCsAgIJAQFzAQULbG9uZ0Z1bmRpbmcJAQFzAQUMc2hvcnRGdW5kaW5nCQEBcwEJARBnZXRUd2FwU3BvdFByaWNlAAkBAXMBCQESZ2V0T3JhY2xlVHdhcFByaWNlAAFpARh2aWV3X2dldEJvcnJvd2VkQnlUcmFkZXIBB190cmFkZXIEDSR0MDg0Njg5ODQ3NDMJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA4NDY4OTg0NzQzAl8xBAdhc3NldElkCAUNJHQwODQ2ODk4NDc0MwJfMgkAAgEJAKwCAgkBAXMBBQhib3Jyb3dlZAUHYXNzZXRJZAFpARBjb21wdXRlU3BvdFByaWNlAAQGcmVzdWx0CQEMZ2V0U3BvdFByaWNlAAkAlAoCBQNuaWwFBnJlc3VsdAFpAR9jb21wdXRlRmVlRm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBAZyZXN1bHQJARhnZXRGb3JUcmFkZXJXaXRoQXJ0aWZhY3QCBQdfdHJhZGVyBQtfYXJ0aWZhY3RJZAkAlAoCBQNuaWwFBnJlc3VsdAECdHgBBnZlcmlmeQAJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAJAQ5hZG1pblB1YmxpY0tleQDCYRmU", "height": 2362899, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: JBA1KTNeUyLdcDHMzXpF3BQAQYAKx6yTHPwhje5aRjqU Next: 9z9TFTBnoasCLfXLbbqzQAUcMB9977wx9Xv4zUG8Kvdu Diff:
OldNewDifferences
553553 }
554554
555555
556+func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
557+ let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
558+ let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
559+ let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
560+ absPriceDiff
561+ }
562+
563+
556564 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
557565 let oraclePrice = getOracleTwapPrice()
558566 let _qtAstW = qtAstW()
559567 let _bsAstW = bsAstW()
560- let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
561- let averagePrice = divd((oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
562- let absPriceDiff = divd(abs((oraclePrice - priceAfter)), averagePrice)
563- if ((absPriceDiff > maxPriceSpread()))
564- then throw(((("Price spread " + toString(absPriceDiff)) + " > max price spread ") + toString(maxPriceSpread())))
568+ let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
569+ let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
570+ if (if ((absPriceDiffAfter > maxPriceSpread()))
571+ then (absPriceDiffAfter > absPriceDiffBefore)
572+ else false)
573+ then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
565574 else true
566575 }
567576
597606 let isShort = (0 > _positionSize)
598607 let positionNotional = if ((_option == PNL_OPTION_SPOT))
599608 then {
600- let $t02423124451 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
601- let outPositionNotional = $t02423124451._1
602- let x1 = $t02423124451._2
603- let x2 = $t02423124451._3
604- let x3 = $t02423124451._4
609+ let $t02463524855 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
610+ let outPositionNotional = $t02463524855._1
611+ let x1 = $t02463524855._2
612+ let x2 = $t02463524855._3
613+ let x3 = $t02463524855._4
605614 outPositionNotional
606615 }
607616 else muld(positionSizeAbs, getOracleTwapPrice())
622631
623632
624633 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
625- let $t02587626004 = getPosition(_trader)
626- let positionSize = $t02587626004._1
627- let positionMargin = $t02587626004._2
628- let positionOpenNotional = $t02587626004._3
629- let positionLstUpdCPF = $t02587626004._4
634+ let $t02628026408 = getPosition(_trader)
635+ let positionSize = $t02628026408._1
636+ let positionMargin = $t02628026408._2
637+ let positionOpenNotional = $t02628026408._3
638+ let positionLstUpdCPF = $t02628026408._4
630639 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
631640 }
632641
635644
636645
637646 func getMarginRatioByOption (_trader,_option) = {
638- let $t02651726628 = getPosition(_trader)
639- let positionSize = $t02651726628._1
640- let positionMargin = $t02651726628._2
641- let pon = $t02651726628._3
642- let positionLstUpdCPF = $t02651726628._4
643- let $t02663426727 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
644- let positionNotional = $t02663426727._1
645- let unrealizedPnl = $t02663426727._2
646- let $t02673226898 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
647- let remainMargin = $t02673226898._1
648- let badDebt = $t02673226898._2
647+ let $t02692127032 = getPosition(_trader)
648+ let positionSize = $t02692127032._1
649+ let positionMargin = $t02692127032._2
650+ let pon = $t02692127032._3
651+ let positionLstUpdCPF = $t02692127032._4
652+ let $t02703827131 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
653+ let positionNotional = $t02703827131._1
654+ let unrealizedPnl = $t02703827131._2
655+ let $t02713627302 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
656+ let remainMargin = $t02713627302._1
657+ let badDebt = $t02713627302._2
649658 calcMarginRatio(remainMargin, badDebt, positionNotional)
650659 }
651660
670679
671680
672681 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
673- let $t02813828266 = getPosition(_trader)
674- let positionSize = $t02813828266._1
675- let positionMargin = $t02813828266._2
676- let positionOpenNotional = $t02813828266._3
677- let positionLstUpdCPF = $t02813828266._4
682+ let $t02854228670 = getPosition(_trader)
683+ let positionSize = $t02854228670._1
684+ let positionMargin = $t02854228670._2
685+ let positionOpenNotional = $t02854228670._3
686+ let positionLstUpdCPF = $t02854228670._4
678687 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
679- let $t02836128529 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
680- let remainMargin = $t02836128529._1
681- let badDebt = $t02836128529._2
688+ let $t02876528933 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
689+ let remainMargin = $t02876528933._1
690+ let badDebt = $t02876528933._2
682691 let exchangedPositionSize = -(positionSize)
683692 let realizedPnl = unrealizedPnl
684693 let marginToVault = -(remainMargin)
685- let $t02865628930 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
686- let exchangedQuoteAssetAmount = $t02865628930._1
687- let quoteAssetReserveAfter = $t02865628930._2
688- let baseAssetReserveAfter = $t02865628930._3
689- let totalPositionSizeAfter = $t02865628930._4
690- let totalLongAfter = $t02865628930._5
691- let totalShortAfter = $t02865628930._6
694+ let $t02906029334 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
695+ let exchangedQuoteAssetAmount = $t02906029334._1
696+ let quoteAssetReserveAfter = $t02906029334._2
697+ let baseAssetReserveAfter = $t02906029334._3
698+ let totalPositionSizeAfter = $t02906029334._4
699+ let totalLongAfter = $t02906029334._5
700+ let totalShortAfter = $t02906029334._6
692701 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
693702 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
694703 then positionOpenNotional
741750 then $Tuple2(qtAstR(), bsAstR())
742751 else {
743752 let direction = (_positionSize > 0)
744- let $t03105331232 = swapOutput(direction, abs(_positionSize), false)
745- let currentNetMarketValue = $t03105331232._1
746- let terminalQuoteAssetReserve = $t03105331232._2
747- let terminalBaseAssetReserve = $t03105331232._3
753+ let $t03145731636 = swapOutput(direction, abs(_positionSize), false)
754+ let currentNetMarketValue = $t03145731636._1
755+ let terminalQuoteAssetReserve = $t03145731636._2
756+ let terminalBaseAssetReserve = $t03145731636._3
748757 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
749758 }
750759 }
768777 }
769778
770779
771-func getSyncTerminalPrice (_terminalPrice) = {
780+func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
772781 let _positionSize = totalPositionSize()
773782 if ((_positionSize == 0))
774783 then {
775- let _qtAstR = qtAstR()
776- let _bsAstR = bsAstR()
777784 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
778785 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
779786 }
780787 else {
781788 let direction = (_positionSize > 0)
782789 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
783- let _qtAstR = qtAstR()
784- let _bsAstR = bsAstR()
785790 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
786791 let newBsAstW = DECIMAL_UNIT
787792 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
815820 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
816821 let baseFeeRaw = fee()
817822 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
818- let $t03433134826 = if ((_artifactId != ""))
823+ let $t03465535150 = if ((_artifactId != ""))
819824 then {
820825 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
821826 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
827832 else throw("Invalid attached artifact")
828833 }
829834 else $Tuple2(baseFee, false)
830- let adjustedFee = $t03433134826._1
831- let burnArtifact = $t03433134826._2
835+ let adjustedFee = $t03465535150._1
836+ let burnArtifact = $t03465535150._2
832837 $Tuple2(adjustedFee, burnArtifact)
833838 }
834839
869874 case _ =>
870875 throw("Invalid computeFeeDiscount result")
871876 }
872- let $t03605736131 = getAdjustedFee(_artifactId, feeDiscount)
873- let adjustedFee = $t03605736131._1
874- let burnArtifact = $t03605736131._2
877+ let $t03638136455 = getAdjustedFee(_artifactId, feeDiscount)
878+ let adjustedFee = $t03638136455._1
879+ let burnArtifact = $t03638136455._2
875880 $Tuple2(adjustedFee, burnArtifact)
876881 }
877882 else throw("Strict value is not equal to itself.")
10191024 let _qtAstW = qtAstW()
10201025 let _bsAstW = bsAstW()
10211026 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
1022- let baseAssetAmountToAdd = divd(_quoteAssetAmount, price)
10231027 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
1028+ let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10241029 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1025- updateAmmReserves(qtAstRAfter, bsAstRAfter)
1030+ let $t04547745632 = getSyncTerminalPrice(getOracleTwapPrice(), qtAstRAfter, bsAstRAfter)
1031+ let newQuoteAssetWeight = $t04547745632._1
1032+ let newBaseAssetWeight = $t04547745632._2
1033+ let marginToVault = $t04547745632._3
1034+ let doExchangePnL = if ((marginToVault != 0))
1035+ then {
1036+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
1037+ if ((doExchangePnL == doExchangePnL))
1038+ then nil
1039+ else throw("Strict value is not equal to itself.")
1040+ }
1041+ else nil
1042+ if ((doExchangePnL == doExchangePnL))
1043+ then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1044+ else throw("Strict value is not equal to itself.")
10261045 }
10271046
10281047
11071126 else paused())
11081127 then throw("Invalid decreasePosition parameters")
11091128 else {
1110- let $t04867048810 = getPosition(_trader)
1111- let oldPositionSize = $t04867048810._1
1112- let oldPositionMargin = $t04867048810._2
1113- let oldPositionOpenNotional = $t04867048810._3
1114- let oldPositionLstUpdCPF = $t04867048810._4
1129+ let $t04947549615 = getPosition(_trader)
1130+ let oldPositionSize = $t04947549615._1
1131+ let oldPositionMargin = $t04947549615._2
1132+ let oldPositionOpenNotional = $t04947549615._3
1133+ let oldPositionLstUpdCPF = $t04947549615._4
11151134 let _direction = if ((oldPositionSize > 0))
11161135 then DIR_SHORT
11171136 else DIR_LONG
11181137 let isAdd = (_direction == DIR_LONG)
11191138 let openNotional = muld(_amount, _leverage)
1120- let $t04898349087 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1121- let oldPositionNotional = $t04898349087._1
1122- let unrealizedPnl = $t04898349087._2
1123- let $t04909351751 = if ((oldPositionNotional > openNotional))
1139+ let $t04978849892 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1140+ let oldPositionNotional = $t04978849892._1
1141+ let unrealizedPnl = $t04978849892._2
1142+ let $t04989852556 = if ((oldPositionNotional > openNotional))
11241143 then {
1125- let $t04950849692 = swapInput(isAdd, openNotional)
1126- let exchangedPositionSize = $t04950849692._1
1127- let quoteAssetReserveAfter = $t04950849692._2
1128- let baseAssetReserveAfter = $t04950849692._3
1129- let totalPositionSizeAfter = $t04950849692._4
1144+ let $t05031350497 = swapInput(isAdd, openNotional)
1145+ let exchangedPositionSize = $t05031350497._1
1146+ let quoteAssetReserveAfter = $t05031350497._2
1147+ let baseAssetReserveAfter = $t05031350497._3
1148+ let totalPositionSizeAfter = $t05031350497._4
11301149 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
11311150 if (if ((_minBaseAssetAmount != 0))
11321151 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
11341153 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
11351154 else {
11361155 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1137- let $t05012950374 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1138- let remainMargin = $t05012950374._1
1139- let badDebt = $t05012950374._2
1140- let fundingPayment = $t05012950374._3
1156+ let $t05093451179 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1157+ let remainMargin = $t05093451179._1
1158+ let badDebt = $t05093451179._2
1159+ let fundingPayment = $t05093451179._3
11411160 let exchangedQuoteAssetAmount = openNotional
11421161 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11431162 let remainOpenNotional = if ((oldPositionSize > 0))
11561175 }
11571176 }
11581177 else throw("Close position first")
1159- let newPositionSize = $t04909351751._1
1160- let newPositionRemainMargin = $t04909351751._2
1161- let newPositionOpenNotional = $t04909351751._3
1162- let newPositionLatestCPF = $t04909351751._4
1163- let baseAssetReserveAfter = $t04909351751._5
1164- let quoteAssetReserveAfter = $t04909351751._6
1165- let totalPositionSizeAfter = $t04909351751._7
1166- let openInterestNotionalAfter = $t04909351751._8
1167- let totalLongAfter = $t04909351751._9
1168- let totalShortAfter = $t04909351751._10
1169- let totalLongOpenInterestAfter = $t04909351751._11
1170- let totalShortOpenInterestAfter = $t04909351751._12
1178+ let newPositionSize = $t04989852556._1
1179+ let newPositionRemainMargin = $t04989852556._2
1180+ let newPositionOpenNotional = $t04989852556._3
1181+ let newPositionLatestCPF = $t04989852556._4
1182+ let baseAssetReserveAfter = $t04989852556._5
1183+ let quoteAssetReserveAfter = $t04989852556._6
1184+ let totalPositionSizeAfter = $t04989852556._7
1185+ let openInterestNotionalAfter = $t04989852556._8
1186+ let totalLongAfter = $t04989852556._9
1187+ let totalShortAfter = $t04989852556._10
1188+ let totalLongOpenInterestAfter = $t04989852556._11
1189+ let totalShortOpenInterestAfter = $t04989852556._12
11711190 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
11721191 if ((notifyNotional == notifyNotional))
11731192 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
12111230 else closeOnly())
12121231 then throw("Invalid increasePosition parameters")
12131232 else {
1214- let $t05318953274 = getForTraderWithArtifact(_trader, getArtifactId(i))
1215- let adjustedFee = $t05318953274._1
1216- let burnArtifact = $t05318953274._2
1233+ let $t05399454079 = getForTraderWithArtifact(_trader, getArtifactId(i))
1234+ let adjustedFee = $t05399454079._1
1235+ let burnArtifact = $t05399454079._2
12171236 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12181237 let _amount = (_rawAmount - rawFeeAmount)
12191238 let distributeFeeAmount = if (isCollateralAsset)
12561275 throw("Invalid referrerFee")
12571276 }
12581277 let feeAmount = (distributeFeeAmount - referrerFee)
1259- let $t05459054730 = getPosition(_trader)
1260- let oldPositionSize = $t05459054730._1
1261- let oldPositionMargin = $t05459054730._2
1262- let oldPositionOpenNotional = $t05459054730._3
1263- let oldPositionLstUpdCPF = $t05459054730._4
1278+ let $t05539555535 = getPosition(_trader)
1279+ let oldPositionSize = $t05539555535._1
1280+ let oldPositionMargin = $t05539555535._2
1281+ let oldPositionOpenNotional = $t05539555535._3
1282+ let oldPositionLstUpdCPF = $t05539555535._4
12641283 let isNewPosition = (oldPositionSize == 0)
12651284 let isSameDirection = if ((oldPositionSize > 0))
12661285 then (_direction == DIR_LONG)
12691288 then isSameDirection
12701289 else false
12711290 let isAdd = (_direction == DIR_LONG)
1272- let $t05501958060 = if (if (isNewPosition)
1291+ let $t05582458865 = if (if (isNewPosition)
12731292 then true
12741293 else expandExisting)
12751294 then {
12761295 let openNotional = muld(_amount, _leverage)
1277- let $t05548155654 = swapInput(isAdd, openNotional)
1278- let amountBaseAssetBought = $t05548155654._1
1279- let quoteAssetReserveAfter = $t05548155654._2
1280- let baseAssetReserveAfter = $t05548155654._3
1281- let totalPositionSizeAfter = $t05548155654._4
1296+ let $t05628656459 = swapInput(isAdd, openNotional)
1297+ let amountBaseAssetBought = $t05628656459._1
1298+ let quoteAssetReserveAfter = $t05628656459._2
1299+ let baseAssetReserveAfter = $t05628656459._3
1300+ let totalPositionSizeAfter = $t05628656459._4
12821301 if (if ((_minBaseAssetAmount != 0))
12831302 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12841303 else false)
12921311 then openNotional
12931312 else 0))
12941313 let increaseMarginRequirement = divd(openNotional, _leverage)
1295- let $t05626256501 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1296- let remainMargin = $t05626256501._1
1297- let x1 = $t05626256501._2
1298- let x2 = $t05626256501._3
1314+ let $t05706757306 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1315+ let remainMargin = $t05706757306._1
1316+ let x1 = $t05706757306._2
1317+ let x2 = $t05706757306._3
12991318 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13001319 then throw("Over max spread limit")
13011320 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13091328 }
13101329 else {
13111330 let openNotional = muld(_amount, _leverage)
1312- let $t05776057876 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1313- let oldPositionNotional = $t05776057876._1
1314- let unrealizedPnl = $t05776057876._2
1331+ let $t05856558681 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1332+ let oldPositionNotional = $t05856558681._1
1333+ let unrealizedPnl = $t05856558681._2
13151334 if ((oldPositionNotional > openNotional))
13161335 then throw("Use decreasePosition to decrease position size")
13171336 else throw("Close position first")
13181337 }
1319- let newPositionSize = $t05501958060._1
1320- let newPositionRemainMargin = $t05501958060._2
1321- let newPositionOpenNotional = $t05501958060._3
1322- let newPositionLatestCPF = $t05501958060._4
1323- let baseAssetReserveAfter = $t05501958060._5
1324- let quoteAssetReserveAfter = $t05501958060._6
1325- let totalPositionSizeAfter = $t05501958060._7
1326- let openInterestNotionalAfter = $t05501958060._8
1327- let totalLongAfter = $t05501958060._9
1328- let totalShortAfter = $t05501958060._10
1329- let totalLongOpenInterestAfter = $t05501958060._11
1330- let totalShortOpenInterestAfter = $t05501958060._12
1331- let $t05806658123 = distributeFee(feeAmount)
1332- let feeToStakers = $t05806658123._1
1333- let feeToVault = $t05806658123._2
1338+ let newPositionSize = $t05582458865._1
1339+ let newPositionRemainMargin = $t05582458865._2
1340+ let newPositionOpenNotional = $t05582458865._3
1341+ let newPositionLatestCPF = $t05582458865._4
1342+ let baseAssetReserveAfter = $t05582458865._5
1343+ let quoteAssetReserveAfter = $t05582458865._6
1344+ let totalPositionSizeAfter = $t05582458865._7
1345+ let openInterestNotionalAfter = $t05582458865._8
1346+ let totalLongAfter = $t05582458865._9
1347+ let totalShortAfter = $t05582458865._10
1348+ let totalLongOpenInterestAfter = $t05582458865._11
1349+ let totalShortOpenInterestAfter = $t05582458865._12
1350+ let $t05887158928 = distributeFee(feeAmount)
1351+ let feeToStakers = $t05887158928._1
1352+ let feeToVault = $t05887158928._2
13341353 let stake = if (isQuoteAsset)
13351354 then {
13361355 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13941413 else closeOnly())
13951414 then throw("Invalid addMargin parameters")
13961415 else {
1397- let $t06007160156 = getForTraderWithArtifact(_trader, getArtifactId(i))
1398- let adjustedFee = $t06007160156._1
1399- let burnArtifact = $t06007160156._2
1416+ let $t06087660961 = getForTraderWithArtifact(_trader, getArtifactId(i))
1417+ let adjustedFee = $t06087660961._1
1418+ let burnArtifact = $t06087660961._2
14001419 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14011420 let _amount = (_rawAmount - rawFeeAmount)
14021421 let distributeFeeAmount = if (isCollateralAsset)
14391458 throw("Invalid referrerFee")
14401459 }
14411460 let feeAmount = (distributeFeeAmount - referrerFee)
1442- let $t06145561595 = getPosition(_trader)
1443- let oldPositionSize = $t06145561595._1
1444- let oldPositionMargin = $t06145561595._2
1445- let oldPositionOpenNotional = $t06145561595._3
1446- let oldPositionLstUpdCPF = $t06145561595._4
1447- let $t06160161658 = distributeFee(feeAmount)
1448- let feeToStakers = $t06160161658._1
1449- let feeToVault = $t06160161658._2
1461+ let $t06226062400 = getPosition(_trader)
1462+ let oldPositionSize = $t06226062400._1
1463+ let oldPositionMargin = $t06226062400._2
1464+ let oldPositionOpenNotional = $t06226062400._3
1465+ let oldPositionLstUpdCPF = $t06226062400._4
1466+ let $t06240662463 = distributeFee(feeAmount)
1467+ let feeToStakers = $t06240662463._1
1468+ let feeToVault = $t06240662463._2
14501469 let stake = if (isQuoteAsset)
14511470 then {
14521471 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
14941513 else paused())
14951514 then throw("Invalid removeMargin parameters")
14961515 else {
1497- let $t06277062910 = getPosition(_trader)
1498- let oldPositionSize = $t06277062910._1
1499- let oldPositionMargin = $t06277062910._2
1500- let oldPositionOpenNotional = $t06277062910._3
1501- let oldPositionLstUpdCPF = $t06277062910._4
1516+ let $t06357563715 = getPosition(_trader)
1517+ let oldPositionSize = $t06357563715._1
1518+ let oldPositionMargin = $t06357563715._2
1519+ let oldPositionOpenNotional = $t06357563715._3
1520+ let oldPositionLstUpdCPF = $t06357563715._4
15021521 let marginDelta = -(_amount)
1503- let $t06294763126 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1504- let remainMargin = $t06294763126._1
1505- let badDebt = $t06294763126._2
1522+ let $t06375263931 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1523+ let remainMargin = $t06375263931._1
1524+ let badDebt = $t06375263931._2
15061525 if ((badDebt != 0))
15071526 then throw("Invalid removed margin amount")
15081527 else {
15111530 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15121531 else {
15131532 let quoteAssetStr = toBase58String(quoteAsset())
1514- let $t06357063624 = getBorrowedByTrader(_trader)
1515- let borrowed = $t06357063624._1
1516- let assetId = $t06357063624._2
1533+ let $t06437564429 = getBorrowedByTrader(_trader)
1534+ let borrowed = $t06437564429._1
1535+ let assetId = $t06437564429._2
15171536 let toRepay = if ((_amount > borrowed))
15181537 then borrowed
15191538 else _amount
15831602 else (0 > _minQuoteAssetAmount))
15841603 then throw("Invalid closePosition parameters")
15851604 else {
1586- let $t06578265922 = getPosition(_trader)
1587- let oldPositionSize = $t06578265922._1
1588- let oldPositionMargin = $t06578265922._2
1589- let oldPositionOpenNotional = $t06578265922._3
1590- let oldPositionLstUpdCPF = $t06578265922._4
1591- let $t06592870365 = if ((abs(oldPositionSize) > _size))
1605+ let $t06658766727 = getPosition(_trader)
1606+ let oldPositionSize = $t06658766727._1
1607+ let oldPositionMargin = $t06658766727._2
1608+ let oldPositionOpenNotional = $t06658766727._3
1609+ let oldPositionLstUpdCPF = $t06658766727._4
1610+ let $t06673371170 = if ((abs(oldPositionSize) > _size))
15921611 then {
15931612 let _direction = if ((oldPositionSize > 0))
15941613 then DIR_SHORT
15951614 else DIR_LONG
15961615 let isAdd = (_direction == DIR_LONG)
1597- let $t06651966741 = swapOutput((oldPositionSize > 0), _size, true)
1598- let exchangedQuoteAssetAmount = $t06651966741._1
1599- let quoteAssetReserveAfter = $t06651966741._2
1600- let baseAssetReserveAfter = $t06651966741._3
1601- let totalPositionSizeAfter = $t06651966741._4
1616+ let $t06732467546 = swapOutput((oldPositionSize > 0), _size, true)
1617+ let exchangedQuoteAssetAmount = $t06732467546._1
1618+ let quoteAssetReserveAfter = $t06732467546._2
1619+ let baseAssetReserveAfter = $t06732467546._3
1620+ let totalPositionSizeAfter = $t06732467546._4
16021621 let exchangedPositionSize = if ((oldPositionSize > 0))
16031622 then -(_size)
16041623 else _size
1605- let $t06683266986 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1606- let oldPositionNotional = $t06683266986._1
1607- let unrealizedPnl = $t06683266986._2
1624+ let $t06763767791 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1625+ let oldPositionNotional = $t06763767791._1
1626+ let unrealizedPnl = $t06763767791._2
16081627 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16091628 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16101629 let realizedPnl = muld(unrealizedPnl, realizedRatio)
1611- let $t06726567503 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1612- let remainMargin = $t06726567503._1
1613- let positionBadDebt = $t06726567503._2
1614- let fundingPayment = $t06726567503._3
1630+ let $t06807068308 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1631+ let remainMargin = $t06807068308._1
1632+ let positionBadDebt = $t06807068308._2
1633+ let fundingPayment = $t06807068308._3
16151634 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16161635 let remainOpenNotional = if ((oldPositionSize > 0))
16171636 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16381657 else if ((_size > abs(oldPositionSize)))
16391658 then throw("Invalid closePosition parameters")
16401659 else {
1641- let $t06930669725 = internalClosePosition(_trader, true)
1642- let exchangedQuoteAssetAmount = $t06930669725._1
1643- let positionBadDebt = $t06930669725._2
1644- let realizedPnl = $t06930669725._3
1645- let marginToVault = $t06930669725._4
1646- let quoteAssetReserveAfter = $t06930669725._5
1647- let baseAssetReserveAfter = $t06930669725._6
1648- let totalPositionSizeAfter = $t06930669725._7
1649- let openInterestNotionalAfter = $t06930669725._8
1650- let x2 = $t06930669725._9
1651- let totalLongAfter = $t06930669725._10
1652- let totalShortAfter = $t06930669725._11
1653- let totalLongOpenInterestAfter = $t06930669725._12
1654- let totalShortOpenInterestAfter = $t06930669725._13
1660+ let $t07011170530 = internalClosePosition(_trader, true)
1661+ let exchangedQuoteAssetAmount = $t07011170530._1
1662+ let positionBadDebt = $t07011170530._2
1663+ let realizedPnl = $t07011170530._3
1664+ let marginToVault = $t07011170530._4
1665+ let quoteAssetReserveAfter = $t07011170530._5
1666+ let baseAssetReserveAfter = $t07011170530._6
1667+ let totalPositionSizeAfter = $t07011170530._7
1668+ let openInterestNotionalAfter = $t07011170530._8
1669+ let x2 = $t07011170530._9
1670+ let totalLongAfter = $t07011170530._10
1671+ let totalShortAfter = $t07011170530._11
1672+ let totalLongOpenInterestAfter = $t07011170530._12
1673+ let totalShortOpenInterestAfter = $t07011170530._13
16551674 if (if ((_minQuoteAssetAmount != 0))
16561675 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16571676 else false)
16581677 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
16591678 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
16601679 }
1661- let newPositionSize = $t06592870365._1
1662- let newPositionMargin = $t06592870365._2
1663- let newPositionOpenNotional = $t06592870365._3
1664- let newPositionLstUpdCPF = $t06592870365._4
1665- let positionBadDebt = $t06592870365._5
1666- let realizedPnl = $t06592870365._6
1667- let marginToVault = $t06592870365._7
1668- let quoteAssetReserveAfter = $t06592870365._8
1669- let baseAssetReserveAfter = $t06592870365._9
1670- let totalPositionSizeAfter = $t06592870365._10
1671- let openInterestNotionalAfter = $t06592870365._11
1672- let totalLongAfter = $t06592870365._12
1673- let totalShortAfter = $t06592870365._13
1674- let totalLongOpenInterestAfter = $t06592870365._14
1675- let totalShortOpenInterestAfter = $t06592870365._15
1680+ let newPositionSize = $t06673371170._1
1681+ let newPositionMargin = $t06673371170._2
1682+ let newPositionOpenNotional = $t06673371170._3
1683+ let newPositionLstUpdCPF = $t06673371170._4
1684+ let positionBadDebt = $t06673371170._5
1685+ let realizedPnl = $t06673371170._6
1686+ let marginToVault = $t06673371170._7
1687+ let quoteAssetReserveAfter = $t06673371170._8
1688+ let baseAssetReserveAfter = $t06673371170._9
1689+ let totalPositionSizeAfter = $t06673371170._10
1690+ let openInterestNotionalAfter = $t06673371170._11
1691+ let totalLongAfter = $t06673371170._12
1692+ let totalShortAfter = $t06673371170._13
1693+ let totalLongOpenInterestAfter = $t06673371170._14
1694+ let totalShortOpenInterestAfter = $t06673371170._15
16761695 if ((positionBadDebt > 0))
16771696 then throw("Unable to close position with bad debt")
16781697 else {
16791698 let withdrawAmount = abs(marginToVault)
16801699 let ammBalance = (cbalance() - withdrawAmount)
1681- let $t07057470781 = if ((0 > ammBalance))
1700+ let $t07137971586 = if ((0 > ammBalance))
16821701 then $Tuple2(0, abs(ammBalance))
16831702 else $Tuple2(ammBalance, 0)
1684- let ammNewBalance = $t07057470781._1
1685- let x11 = $t07057470781._2
1686- let $t07078870842 = getBorrowedByTrader(_trader)
1687- let borrowed = $t07078870842._1
1688- let assetId = $t07078870842._2
1689- let $t07085771716 = if ((borrowed > 0))
1703+ let ammNewBalance = $t07137971586._1
1704+ let x11 = $t07137971586._2
1705+ let $t07159371647 = getBorrowedByTrader(_trader)
1706+ let borrowed = $t07159371647._1
1707+ let assetId = $t07159371647._2
1708+ let $t07166272521 = if ((borrowed > 0))
16901709 then if ((withdrawAmount >= borrowed))
16911710 then {
16921711 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
17011720 else throw("Strict value is not equal to itself.")
17021721 }
17031722 else $Tuple2(nil, withdrawAmount)
1704- if (($t07085771716 == $t07085771716))
1723+ if (($t07166272521 == $t07166272521))
17051724 then {
1706- let quoteWithdrawAmount = $t07085771716._2
1707- let sendCollateralAction = $t07085771716._1
1725+ let quoteWithdrawAmount = $t07166272521._2
1726+ let sendCollateralAction = $t07166272521._1
17081727 let unstake = if ((quoteWithdrawAmount > 0))
17091728 then {
17101729 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
17611780 then (DECIMAL_UNIT > partialLiquidationRatio())
17621781 else false)
17631782 then {
1764- let $t07401374163 = getPosition(_trader)
1765- let oldPositionSize = $t07401374163._1
1766- let oldPositionMargin = $t07401374163._2
1767- let oldPositionOpenNotional = $t07401374163._3
1768- let oldPositionLstUpdCPF = $t07401374163._4
1783+ let $t07481874968 = getPosition(_trader)
1784+ let oldPositionSize = $t07481874968._1
1785+ let oldPositionMargin = $t07481874968._2
1786+ let oldPositionOpenNotional = $t07481874968._3
1787+ let oldPositionLstUpdCPF = $t07481874968._4
17691788 let _direction = if ((oldPositionSize > 0))
17701789 then DIR_SHORT
17711790 else DIR_LONG
17721791 let isAdd = (_direction == DIR_LONG)
17731792 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1774- let $t07438874492 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1775- let oldPositionNotional = $t07438874492._1
1776- let unrealizedPnl = $t07438874492._2
1777- let $t07450074687 = swapInput(isAdd, exchangedQuoteAssetAmount)
1778- let exchangedPositionSize = $t07450074687._1
1779- let quoteAssetReserveAfter = $t07450074687._2
1780- let baseAssetReserveAfter = $t07450074687._3
1781- let totalPositionSizeAfter = $t07450074687._4
1793+ let $t07519375297 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1794+ let oldPositionNotional = $t07519375297._1
1795+ let unrealizedPnl = $t07519375297._2
1796+ let $t07530575492 = swapInput(isAdd, exchangedQuoteAssetAmount)
1797+ let exchangedPositionSize = $t07530575492._1
1798+ let quoteAssetReserveAfter = $t07530575492._2
1799+ let baseAssetReserveAfter = $t07530575492._3
1800+ let totalPositionSizeAfter = $t07530575492._4
17821801 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
17831802 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1784- let $t07497675209 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1785- let remainMargin = $t07497675209._1
1786- let badDebt = $t07497675209._2
1787- let fundingPayment = $t07497675209._3
1803+ let $t07578176014 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1804+ let remainMargin = $t07578176014._1
1805+ let badDebt = $t07578176014._2
1806+ let fundingPayment = $t07578176014._3
17881807 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
17891808 let remainOpenNotional = if ((oldPositionSize > 0))
17901809 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
17981817 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
17991818 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
18001819 let ammBalance = (cbalance() - liquidationPenalty)
1801- let $t07637876507 = if ((0 > ammBalance))
1820+ let $t07718377312 = if ((0 > ammBalance))
18021821 then $Tuple2(0, abs(ammBalance))
18031822 else $Tuple2(ammBalance, 0)
1804- let newAmmBalance = $t07637876507._1
1805- let x11 = $t07637876507._2
1806- let $t07651576569 = getBorrowedByTrader(_trader)
1807- let borrowed = $t07651576569._1
1808- let assetId = $t07651576569._2
1823+ let newAmmBalance = $t07718377312._1
1824+ let x11 = $t07718377312._2
1825+ let $t07732077374 = getBorrowedByTrader(_trader)
1826+ let borrowed = $t07732077374._1
1827+ let assetId = $t07732077374._2
18091828 let doLiquidateCollateral = if ((borrowed > 0))
18101829 then {
18111830 let collateralToSell = muld(borrowed, liquidationRatio)
18431862 else throw("Strict value is not equal to itself.")
18441863 }
18451864 else {
1846- let $t07826478759 = internalClosePosition(_trader, false)
1847- let x1 = $t07826478759._1
1848- let badDebt = $t07826478759._2
1849- let x2 = $t07826478759._3
1850- let x3 = $t07826478759._4
1851- let quoteAssetReserveAfter = $t07826478759._5
1852- let baseAssetReserveAfter = $t07826478759._6
1853- let totalPositionSizeAfter = $t07826478759._7
1854- let openInterestNotionalAfter = $t07826478759._8
1855- let exchangedQuoteAssetAmount = $t07826478759._9
1856- let totalLongAfter = $t07826478759._10
1857- let totalShortAfter = $t07826478759._11
1858- let totalLongOpenInterestAfter = $t07826478759._12
1859- let totalShortOpenInterestAfter = $t07826478759._13
1865+ let $t07906979564 = internalClosePosition(_trader, false)
1866+ let x1 = $t07906979564._1
1867+ let badDebt = $t07906979564._2
1868+ let x2 = $t07906979564._3
1869+ let x3 = $t07906979564._4
1870+ let quoteAssetReserveAfter = $t07906979564._5
1871+ let baseAssetReserveAfter = $t07906979564._6
1872+ let totalPositionSizeAfter = $t07906979564._7
1873+ let openInterestNotionalAfter = $t07906979564._8
1874+ let exchangedQuoteAssetAmount = $t07906979564._9
1875+ let totalLongAfter = $t07906979564._10
1876+ let totalShortAfter = $t07906979564._11
1877+ let totalLongOpenInterestAfter = $t07906979564._12
1878+ let totalShortOpenInterestAfter = $t07906979564._13
18601879 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18611880 let feeToLiquidator = (liquidationPenalty / 2)
18621881 let feeToVault = (liquidationPenalty - feeToLiquidator)
18631882 let ammBalance = (cbalance() - liquidationPenalty)
1864- let $t07916779296 = if ((0 > ammBalance))
1883+ let $t07997280101 = if ((0 > ammBalance))
18651884 then $Tuple2(0, abs(ammBalance))
18661885 else $Tuple2(ammBalance, 0)
1867- let newAmmBalance = $t07916779296._1
1868- let x11 = $t07916779296._2
1869- let $t07930479358 = getBorrowedByTrader(_trader)
1870- let borrowed = $t07930479358._1
1871- let assetId = $t07930479358._2
1886+ let newAmmBalance = $t07997280101._1
1887+ let x11 = $t07997280101._2
1888+ let $t08010980163 = getBorrowedByTrader(_trader)
1889+ let borrowed = $t08010980163._1
1890+ let assetId = $t08010980163._2
18721891 let doLiquidateCollateral = if ((borrowed > 0))
18731892 then {
18741893 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
19281947 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19291948 else {
19301949 let underlyingPrice = getOracleTwapPrice()
1931- let $t08123481296 = getFunding()
1932- let shortPremiumFraction = $t08123481296._1
1933- let longPremiumFraction = $t08123481296._2
1950+ let $t08203982101 = getFunding()
1951+ let shortPremiumFraction = $t08203982101._1
1952+ let longPremiumFraction = $t08203982101._2
19341953 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19351954 }
19361955 }
19411960
19421961 @Callable(i)
19431962 func syncTerminalPriceToOracle () = {
1944- let $t08167881799 = getSyncTerminalPrice(getOracleTwapPrice())
1945- let newQuoteAssetWeight = $t08167881799._1
1946- let newBaseAssetWeight = $t08167881799._2
1947- let marginToVault = $t08167881799._3
1963+ let _qtAstR = qtAstR()
1964+ let _bsAstR = bsAstR()
1965+ let $t08253382672 = getSyncTerminalPrice(getOracleTwapPrice(), _qtAstR, _bsAstR)
1966+ let newQuoteAssetWeight = $t08253382672._1
1967+ let newBaseAssetWeight = $t08253382672._2
1968+ let marginToVault = $t08253382672._3
19481969 let doExchangePnL = if ((marginToVault != 0))
19491970 then {
19501971 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
19541975 }
19551976 else nil
19561977 if ((doExchangePnL == doExchangePnL))
1957- then {
1958- let _qtAstR = qtAstR()
1959- let _bsAstR = bsAstR()
1960- (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
1961- }
1978+ then (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
19621979 else throw("Strict value is not equal to itself.")
19631980 }
19641981
19691986 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19701987 if ((sync == sync))
19711988 then {
1972- let $t08241982520 = getPosition(_trader)
1973- let positionSize = $t08241982520._1
1974- let positionMargin = $t08241982520._2
1975- let pon = $t08241982520._3
1976- let positionLstUpdCPF = $t08241982520._4
1977- let $t08252382624 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1978- let positionNotional = $t08252382624._1
1979- let unrealizedPnl = $t08252382624._2
1980- let $t08262782799 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1981- let remainMargin = $t08262782799._1
1982- let badDebt = $t08262782799._2
1983- let fundingPayment = $t08262782799._3
1989+ let $t08324183342 = getPosition(_trader)
1990+ let positionSize = $t08324183342._1
1991+ let positionMargin = $t08324183342._2
1992+ let pon = $t08324183342._3
1993+ let positionLstUpdCPF = $t08324183342._4
1994+ let $t08334583446 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1995+ let positionNotional = $t08334583446._1
1996+ let unrealizedPnl = $t08334583446._2
1997+ let $t08344983621 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1998+ let remainMargin = $t08344983621._1
1999+ let badDebt = $t08344983621._2
2000+ let fundingPayment = $t08344983621._3
19842001 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
19852002 }
19862003 else throw("Strict value is not equal to itself.")
19902007
19912008 @Callable(i)
19922009 func view_getPegAdjustCost (_price) = {
1993- let result = getSyncTerminalPrice(_price)
2010+ let _qtAstR = qtAstR()
2011+ let _bsAstR = bsAstR()
2012+ let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
19942013 throw(toString(result._3))
19952014 }
19962015
19982017
19992018 @Callable(i)
20002019 func view_getTerminalAmmPrice () = {
2001- let $t08314683227 = getTerminalAmmState()
2002- let terminalQuoteAssetReserve = $t08314683227._1
2003- let terminalBaseAssetReserve = $t08314683227._2
2020+ let $t08403784118 = getTerminalAmmState()
2021+ let terminalQuoteAssetReserve = $t08403784118._1
2022+ let terminalBaseAssetReserve = $t08403784118._2
20042023 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20052024 throw(toString(price))
20062025 }
20102029 @Callable(i)
20112030 func view_getFunding () = {
20122031 let underlyingPrice = getOracleTwapPrice()
2013- let $t08344683508 = getFunding()
2014- let shortPremiumFraction = $t08344683508._1
2015- let longPremiumFraction = $t08344683508._2
2032+ let $t08433784399 = getFunding()
2033+ let shortPremiumFraction = $t08433784399._1
2034+ let longPremiumFraction = $t08433784399._2
20162035 let longFunding = divd(longPremiumFraction, underlyingPrice)
20172036 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20182037 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
20222041
20232042 @Callable(i)
20242043 func view_getBorrowedByTrader (_trader) = {
2025- let $t08379883852 = getBorrowedByTrader(_trader)
2026- let borrowed = $t08379883852._1
2027- let assetId = $t08379883852._2
2044+ let $t08468984743 = getBorrowedByTrader(_trader)
2045+ let borrowed = $t08468984743._1
2046+ let assetId = $t08468984743._2
20282047 throw((s(borrowed) + assetId))
20292048 }
20302049
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 = "k_ora"
99
1010 let k_balance = "k_balance"
1111
1212 let k_sequence = "k_sequence"
1313
1414 let k_positionSize = "k_positionSize"
1515
1616 let k_positionMargin = "k_positionMargin"
1717
1818 let k_positionOpenNotional = "k_positionOpenNotional"
1919
2020 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
2121
2222 let k_positionSequence = "k_positionSequence"
2323
2424 let k_positionAsset = "k_positionAsset"
2525
2626 let k_initialized = "k_initialized"
2727
2828 let k_paused = "k_paused"
2929
3030 let k_closeOnly = "k_closeOnly"
3131
3232 let k_fee = "k_fee"
3333
3434 let k_fundingPeriod = "k_fundingPeriod"
3535
3636 let k_initMarginRatio = "k_initMarginRatio"
3737
3838 let k_maintenanceMarginRatio = "k_mmr"
3939
4040 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4141
4242 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4343
4444 let k_spreadLimit = "k_spreadLimit"
4545
4646 let k_maxPriceImpact = "k_maxPriceImpact"
4747
4848 let k_maxPriceSpread = "k_maxPriceSpread"
4949
5050 let k_maxOpenNotional = "k_maxOpenNotional"
5151
5252 let k_feeToStakersPercent = "k_feeToStakersPercent"
5353
5454 let k_maxOracleDelay = "k_maxOracleDelay"
5555
5656 let k_lastDataStr = "k_lastDataStr"
5757
5858 let k_lastMinuteId = "k_lastMinuteId"
5959
6060 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6161
6262 let k_twapDataLastPrice = "k_twapDataLastPrice"
6363
6464 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
6565
6666 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6767
6868 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
6969
7070 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7171
7272 let k_longFundingRate = "k_longFundingRate"
7373
7474 let k_shortFundingRate = "k_shortFundingRate"
7575
7676 let k_quoteAssetReserve = "k_qtAstR"
7777
7878 let k_baseAssetReserve = "k_bsAstR"
7979
8080 let k_quoteAssetWeight = "k_qtAstW"
8181
8282 let k_baseAssetWeight = "k_bsAstW"
8383
8484 let k_totalPositionSize = "k_totalPositionSize"
8585
8686 let k_totalLongPositionSize = "k_totalLongPositionSize"
8787
8888 let k_totalShortPositionSize = "k_totalShortPositionSize"
8989
9090 let k_openInterestNotional = "k_openInterestNotional"
9191
9292 let k_openInterestShort = "k_openInterestShort"
9393
9494 let k_openInterestLong = "k_openInterestLong"
9595
9696 let k_coordinatorAddress = "k_coordinatorAddress"
9797
9898 let k_vault_address = "k_vault_address"
9999
100100 let k_admin_address = "k_admin_address"
101101
102102 let k_admin_public_key = "k_admin_public_key"
103103
104104 let k_quote_asset = "k_quote_asset"
105105
106106 let k_quote_staking = "k_quote_staking"
107107
108108 let k_staking_address = "k_staking_address"
109109
110110 let k_miner_address = "k_miner_address"
111111
112112 let k_orders_address = "k_orders_address"
113113
114114 let k_referral_address = "k_referral_address"
115115
116116 let k_collateral_address = "k_collateral_address"
117117
118118 let k_exchange_address = "k_exchange_address"
119119
120120 let k_nft_manager_address = "k_nft_manager_address"
121121
122122 let k_trader_market_asset_collateral = "k_trader_market_asset_collateral"
123123
124124 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
125125
126126
127127 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
128128
129129
130130 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
131131
132132
133133 func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
134134
135135
136136 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
137137
138138
139139 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
140140
141141
142142 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
143143
144144
145145 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
146146
147147
148148 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
149149
150150
151151 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
152152
153153
154154 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
155155
156156
157157 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
158158
159159
160160 func collateralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_collateral_address)), "Collateral Manager not set")
161161
162162
163163 func swapAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_exchange_address), "No swap address")), "Invalid swap address")
164164
165165
166166 let k_whitelist_asset = "k_whitelist_asset"
167167
168168 func isWhitelistAsset (_assetId) = valueOrElse(getBoolean(collateralAddress(), toCompositeKey(k_whitelist_asset, _assetId)), false)
169169
170170
171171 let k_token_param = "k_token_param"
172172
173173 let k_token_type = "k_token_type"
174174
175175 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
176176
177177 let DIR_LONG = 1
178178
179179 let DIR_SHORT = 2
180180
181181 let TWAP_INTERVAL = 15
182182
183183 let ORACLE_INTERVAL = 15
184184
185185 let SECONDS = 1000
186186
187187 let DECIMAL_NUMBERS = 6
188188
189189 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
190190
191191 let ONE_DAY = (86400 * DECIMAL_UNIT)
192192
193193 let ALL_FEES = 100
194194
195195 let PNL_OPTION_SPOT = 1
196196
197197 let PNL_OPTION_ORACLE = 2
198198
199199 func s (_x) = (toString(_x) + ",")
200200
201201
202202 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
203203
204204
205205 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
206206
207207
208208 func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
209209
210210
211211 func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
212212
213213
214214 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
215215
216216
217217 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
218218
219219
220220 func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
221221
222222
223223 func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
224224
225225
226226 func abs (_x) = if ((_x > 0))
227227 then _x
228228 else -(_x)
229229
230230
231231 func vmax (_x,_y) = if ((_x >= _y))
232232 then _x
233233 else _y
234234
235235
236236 func listToStr (_list) = {
237237 func _join (accumulator,val) = ((accumulator + val) + ",")
238238
239239 let newListStr = {
240240 let $l = _list
241241 let $s = size($l)
242242 let $acc0 = ""
243243 func $f0_1 ($a,$i) = if (($i >= $s))
244244 then $a
245245 else _join($a, $l[$i])
246246
247247 func $f0_2 ($a,$i) = if (($i >= $s))
248248 then $a
249249 else throw("List size exceeds 20")
250250
251251 $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)
252252 }
253253 let newListStrU = dropRight(newListStr, 1)
254254 let newListStrR = if ((take(newListStrU, 1) == ","))
255255 then drop(newListStrU, 1)
256256 else newListStrU
257257 newListStrR
258258 }
259259
260260
261261 func strToList (_str) = split(_str, ",")
262262
263263
264264 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
265265 then (removeByIndex(_list, 0) :+ _value)
266266 else (_list :+ _value)
267267
268268
269269 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
270270
271271
272272 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
273273
274274
275275 func strA (_address,_key) = {
276276 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
277277 val
278278 }
279279
280280
281281 func intA (_address,_key) = {
282282 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
283283 val
284284 }
285285
286286
287287 func cbalance () = int(k_balance)
288288
289289
290290 func fee () = int(k_fee)
291291
292292
293293 func initMarginRatio () = int(k_initMarginRatio)
294294
295295
296296 func qtAstR () = int(k_quoteAssetReserve)
297297
298298
299299 func bsAstR () = int(k_baseAssetReserve)
300300
301301
302302 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
303303
304304
305305 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
306306
307307
308308 func totalPositionSize () = int(k_totalPositionSize)
309309
310310
311311 func openInterestNotional () = int(k_openInterestNotional)
312312
313313
314314 func openInterestShort () = int(k_openInterestShort)
315315
316316
317317 func openInterestLong () = int(k_openInterestLong)
318318
319319
320320 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
321321
322322
323323 func fundingPeriodRaw () = int(k_fundingPeriod)
324324
325325
326326 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
327327
328328
329329 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
330330
331331
332332 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
333333
334334
335335 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
336336
337337
338338 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
339339
340340
341341 func spreadLimit () = int(k_spreadLimit)
342342
343343
344344 func maxPriceImpact () = int(k_maxPriceImpact)
345345
346346
347347 func maxPriceSpread () = int(k_maxPriceSpread)
348348
349349
350350 func maxOpenNotional () = int(k_maxOpenNotional)
351351
352352
353353 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
354354
355355
356356 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
357357
358358
359359 func totalShortPositionSize () = int(k_totalShortPositionSize)
360360
361361
362362 func totalLongPositionSize () = int(k_totalLongPositionSize)
363363
364364
365365 func lastSequence () = intOr(k_sequence, 0)
366366
367367
368368 func feeToStakersPercent () = int(k_feeToStakersPercent)
369369
370370
371371 func maxOracleDelay () = int(k_maxOracleDelay)
372372
373373
374374 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
375375
376376
377377 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
378378 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
379379 if (if (_largerThanOrEqualTo)
380380 then (0 > remainingMarginRatio)
381381 else false)
382382 then throw("Invalid margin")
383383 else if (if (!(_largerThanOrEqualTo))
384384 then (remainingMarginRatio >= 0)
385385 else false)
386386 then throw("Invalid margin")
387387 else true
388388 }
389389
390390
391391 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
392392 then throw("Should not be called with _positionSize == 0")
393393 else if ((_positionSize > 0))
394394 then latestLongCumulativePremiumFraction()
395395 else latestShortCumulativePremiumFraction()
396396
397397
398398 func getPosition (_trader) = {
399399 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
400400 match positionSizeOpt {
401401 case positionSize: Int =>
402402 $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
403403 case _ =>
404404 $Tuple4(0, 0, 0, 0)
405405 }
406406 }
407407
408408
409409 func getPositionAsset (_trader) = {
410410 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
411411 match positionAssetOpt {
412412 case positionAsset: String =>
413413 positionAsset
414414 case _ =>
415415 toBase58String(quoteAsset())
416416 }
417417 }
418418
419419
420420 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
421421 then throw("No open position")
422422 else true
423423
424424
425425 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
426426
427427
428428 func paused () = valueOrElse(getBoolean(this, k_paused), false)
429429
430430
431431 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
432432
433433
434434 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
435435 then {
436436 let newBase = (bsAstR() - _baseAssetAmount)
437437 if ((0 >= newBase))
438438 then throw("Tx lead to base asset reserve <= 0, revert")
439439 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
440440 }
441441 else {
442442 let newQuote = (qtAstR() - _quoteAssetAmount)
443443 if ((0 >= newQuote))
444444 then throw("Tx lead to base quote reserve <= 0, revert")
445445 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
446446 }
447447
448448
449449 func calcInvariant (_qtAstR,_qtAstW,_bsAstR,_bsAstW) = {
450450 let bqtAstR = toBigInt(_qtAstR)
451451 let bqtAstW = toBigInt(_qtAstW)
452452 let bbsAstR = toBigInt(_bsAstR)
453453 let bbsAstW = toBigInt(_bsAstW)
454454 bmuld(bmuld(bqtAstR, bqtAstW), bmuld(bbsAstR, bbsAstW))
455455 }
456456
457457
458458 func swapInput (_isAdd,_quoteAssetAmount) = {
459459 let _qtAstR = qtAstR()
460460 let _bsAstR = bsAstR()
461461 let _qtAstW = qtAstW()
462462 let _bsAstW = bsAstW()
463463 let k = calcInvariant(_qtAstR, _qtAstW, _bsAstR, _bsAstW)
464464 let quoteAssetReserveAfter = if (_isAdd)
465465 then (_qtAstR + _quoteAssetAmount)
466466 else (_qtAstR - _quoteAssetAmount)
467467 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(muld(quoteAssetReserveAfter, _qtAstW))))
468468 let amountBaseAssetBoughtAbs = divd(abs((baseAssetReserveAfter - _bsAstR)), _qtAstW)
469469 let amountBaseAssetBought = if (_isAdd)
470470 then amountBaseAssetBoughtAbs
471471 else -(amountBaseAssetBoughtAbs)
472472 let $t01694617109 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
473473 let quoteAssetReserveAfter1 = $t01694617109._1
474474 let baseAssetReserveAfter1 = $t01694617109._2
475475 let totalPositionSizeAfter1 = $t01694617109._3
476476 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
477477 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
478478 let priceDiff = abs((priceBefore - marketPrice))
479479 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
480480 let maxPriceImpactValue = maxPriceImpact()
481481 if ((priceImpact > maxPriceImpactValue))
482482 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)))
483483 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
484484 }
485485
486486
487487 func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
488488 let fundingPayment = if ((_oldPositionSize != 0))
489489 then {
490490 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
491491 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
492492 }
493493 else 0
494494 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
495495 let $t01859618723 = if ((0 > signedMargin))
496496 then $Tuple2(0, abs(signedMargin))
497497 else $Tuple2(abs(signedMargin), 0)
498498 let remainMargin = $t01859618723._1
499499 let badDebt = $t01859618723._2
500500 $Tuple3(remainMargin, badDebt, fundingPayment)
501501 }
502502
503503
504504 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
505505 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
506506 if ((_baseAssetAmount == 0))
507507 then throw("Invalid base asset amount")
508508 else {
509509 let k = calcInvariant(_quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
510510 let baseAssetPoolAmountAfter = if (_isAdd)
511511 then (_baseAssetReserve + _baseAssetAmount)
512512 else (_baseAssetReserve - _baseAssetAmount)
513513 let quoteAssetAfter = toInt(bdivd(k, toBigInt(muld(baseAssetPoolAmountAfter, _baseAssetWeight))))
514514 let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
515515 let maxPriceImpactValue = maxPriceImpact()
516516 let $t01991120072 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
517517 let quoteAssetReserveAfter1 = $t01991120072._1
518518 let baseAssetReserveAfter1 = $t01991120072._2
519519 let totalPositionSizeAfter1 = $t01991120072._3
520520 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
521521 let priceDiff = abs((priceBefore - marketPrice))
522522 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
523523 if (if ((priceImpact > maxPriceImpactValue))
524524 then _checkMaxPriceImpact
525525 else false)
526526 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)))
527527 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
528528 then abs(_baseAssetAmount)
529529 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
530530 then abs(_baseAssetAmount)
531531 else 0)), priceImpact)
532532 }
533533 }
534534
535535
536536 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
537537
538538
539539 func getOracleTwapPrice () = {
540540 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
541541 let priceKey = getStringValue(this, k_ora_key)
542542 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
543543 let blockKey = valueOrElse(getString(this, k_ora_block_key), "")
544544 if ((blockKey != ""))
545545 then {
546546 let currentBlock = lastBlock.height
547547 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
548548 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
549549 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
550550 else lastValue
551551 }
552552 else lastValue
553553 }
554554
555555
556+func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
557+ let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
558+ let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
559+ let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
560+ absPriceDiff
561+ }
562+
563+
556564 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
557565 let oraclePrice = getOracleTwapPrice()
558566 let _qtAstW = qtAstW()
559567 let _bsAstW = bsAstW()
560- let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
561- let averagePrice = divd((oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
562- let absPriceDiff = divd(abs((oraclePrice - priceAfter)), averagePrice)
563- if ((absPriceDiff > maxPriceSpread()))
564- then throw(((("Price spread " + toString(absPriceDiff)) + " > max price spread ") + toString(maxPriceSpread())))
568+ let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
569+ let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
570+ if (if ((absPriceDiffAfter > maxPriceSpread()))
571+ then (absPriceDiffAfter > absPriceDiffBefore)
572+ else false)
573+ then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
565574 else true
566575 }
567576
568577
569578 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
570579 let _maxOpenNotional = maxOpenNotional()
571580 if ((_longOpenNotional > _maxOpenNotional))
572581 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
573582 else if ((_shortOpenNotional > _maxOpenNotional))
574583 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
575584 else true
576585 }
577586
578587
579588 func getSpotPrice () = {
580589 let _quoteAssetReserve = qtAstR()
581590 let _baseAssetReserve = bsAstR()
582591 let _qtAstW = qtAstW()
583592 let _bsAstW = bsAstW()
584593 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
585594 }
586595
587596
588597 func isOverFluctuationLimit () = {
589598 let oraclePrice = getOracleTwapPrice()
590599 let currentPrice = getSpotPrice()
591600 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
592601 }
593602
594603
595604 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
596605 let positionSizeAbs = abs(_positionSize)
597606 let isShort = (0 > _positionSize)
598607 let positionNotional = if ((_option == PNL_OPTION_SPOT))
599608 then {
600- let $t02423124451 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
601- let outPositionNotional = $t02423124451._1
602- let x1 = $t02423124451._2
603- let x2 = $t02423124451._3
604- let x3 = $t02423124451._4
609+ let $t02463524855 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
610+ let outPositionNotional = $t02463524855._1
611+ let x1 = $t02463524855._2
612+ let x2 = $t02463524855._3
613+ let x3 = $t02463524855._4
605614 outPositionNotional
606615 }
607616 else muld(positionSizeAbs, getOracleTwapPrice())
608617 positionNotional
609618 }
610619
611620
612621 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
613622 then throw("Invalid position size")
614623 else {
615624 let isShort = (0 > _positionSize)
616625 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
617626 let unrealizedPnl = if (isShort)
618627 then (_positionOpenNotional - positionNotional)
619628 else (positionNotional - _positionOpenNotional)
620629 $Tuple2(positionNotional, unrealizedPnl)
621630 }
622631
623632
624633 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
625- let $t02587626004 = getPosition(_trader)
626- let positionSize = $t02587626004._1
627- let positionMargin = $t02587626004._2
628- let positionOpenNotional = $t02587626004._3
629- let positionLstUpdCPF = $t02587626004._4
634+ let $t02628026408 = getPosition(_trader)
635+ let positionSize = $t02628026408._1
636+ let positionMargin = $t02628026408._2
637+ let positionOpenNotional = $t02628026408._3
638+ let positionLstUpdCPF = $t02628026408._4
630639 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
631640 }
632641
633642
634643 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
635644
636645
637646 func getMarginRatioByOption (_trader,_option) = {
638- let $t02651726628 = getPosition(_trader)
639- let positionSize = $t02651726628._1
640- let positionMargin = $t02651726628._2
641- let pon = $t02651726628._3
642- let positionLstUpdCPF = $t02651726628._4
643- let $t02663426727 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
644- let positionNotional = $t02663426727._1
645- let unrealizedPnl = $t02663426727._2
646- let $t02673226898 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
647- let remainMargin = $t02673226898._1
648- let badDebt = $t02673226898._2
647+ let $t02692127032 = getPosition(_trader)
648+ let positionSize = $t02692127032._1
649+ let positionMargin = $t02692127032._2
650+ let pon = $t02692127032._3
651+ let positionLstUpdCPF = $t02692127032._4
652+ let $t02703827131 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
653+ let positionNotional = $t02703827131._1
654+ let unrealizedPnl = $t02703827131._2
655+ let $t02713627302 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
656+ let remainMargin = $t02713627302._1
657+ let badDebt = $t02713627302._2
649658 calcMarginRatio(remainMargin, badDebt, positionNotional)
650659 }
651660
652661
653662 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
654663
655664
656665 func getPartialLiquidationAmount (_trader,_positionSize) = {
657666 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
658667 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
659668 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
660669 let maxExchangedQuoteAssetAmount = swapResult._1
661670 let priceImpact = swapResult._7
662671 if ((maxPriceImpact() > priceImpact))
663672 then maxExchangedQuoteAssetAmount
664673 else {
665674 let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
666675 let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
667676 exchangedQuoteAssetAmount
668677 }
669678 }
670679
671680
672681 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
673- let $t02813828266 = getPosition(_trader)
674- let positionSize = $t02813828266._1
675- let positionMargin = $t02813828266._2
676- let positionOpenNotional = $t02813828266._3
677- let positionLstUpdCPF = $t02813828266._4
682+ let $t02854228670 = getPosition(_trader)
683+ let positionSize = $t02854228670._1
684+ let positionMargin = $t02854228670._2
685+ let positionOpenNotional = $t02854228670._3
686+ let positionLstUpdCPF = $t02854228670._4
678687 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
679- let $t02836128529 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
680- let remainMargin = $t02836128529._1
681- let badDebt = $t02836128529._2
688+ let $t02876528933 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
689+ let remainMargin = $t02876528933._1
690+ let badDebt = $t02876528933._2
682691 let exchangedPositionSize = -(positionSize)
683692 let realizedPnl = unrealizedPnl
684693 let marginToVault = -(remainMargin)
685- let $t02865628930 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
686- let exchangedQuoteAssetAmount = $t02865628930._1
687- let quoteAssetReserveAfter = $t02865628930._2
688- let baseAssetReserveAfter = $t02865628930._3
689- let totalPositionSizeAfter = $t02865628930._4
690- let totalLongAfter = $t02865628930._5
691- let totalShortAfter = $t02865628930._6
694+ let $t02906029334 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
695+ let exchangedQuoteAssetAmount = $t02906029334._1
696+ let quoteAssetReserveAfter = $t02906029334._2
697+ let baseAssetReserveAfter = $t02906029334._3
698+ let totalPositionSizeAfter = $t02906029334._4
699+ let totalLongAfter = $t02906029334._5
700+ let totalShortAfter = $t02906029334._6
692701 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
693702 $Tuple13(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter, (openInterestLong() - (if ((positionSize > 0))
694703 then positionOpenNotional
695704 else 0)), (openInterestShort() - (if ((0 > positionSize))
696705 then positionOpenNotional
697706 else 0)))
698707 }
699708
700709
701710 func getTwapSpotPrice () = {
702711 let minuteId = ((lastBlock.timestamp / 1000) / 60)
703712 let startMinuteId = (minuteId - TWAP_INTERVAL)
704713 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
705714 let list = split(listStr, ",")
706715 func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
707716 then (accumulator :+ parseIntValue(next))
708717 else accumulator
709718
710719 let listF = {
711720 let $l = list
712721 let $s = size($l)
713722 let $acc0 = nil
714723 func $f0_1 ($a,$i) = if (($i >= $s))
715724 then $a
716725 else filterFn($a, $l[$i])
717726
718727 func $f0_2 ($a,$i) = if (($i >= $s))
719728 then $a
720729 else throw("List size exceeds 20")
721730
722731 $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)
723732 }
724733 let maxIndex = if ((size(listF) > 0))
725734 then max(listF)
726735 else parseIntValue(list[0])
727736 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
728737 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
729738 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
730739 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
731740 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
732741 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
733742 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
734743 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
735744 }
736745
737746
738747 func getTerminalAmmState () = {
739748 let _positionSize = totalPositionSize()
740749 if ((_positionSize == 0))
741750 then $Tuple2(qtAstR(), bsAstR())
742751 else {
743752 let direction = (_positionSize > 0)
744- let $t03105331232 = swapOutput(direction, abs(_positionSize), false)
745- let currentNetMarketValue = $t03105331232._1
746- let terminalQuoteAssetReserve = $t03105331232._2
747- let terminalBaseAssetReserve = $t03105331232._3
753+ let $t03145731636 = swapOutput(direction, abs(_positionSize), false)
754+ let currentNetMarketValue = $t03145731636._1
755+ let terminalQuoteAssetReserve = $t03145731636._2
756+ let terminalBaseAssetReserve = $t03145731636._3
748757 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
749758 }
750759 }
751760
752761
753762 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
754763 let b = toBigInt(baseAssetReserve)
755764 let sz = toBigInt(totalPositionSize)
756765 let q = toBigInt(quoteAssetReserve)
757766 let p = toBigInt(targetPrice)
758767 let bs2 = bpowd((b + sz), toBigInt((2 * DECIMAL_UNIT)))
759768 let qbs2 = bmuld(q, bs2)
760769 let ps4 = (toBigInt(4) * bmuld(p, sz))
761770 let sqr = bsqrtd(bmuld(qbs2, (q - ps4)))
762771 let bq = bmuld(b, q)
763772 let qs = bmuld(q, sz)
764773 let top = ((-(sqr) + bq) + qs)
765774 let bot = (toBigInt(2) * bmuld(q, sz))
766775 let result = bdivd(top, bot)
767776 toInt(result)
768777 }
769778
770779
771-func getSyncTerminalPrice (_terminalPrice) = {
780+func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
772781 let _positionSize = totalPositionSize()
773782 if ((_positionSize == 0))
774783 then {
775- let _qtAstR = qtAstR()
776- let _bsAstR = bsAstR()
777784 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
778785 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
779786 }
780787 else {
781788 let direction = (_positionSize > 0)
782789 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
783- let _qtAstR = qtAstR()
784- let _bsAstR = bsAstR()
785790 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
786791 let newBsAstW = DECIMAL_UNIT
787792 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
788793 $Tuple3(newQtAstW, newBsAstW, marginToVault)
789794 }
790795 }
791796
792797
793798 func getFunding () = {
794799 let underlyingPrice = getOracleTwapPrice()
795800 let spotTwapPrice = getTwapSpotPrice()
796801 let premium = (spotTwapPrice - underlyingPrice)
797802 if (if ((totalShortPositionSize() == 0))
798803 then true
799804 else (totalLongPositionSize() == 0))
800805 then $Tuple2(0, 0)
801806 else if ((0 > premium))
802807 then {
803808 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
804809 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
805810 $Tuple2(shortPremiumFraction, longPremiumFraction)
806811 }
807812 else {
808813 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
809814 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
810815 $Tuple2(shortPremiumFraction, longPremiumFraction)
811816 }
812817 }
813818
814819
815820 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
816821 let baseFeeRaw = fee()
817822 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
818- let $t03433134826 = if ((_artifactId != ""))
823+ let $t03465535150 = if ((_artifactId != ""))
819824 then {
820825 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
821826 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
822827 then {
823828 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
824829 let adjustedFee = muld(baseFee, reduction)
825830 $Tuple2(adjustedFee, true)
826831 }
827832 else throw("Invalid attached artifact")
828833 }
829834 else $Tuple2(baseFee, false)
830- let adjustedFee = $t03433134826._1
831- let burnArtifact = $t03433134826._2
835+ let adjustedFee = $t03465535150._1
836+ let burnArtifact = $t03465535150._2
832837 $Tuple2(adjustedFee, burnArtifact)
833838 }
834839
835840
836841 func isSameAssetOrNoPosition (_trader,_assetId) = {
837842 let oldPositionSize = getPosition(_trader)._1
838843 if ((oldPositionSize == 0))
839844 then true
840845 else (getPositionAsset(_trader) == _assetId)
841846 }
842847
843848
844849 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
845850
846851
847852 func getBorrowedByTraderInMarketKey (_amm,_assetId,_trader) = ((((((k_trader_market_asset_collateral + "_") + _amm) + "_") + _assetId) + "_") + _trader)
848853
849854
850855 func getBorrowedByTrader (_trader) = {
851856 let positionAsset = getPositionAsset(_trader)
852857 if ((positionAsset == toBase58String(quoteAsset())))
853858 then $Tuple2(0, positionAsset)
854859 else {
855860 let key = getBorrowedByTraderInMarketKey(toString(this), positionAsset, _trader)
856861 let borrow = valueOrElse(getInteger(collateralAddress(), key), 0)
857862 $Tuple2(borrow, positionAsset)
858863 }
859864 }
860865
861866
862867 func getForTraderWithArtifact (_trader,_artifactId) = {
863868 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
864869 if ((doGetFeeDiscount == doGetFeeDiscount))
865870 then {
866871 let feeDiscount = match doGetFeeDiscount {
867872 case x: Int =>
868873 x
869874 case _ =>
870875 throw("Invalid computeFeeDiscount result")
871876 }
872- let $t03605736131 = getAdjustedFee(_artifactId, feeDiscount)
873- let adjustedFee = $t03605736131._1
874- let burnArtifact = $t03605736131._2
877+ let $t03638136455 = getAdjustedFee(_artifactId, feeDiscount)
878+ let adjustedFee = $t03638136455._1
879+ let burnArtifact = $t03638136455._2
875880 $Tuple2(adjustedFee, burnArtifact)
876881 }
877882 else throw("Strict value is not equal to itself.")
878883 }
879884
880885
881886 func getArtifactId (i) = {
882887 let artifactId = if ((size(i.payments) > 1))
883888 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
884889 else ""
885890 artifactId
886891 }
887892
888893
889894 func distributeFee (_feeAmount) = {
890895 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
891896 let feeToVault = (_feeAmount - feeToStakers)
892897 $Tuple2(feeToStakers, feeToVault)
893898 }
894899
895900
896901 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)]
897902
898903
899904 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)]
900905
901906
902907 func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
903908
904909
905910 func incrementPositionSequenceNumber (isNewPosition,_address) = if (isNewPosition)
906911 then {
907912 let currentSequence = lastSequence()
908913 [IntegerEntry(toCompositeKey(k_positionSequence, _address), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
909914 }
910915 else nil
911916
912917
913918 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)]
914919
915920
916921 func appendTwap (_price) = {
917922 let minuteId = ((lastBlock.timestamp / 1000) / 60)
918923 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
919924 if ((previousMinuteId > minuteId))
920925 then throw("TWAP out-of-order")
921926 else {
922927 let lastMinuteId = if ((previousMinuteId == 0))
923928 then minuteId
924929 else previousMinuteId
925930 if ((minuteId > previousMinuteId))
926931 then {
927932 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
928933 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), _price)
929934 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
930935 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
931936 [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))]
932937 }
933938 else {
934939 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
935940 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
936941 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), _price)
937942 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
938943 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), _price)]
939944 }
940945 }
941946 }
942947
943948
944949 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
945950
946951
947952 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
948953
949954
950955 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
951956 let _qtAstW = qtAstW()
952957 let _bsAstW = bsAstW()
953958 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
954959 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
955960 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))))
956961 }
957962
958963
959964 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))]
960965
961966
962967 func withdraw (_address,_amount) = {
963968 let balance = assetBalance(this, quoteAsset())
964969 if ((_amount > balance))
965970 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
966971 else [ScriptTransfer(_address, _amount, quoteAsset())]
967972 }
968973
969974
970975 func updateBalance (i) = if ((0 > i))
971976 then throw("Balance")
972977 else [IntegerEntry(k_balance, i)]
973978
974979
975980 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
976981
977982
978983 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
979984 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
980985 else nil
981986
982987
983988 @Callable(i)
984989 func pause () = if ((i.caller != adminAddress()))
985990 then throw("Invalid pause params")
986991 else [BooleanEntry(k_paused, true)]
987992
988993
989994
990995 @Callable(i)
991996 func unpause () = if ((i.caller != adminAddress()))
992997 then throw("Invalid unpause params")
993998 else [BooleanEntry(k_paused, false)]
994999
9951000
9961001
9971002 @Callable(i)
9981003 func setCloseOnly () = if ((i.caller != adminAddress()))
9991004 then throw("Invalid setCloseOnly params")
10001005 else [BooleanEntry(k_closeOnly, true)]
10011006
10021007
10031008
10041009 @Callable(i)
10051010 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10061011 then throw("Invalid unsetCloseOnly params")
10071012 else [BooleanEntry(k_closeOnly, false)]
10081013
10091014
10101015
10111016 @Callable(i)
10121017 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10131018 then true
10141019 else (0 >= _quoteAssetAmount))
10151020 then throw("Invalid addLiquidity params")
10161021 else {
10171022 let _qtAstR = qtAstR()
10181023 let _bsAstR = bsAstR()
10191024 let _qtAstW = qtAstW()
10201025 let _bsAstW = bsAstW()
10211026 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
1022- let baseAssetAmountToAdd = divd(_quoteAssetAmount, price)
10231027 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
1028+ let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10241029 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1025- updateAmmReserves(qtAstRAfter, bsAstRAfter)
1030+ let $t04547745632 = getSyncTerminalPrice(getOracleTwapPrice(), qtAstRAfter, bsAstRAfter)
1031+ let newQuoteAssetWeight = $t04547745632._1
1032+ let newBaseAssetWeight = $t04547745632._2
1033+ let marginToVault = $t04547745632._3
1034+ let doExchangePnL = if ((marginToVault != 0))
1035+ then {
1036+ let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
1037+ if ((doExchangePnL == doExchangePnL))
1038+ then nil
1039+ else throw("Strict value is not equal to itself.")
1040+ }
1041+ else nil
1042+ if ((doExchangePnL == doExchangePnL))
1043+ then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
1044+ else throw("Strict value is not equal to itself.")
10261045 }
10271046
10281047
10291048
10301049 @Callable(i)
10311050 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10321051 then true
10331052 else (0 >= _quoteAssetAmount))
10341053 then throw("Invalid removeLiquidity params")
10351054 else {
10361055 let _qtAstR = qtAstR()
10371056 let _bsAstR = bsAstR()
10381057 let _qtAstW = qtAstW()
10391058 let _bsAstW = bsAstW()
10401059 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10411060 let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
10421061 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10431062 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
10441063 updateAmmReserves(qtAstRAfter, bsAstRAfter)
10451064 }
10461065
10471066
10481067
10491068 @Callable(i)
10501069 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay) = if ((i.caller != adminAddress()))
10511070 then throw("Invalid changeSettings params")
10521071 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay)
10531072
10541073
10551074
10561075 @Callable(i)
10571076 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))
10581077 then true
10591078 else (0 >= _bsAstR))
10601079 then true
10611080 else (0 >= _fundingPeriod))
10621081 then true
10631082 else (0 >= _initMarginRatio))
10641083 then true
10651084 else (0 >= _mmr))
10661085 then true
10671086 else (0 >= _liquidationFeeRatio))
10681087 then true
10691088 else (0 >= _fee))
10701089 then true
10711090 else (0 >= _spreadLimit))
10721091 then true
10731092 else (0 >= _maxPriceImpact))
10741093 then true
10751094 else (0 >= _partialLiquidationRatio))
10761095 then true
10771096 else (0 >= _maxPriceSpread))
10781097 then true
10791098 else (0 >= _maxOpenNotional))
10801099 then true
10811100 else (0 >= _feeToStakersPercent))
10821101 then true
10831102 else (_feeToStakersPercent > DECIMAL_UNIT))
10841103 then true
10851104 else (0 >= _maxOracleDelay))
10861105 then true
10871106 else initialized())
10881107 then throw("Invalid initialize parameters")
10891108 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)])
10901109
10911110
10921111
10931112 @Callable(i)
10941113 func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
10951114 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
10961115 if ((sync == sync))
10971116 then {
10981117 let _trader = getActualCaller(i)
10991118 if (if (if (if (if ((0 >= _amount))
11001119 then true
11011120 else !(initialized()))
11021121 then true
11031122 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
11041123 then true
11051124 else !(requireOpenPosition(_trader)))
11061125 then true
11071126 else paused())
11081127 then throw("Invalid decreasePosition parameters")
11091128 else {
1110- let $t04867048810 = getPosition(_trader)
1111- let oldPositionSize = $t04867048810._1
1112- let oldPositionMargin = $t04867048810._2
1113- let oldPositionOpenNotional = $t04867048810._3
1114- let oldPositionLstUpdCPF = $t04867048810._4
1129+ let $t04947549615 = getPosition(_trader)
1130+ let oldPositionSize = $t04947549615._1
1131+ let oldPositionMargin = $t04947549615._2
1132+ let oldPositionOpenNotional = $t04947549615._3
1133+ let oldPositionLstUpdCPF = $t04947549615._4
11151134 let _direction = if ((oldPositionSize > 0))
11161135 then DIR_SHORT
11171136 else DIR_LONG
11181137 let isAdd = (_direction == DIR_LONG)
11191138 let openNotional = muld(_amount, _leverage)
1120- let $t04898349087 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1121- let oldPositionNotional = $t04898349087._1
1122- let unrealizedPnl = $t04898349087._2
1123- let $t04909351751 = if ((oldPositionNotional > openNotional))
1139+ let $t04978849892 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1140+ let oldPositionNotional = $t04978849892._1
1141+ let unrealizedPnl = $t04978849892._2
1142+ let $t04989852556 = if ((oldPositionNotional > openNotional))
11241143 then {
1125- let $t04950849692 = swapInput(isAdd, openNotional)
1126- let exchangedPositionSize = $t04950849692._1
1127- let quoteAssetReserveAfter = $t04950849692._2
1128- let baseAssetReserveAfter = $t04950849692._3
1129- let totalPositionSizeAfter = $t04950849692._4
1144+ let $t05031350497 = swapInput(isAdd, openNotional)
1145+ let exchangedPositionSize = $t05031350497._1
1146+ let quoteAssetReserveAfter = $t05031350497._2
1147+ let baseAssetReserveAfter = $t05031350497._3
1148+ let totalPositionSizeAfter = $t05031350497._4
11301149 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
11311150 if (if ((_minBaseAssetAmount != 0))
11321151 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
11331152 else false)
11341153 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
11351154 else {
11361155 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1137- let $t05012950374 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1138- let remainMargin = $t05012950374._1
1139- let badDebt = $t05012950374._2
1140- let fundingPayment = $t05012950374._3
1156+ let $t05093451179 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1157+ let remainMargin = $t05093451179._1
1158+ let badDebt = $t05093451179._2
1159+ let fundingPayment = $t05093451179._3
11411160 let exchangedQuoteAssetAmount = openNotional
11421161 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
11431162 let remainOpenNotional = if ((oldPositionSize > 0))
11441163 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
11451164 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
11461165 let newPositionSize = (oldPositionSize + exchangedPositionSize)
11471166 $Tuple12(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
11481167 then abs(exchangedPositionSize)
11491168 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
11501169 then abs(exchangedPositionSize)
11511170 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
11521171 then openNotional
11531172 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
11541173 then openNotional
11551174 else 0)))
11561175 }
11571176 }
11581177 else throw("Close position first")
1159- let newPositionSize = $t04909351751._1
1160- let newPositionRemainMargin = $t04909351751._2
1161- let newPositionOpenNotional = $t04909351751._3
1162- let newPositionLatestCPF = $t04909351751._4
1163- let baseAssetReserveAfter = $t04909351751._5
1164- let quoteAssetReserveAfter = $t04909351751._6
1165- let totalPositionSizeAfter = $t04909351751._7
1166- let openInterestNotionalAfter = $t04909351751._8
1167- let totalLongAfter = $t04909351751._9
1168- let totalShortAfter = $t04909351751._10
1169- let totalLongOpenInterestAfter = $t04909351751._11
1170- let totalShortOpenInterestAfter = $t04909351751._12
1178+ let newPositionSize = $t04989852556._1
1179+ let newPositionRemainMargin = $t04989852556._2
1180+ let newPositionOpenNotional = $t04989852556._3
1181+ let newPositionLatestCPF = $t04989852556._4
1182+ let baseAssetReserveAfter = $t04989852556._5
1183+ let quoteAssetReserveAfter = $t04989852556._6
1184+ let totalPositionSizeAfter = $t04989852556._7
1185+ let openInterestNotionalAfter = $t04989852556._8
1186+ let totalLongAfter = $t04989852556._9
1187+ let totalShortAfter = $t04989852556._10
1188+ let totalLongOpenInterestAfter = $t04989852556._11
1189+ let totalShortOpenInterestAfter = $t04989852556._12
11711190 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
11721191 if ((notifyNotional == notifyNotional))
11731192 then (updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter))
11741193 else throw("Strict value is not equal to itself.")
11751194 }
11761195 }
11771196 else throw("Strict value is not equal to itself.")
11781197 }
11791198
11801199
11811200
11821201 @Callable(i)
11831202 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
11841203 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11851204 if ((sync == sync))
11861205 then {
11871206 let _trader = getActualCaller(i)
11881207 let _rawAmount = i.payments[0].amount
11891208 let _assetId = i.payments[0].assetId
11901209 let _assetIdStr = toBase58String(value(_assetId))
11911210 let isQuoteAsset = (_assetId == quoteAsset())
11921211 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
11931212 if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
11941213 then (_direction != DIR_SHORT)
11951214 else false)
11961215 then true
11971216 else (0 >= _rawAmount))
11981217 then true
11991218 else !(initialized()))
12001219 then true
12011220 else if (!(isQuoteAsset))
12021221 then !(isCollateralAsset)
12031222 else false)
12041223 then true
12051224 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
12061225 then true
12071226 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12081227 then true
12091228 else paused())
12101229 then true
12111230 else closeOnly())
12121231 then throw("Invalid increasePosition parameters")
12131232 else {
1214- let $t05318953274 = getForTraderWithArtifact(_trader, getArtifactId(i))
1215- let adjustedFee = $t05318953274._1
1216- let burnArtifact = $t05318953274._2
1233+ let $t05399454079 = getForTraderWithArtifact(_trader, getArtifactId(i))
1234+ let adjustedFee = $t05399454079._1
1235+ let burnArtifact = $t05399454079._2
12171236 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12181237 let _amount = (_rawAmount - rawFeeAmount)
12191238 let distributeFeeAmount = if (isCollateralAsset)
12201239 then {
12211240 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12221241 if ((doBorrow == doBorrow))
12231242 then {
12241243 let balanceBefore = assetBalance(this, quoteAsset())
12251244 if ((balanceBefore == balanceBefore))
12261245 then {
12271246 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
12281247 if ((doSwap == doSwap))
12291248 then {
12301249 let balanceAfter = assetBalance(this, quoteAsset())
12311250 if ((balanceAfter == balanceAfter))
12321251 then {
12331252 let exchangedAmount = (balanceAfter - balanceBefore)
12341253 if ((exchangedAmount == exchangedAmount))
12351254 then exchangedAmount
12361255 else throw("Strict value is not equal to itself.")
12371256 }
12381257 else throw("Strict value is not equal to itself.")
12391258 }
12401259 else throw("Strict value is not equal to itself.")
12411260 }
12421261 else throw("Strict value is not equal to itself.")
12431262 }
12441263 else throw("Strict value is not equal to itself.")
12451264 }
12461265 else rawFeeAmount
12471266 if ((distributeFeeAmount == distributeFeeAmount))
12481267 then {
12491268 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12501269 if ((referrerFeeAny == referrerFeeAny))
12511270 then {
12521271 let referrerFee = match referrerFeeAny {
12531272 case x: Int =>
12541273 x
12551274 case _ =>
12561275 throw("Invalid referrerFee")
12571276 }
12581277 let feeAmount = (distributeFeeAmount - referrerFee)
1259- let $t05459054730 = getPosition(_trader)
1260- let oldPositionSize = $t05459054730._1
1261- let oldPositionMargin = $t05459054730._2
1262- let oldPositionOpenNotional = $t05459054730._3
1263- let oldPositionLstUpdCPF = $t05459054730._4
1278+ let $t05539555535 = getPosition(_trader)
1279+ let oldPositionSize = $t05539555535._1
1280+ let oldPositionMargin = $t05539555535._2
1281+ let oldPositionOpenNotional = $t05539555535._3
1282+ let oldPositionLstUpdCPF = $t05539555535._4
12641283 let isNewPosition = (oldPositionSize == 0)
12651284 let isSameDirection = if ((oldPositionSize > 0))
12661285 then (_direction == DIR_LONG)
12671286 else (_direction == DIR_SHORT)
12681287 let expandExisting = if (!(isNewPosition))
12691288 then isSameDirection
12701289 else false
12711290 let isAdd = (_direction == DIR_LONG)
1272- let $t05501958060 = if (if (isNewPosition)
1291+ let $t05582458865 = if (if (isNewPosition)
12731292 then true
12741293 else expandExisting)
12751294 then {
12761295 let openNotional = muld(_amount, _leverage)
1277- let $t05548155654 = swapInput(isAdd, openNotional)
1278- let amountBaseAssetBought = $t05548155654._1
1279- let quoteAssetReserveAfter = $t05548155654._2
1280- let baseAssetReserveAfter = $t05548155654._3
1281- let totalPositionSizeAfter = $t05548155654._4
1296+ let $t05628656459 = swapInput(isAdd, openNotional)
1297+ let amountBaseAssetBought = $t05628656459._1
1298+ let quoteAssetReserveAfter = $t05628656459._2
1299+ let baseAssetReserveAfter = $t05628656459._3
1300+ let totalPositionSizeAfter = $t05628656459._4
12821301 if (if ((_minBaseAssetAmount != 0))
12831302 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12841303 else false)
12851304 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12861305 else {
12871306 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12881307 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12891308 then openNotional
12901309 else 0))
12911310 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12921311 then openNotional
12931312 else 0))
12941313 let increaseMarginRequirement = divd(openNotional, _leverage)
1295- let $t05626256501 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1296- let remainMargin = $t05626256501._1
1297- let x1 = $t05626256501._2
1298- let x2 = $t05626256501._3
1314+ let $t05706757306 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1315+ let remainMargin = $t05706757306._1
1316+ let x1 = $t05706757306._2
1317+ let x2 = $t05706757306._3
12991318 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
13001319 then throw("Over max spread limit")
13011320 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13021321 then throw("Over max open notional")
13031322 else $Tuple12(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13041323 then abs(amountBaseAssetBought)
13051324 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13061325 then abs(amountBaseAssetBought)
13071326 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter)
13081327 }
13091328 }
13101329 else {
13111330 let openNotional = muld(_amount, _leverage)
1312- let $t05776057876 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1313- let oldPositionNotional = $t05776057876._1
1314- let unrealizedPnl = $t05776057876._2
1331+ let $t05856558681 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1332+ let oldPositionNotional = $t05856558681._1
1333+ let unrealizedPnl = $t05856558681._2
13151334 if ((oldPositionNotional > openNotional))
13161335 then throw("Use decreasePosition to decrease position size")
13171336 else throw("Close position first")
13181337 }
1319- let newPositionSize = $t05501958060._1
1320- let newPositionRemainMargin = $t05501958060._2
1321- let newPositionOpenNotional = $t05501958060._3
1322- let newPositionLatestCPF = $t05501958060._4
1323- let baseAssetReserveAfter = $t05501958060._5
1324- let quoteAssetReserveAfter = $t05501958060._6
1325- let totalPositionSizeAfter = $t05501958060._7
1326- let openInterestNotionalAfter = $t05501958060._8
1327- let totalLongAfter = $t05501958060._9
1328- let totalShortAfter = $t05501958060._10
1329- let totalLongOpenInterestAfter = $t05501958060._11
1330- let totalShortOpenInterestAfter = $t05501958060._12
1331- let $t05806658123 = distributeFee(feeAmount)
1332- let feeToStakers = $t05806658123._1
1333- let feeToVault = $t05806658123._2
1338+ let newPositionSize = $t05582458865._1
1339+ let newPositionRemainMargin = $t05582458865._2
1340+ let newPositionOpenNotional = $t05582458865._3
1341+ let newPositionLatestCPF = $t05582458865._4
1342+ let baseAssetReserveAfter = $t05582458865._5
1343+ let quoteAssetReserveAfter = $t05582458865._6
1344+ let totalPositionSizeAfter = $t05582458865._7
1345+ let openInterestNotionalAfter = $t05582458865._8
1346+ let totalLongAfter = $t05582458865._9
1347+ let totalShortAfter = $t05582458865._10
1348+ let totalLongOpenInterestAfter = $t05582458865._11
1349+ let totalShortOpenInterestAfter = $t05582458865._12
1350+ let $t05887158928 = distributeFee(feeAmount)
1351+ let feeToStakers = $t05887158928._1
1352+ let feeToVault = $t05887158928._2
13341353 let stake = if (isQuoteAsset)
13351354 then {
13361355 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
13371356 if ((stake == stake))
13381357 then nil
13391358 else throw("Strict value is not equal to itself.")
13401359 }
13411360 else nil
13421361 if ((stake == stake))
13431362 then {
13441363 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13451364 if ((depositInsurance == depositInsurance))
13461365 then {
13471366 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13481367 if ((notifyFee == notifyFee))
13491368 then {
13501369 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13511370 if ((notifyNotional == notifyNotional))
13521371 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))
13531372 else throw("Strict value is not equal to itself.")
13541373 }
13551374 else throw("Strict value is not equal to itself.")
13561375 }
13571376 else throw("Strict value is not equal to itself.")
13581377 }
13591378 else throw("Strict value is not equal to itself.")
13601379 }
13611380 else throw("Strict value is not equal to itself.")
13621381 }
13631382 else throw("Strict value is not equal to itself.")
13641383 }
13651384 }
13661385 else throw("Strict value is not equal to itself.")
13671386 }
13681387
13691388
13701389
13711390 @Callable(i)
13721391 func addMargin () = {
13731392 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13741393 if ((sync == sync))
13751394 then {
13761395 let _trader = toString(i.caller)
13771396 let _rawAmount = i.payments[0].amount
13781397 let _assetId = i.payments[0].assetId
13791398 let _assetIdStr = toBase58String(value(_assetId))
13801399 let isQuoteAsset = (_assetId == quoteAsset())
13811400 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
13821401 if (if (if (if (if (if (if (!(isQuoteAsset))
13831402 then !(isCollateralAsset)
13841403 else false)
13851404 then true
13861405 else !(requireOpenPosition(toString(i.caller))))
13871406 then true
13881407 else !(isSameAsset(_trader, _assetIdStr)))
13891408 then true
13901409 else !(initialized()))
13911410 then true
13921411 else paused())
13931412 then true
13941413 else closeOnly())
13951414 then throw("Invalid addMargin parameters")
13961415 else {
1397- let $t06007160156 = getForTraderWithArtifact(_trader, getArtifactId(i))
1398- let adjustedFee = $t06007160156._1
1399- let burnArtifact = $t06007160156._2
1416+ let $t06087660961 = getForTraderWithArtifact(_trader, getArtifactId(i))
1417+ let adjustedFee = $t06087660961._1
1418+ let burnArtifact = $t06087660961._2
14001419 let rawFeeAmount = muld(_rawAmount, adjustedFee)
14011420 let _amount = (_rawAmount - rawFeeAmount)
14021421 let distributeFeeAmount = if (isCollateralAsset)
14031422 then {
14041423 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
14051424 if ((doBorrow == doBorrow))
14061425 then {
14071426 let balanceBefore = assetBalance(this, quoteAsset())
14081427 if ((balanceBefore == balanceBefore))
14091428 then {
14101429 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
14111430 if ((doSwap == doSwap))
14121431 then {
14131432 let balanceAfter = assetBalance(this, quoteAsset())
14141433 if ((balanceAfter == balanceAfter))
14151434 then {
14161435 let exchangedAmount = (balanceAfter - balanceBefore)
14171436 if ((exchangedAmount == exchangedAmount))
14181437 then exchangedAmount
14191438 else throw("Strict value is not equal to itself.")
14201439 }
14211440 else throw("Strict value is not equal to itself.")
14221441 }
14231442 else throw("Strict value is not equal to itself.")
14241443 }
14251444 else throw("Strict value is not equal to itself.")
14261445 }
14271446 else throw("Strict value is not equal to itself.")
14281447 }
14291448 else rawFeeAmount
14301449 if ((distributeFeeAmount == distributeFeeAmount))
14311450 then {
14321451 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
14331452 if ((referrerFeeAny == referrerFeeAny))
14341453 then {
14351454 let referrerFee = match referrerFeeAny {
14361455 case x: Int =>
14371456 x
14381457 case _ =>
14391458 throw("Invalid referrerFee")
14401459 }
14411460 let feeAmount = (distributeFeeAmount - referrerFee)
1442- let $t06145561595 = getPosition(_trader)
1443- let oldPositionSize = $t06145561595._1
1444- let oldPositionMargin = $t06145561595._2
1445- let oldPositionOpenNotional = $t06145561595._3
1446- let oldPositionLstUpdCPF = $t06145561595._4
1447- let $t06160161658 = distributeFee(feeAmount)
1448- let feeToStakers = $t06160161658._1
1449- let feeToVault = $t06160161658._2
1461+ let $t06226062400 = getPosition(_trader)
1462+ let oldPositionSize = $t06226062400._1
1463+ let oldPositionMargin = $t06226062400._2
1464+ let oldPositionOpenNotional = $t06226062400._3
1465+ let oldPositionLstUpdCPF = $t06226062400._4
1466+ let $t06240662463 = distributeFee(feeAmount)
1467+ let feeToStakers = $t06240662463._1
1468+ let feeToVault = $t06240662463._2
14501469 let stake = if (isQuoteAsset)
14511470 then {
14521471 let stake = invoke(vaultAddress(), "addLocked", [false], [AttachedPayment(quoteAsset(), _amount)])
14531472 if ((stake == stake))
14541473 then nil
14551474 else throw("Strict value is not equal to itself.")
14561475 }
14571476 else nil
14581477 if ((stake == stake))
14591478 then {
14601479 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
14611480 if ((depositInsurance == depositInsurance))
14621481 then {
14631482 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
14641483 if ((notifyFee == notifyFee))
14651484 then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
14661485 else throw("Strict value is not equal to itself.")
14671486 }
14681487 else throw("Strict value is not equal to itself.")
14691488 }
14701489 else throw("Strict value is not equal to itself.")
14711490 }
14721491 else throw("Strict value is not equal to itself.")
14731492 }
14741493 else throw("Strict value is not equal to itself.")
14751494 }
14761495 }
14771496 else throw("Strict value is not equal to itself.")
14781497 }
14791498
14801499
14811500
14821501 @Callable(i)
14831502 func removeMargin (_amount) = {
14841503 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14851504 if ((sync == sync))
14861505 then {
14871506 let _trader = toString(i.caller)
14881507 if (if (if (if ((0 >= _amount))
14891508 then true
14901509 else !(requireOpenPosition(_trader)))
14911510 then true
14921511 else !(initialized()))
14931512 then true
14941513 else paused())
14951514 then throw("Invalid removeMargin parameters")
14961515 else {
1497- let $t06277062910 = getPosition(_trader)
1498- let oldPositionSize = $t06277062910._1
1499- let oldPositionMargin = $t06277062910._2
1500- let oldPositionOpenNotional = $t06277062910._3
1501- let oldPositionLstUpdCPF = $t06277062910._4
1516+ let $t06357563715 = getPosition(_trader)
1517+ let oldPositionSize = $t06357563715._1
1518+ let oldPositionMargin = $t06357563715._2
1519+ let oldPositionOpenNotional = $t06357563715._3
1520+ let oldPositionLstUpdCPF = $t06357563715._4
15021521 let marginDelta = -(_amount)
1503- let $t06294763126 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1504- let remainMargin = $t06294763126._1
1505- let badDebt = $t06294763126._2
1522+ let $t06375263931 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1523+ let remainMargin = $t06375263931._1
1524+ let badDebt = $t06375263931._2
15061525 if ((badDebt != 0))
15071526 then throw("Invalid removed margin amount")
15081527 else {
15091528 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
15101529 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
15111530 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
15121531 else {
15131532 let quoteAssetStr = toBase58String(quoteAsset())
1514- let $t06357063624 = getBorrowedByTrader(_trader)
1515- let borrowed = $t06357063624._1
1516- let assetId = $t06357063624._2
1533+ let $t06437564429 = getBorrowedByTrader(_trader)
1534+ let borrowed = $t06437564429._1
1535+ let assetId = $t06437564429._2
15171536 let toRepay = if ((_amount > borrowed))
15181537 then borrowed
15191538 else _amount
15201539 let toWithdraw = if ((borrowed > _amount))
15211540 then 0
15221541 else (_amount - borrowed)
15231542 let finalBorrow = (borrowed - toRepay)
15241543 let switchPositionToQuote = if ((finalBorrow > 0))
15251544 then nil
15261545 else updatePositionAsset(_trader, quoteAssetStr)
15271546 let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
15281547 then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
15291548 else nil
15301549 if ((doSanityCheck == doSanityCheck))
15311550 then {
15321551 let doUnstake = if ((toWithdraw > 0))
15331552 then {
15341553 let doUnstake = invoke(vaultAddress(), "withdrawLocked", [toWithdraw], nil)
15351554 if ((doUnstake == doUnstake))
15361555 then nil
15371556 else throw("Strict value is not equal to itself.")
15381557 }
15391558 else nil
15401559 if ((doUnstake == doUnstake))
15411560 then {
15421561 let returnCollateralAction = if ((toRepay > 0))
15431562 then {
15441563 let doRepay = invoke(collateralAddress(), "repay", [_trader, toRepay, assetId], nil)
15451564 if ((doRepay == doRepay))
15461565 then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
15471566 else throw("Strict value is not equal to itself.")
15481567 }
15491568 else nil
15501569 if ((returnCollateralAction == returnCollateralAction))
15511570 then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
15521571 then withdraw(i.caller, toWithdraw)
15531572 else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
15541573 else throw("Strict value is not equal to itself.")
15551574 }
15561575 else throw("Strict value is not equal to itself.")
15571576 }
15581577 else throw("Strict value is not equal to itself.")
15591578 }
15601579 }
15611580 }
15621581 }
15631582 else throw("Strict value is not equal to itself.")
15641583 }
15651584
15661585
15671586
15681587 @Callable(i)
15691588 func closePosition (_size,_minQuoteAssetAmount) = {
15701589 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15711590 if ((sync == sync))
15721591 then {
15731592 let _trader = getActualCaller(i)
15741593 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
15751594 if (if (if (if (if (!(requireOpenPosition(_trader)))
15761595 then true
15771596 else !(initialized()))
15781597 then true
15791598 else paused())
15801599 then true
15811600 else (0 >= _size))
15821601 then true
15831602 else (0 > _minQuoteAssetAmount))
15841603 then throw("Invalid closePosition parameters")
15851604 else {
1586- let $t06578265922 = getPosition(_trader)
1587- let oldPositionSize = $t06578265922._1
1588- let oldPositionMargin = $t06578265922._2
1589- let oldPositionOpenNotional = $t06578265922._3
1590- let oldPositionLstUpdCPF = $t06578265922._4
1591- let $t06592870365 = if ((abs(oldPositionSize) > _size))
1605+ let $t06658766727 = getPosition(_trader)
1606+ let oldPositionSize = $t06658766727._1
1607+ let oldPositionMargin = $t06658766727._2
1608+ let oldPositionOpenNotional = $t06658766727._3
1609+ let oldPositionLstUpdCPF = $t06658766727._4
1610+ let $t06673371170 = if ((abs(oldPositionSize) > _size))
15921611 then {
15931612 let _direction = if ((oldPositionSize > 0))
15941613 then DIR_SHORT
15951614 else DIR_LONG
15961615 let isAdd = (_direction == DIR_LONG)
1597- let $t06651966741 = swapOutput((oldPositionSize > 0), _size, true)
1598- let exchangedQuoteAssetAmount = $t06651966741._1
1599- let quoteAssetReserveAfter = $t06651966741._2
1600- let baseAssetReserveAfter = $t06651966741._3
1601- let totalPositionSizeAfter = $t06651966741._4
1616+ let $t06732467546 = swapOutput((oldPositionSize > 0), _size, true)
1617+ let exchangedQuoteAssetAmount = $t06732467546._1
1618+ let quoteAssetReserveAfter = $t06732467546._2
1619+ let baseAssetReserveAfter = $t06732467546._3
1620+ let totalPositionSizeAfter = $t06732467546._4
16021621 let exchangedPositionSize = if ((oldPositionSize > 0))
16031622 then -(_size)
16041623 else _size
1605- let $t06683266986 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1606- let oldPositionNotional = $t06683266986._1
1607- let unrealizedPnl = $t06683266986._2
1624+ let $t06763767791 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1625+ let oldPositionNotional = $t06763767791._1
1626+ let unrealizedPnl = $t06763767791._2
16081627 let mr = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
16091628 let realizedRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
16101629 let realizedPnl = muld(unrealizedPnl, realizedRatio)
1611- let $t06726567503 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1612- let remainMargin = $t06726567503._1
1613- let positionBadDebt = $t06726567503._2
1614- let fundingPayment = $t06726567503._3
1630+ let $t06807068308 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1631+ let remainMargin = $t06807068308._1
1632+ let positionBadDebt = $t06807068308._2
1633+ let fundingPayment = $t06807068308._3
16151634 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
16161635 let remainOpenNotional = if ((oldPositionSize > 0))
16171636 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
16181637 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
16191638 let newPositionOpenNotional = abs(remainOpenNotional)
16201639 let newPositionMargin = muld(newPositionOpenNotional, mr)
16211640 let newPositionSize = (oldPositionSize + exchangedPositionSize)
16221641 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
16231642 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
16241643 if (if ((_minQuoteAssetAmount != 0))
16251644 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16261645 else false)
16271646 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
16281647 else $Tuple15(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, (abs((remainMargin - newPositionMargin)) + realizedPnl), quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16291648 then abs(exchangedPositionSize)
16301649 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16311650 then abs(exchangedPositionSize)
16321651 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
16331652 then exchangedQuoteAssetAmount
16341653 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
16351654 then exchangedQuoteAssetAmount
16361655 else 0)))
16371656 }
16381657 else if ((_size > abs(oldPositionSize)))
16391658 then throw("Invalid closePosition parameters")
16401659 else {
1641- let $t06930669725 = internalClosePosition(_trader, true)
1642- let exchangedQuoteAssetAmount = $t06930669725._1
1643- let positionBadDebt = $t06930669725._2
1644- let realizedPnl = $t06930669725._3
1645- let marginToVault = $t06930669725._4
1646- let quoteAssetReserveAfter = $t06930669725._5
1647- let baseAssetReserveAfter = $t06930669725._6
1648- let totalPositionSizeAfter = $t06930669725._7
1649- let openInterestNotionalAfter = $t06930669725._8
1650- let x2 = $t06930669725._9
1651- let totalLongAfter = $t06930669725._10
1652- let totalShortAfter = $t06930669725._11
1653- let totalLongOpenInterestAfter = $t06930669725._12
1654- let totalShortOpenInterestAfter = $t06930669725._13
1660+ let $t07011170530 = internalClosePosition(_trader, true)
1661+ let exchangedQuoteAssetAmount = $t07011170530._1
1662+ let positionBadDebt = $t07011170530._2
1663+ let realizedPnl = $t07011170530._3
1664+ let marginToVault = $t07011170530._4
1665+ let quoteAssetReserveAfter = $t07011170530._5
1666+ let baseAssetReserveAfter = $t07011170530._6
1667+ let totalPositionSizeAfter = $t07011170530._7
1668+ let openInterestNotionalAfter = $t07011170530._8
1669+ let x2 = $t07011170530._9
1670+ let totalLongAfter = $t07011170530._10
1671+ let totalShortAfter = $t07011170530._11
1672+ let totalLongOpenInterestAfter = $t07011170530._12
1673+ let totalShortOpenInterestAfter = $t07011170530._13
16551674 if (if ((_minQuoteAssetAmount != 0))
16561675 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
16571676 else false)
16581677 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
16591678 else $Tuple15(0, 0, 0, 0, positionBadDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)
16601679 }
1661- let newPositionSize = $t06592870365._1
1662- let newPositionMargin = $t06592870365._2
1663- let newPositionOpenNotional = $t06592870365._3
1664- let newPositionLstUpdCPF = $t06592870365._4
1665- let positionBadDebt = $t06592870365._5
1666- let realizedPnl = $t06592870365._6
1667- let marginToVault = $t06592870365._7
1668- let quoteAssetReserveAfter = $t06592870365._8
1669- let baseAssetReserveAfter = $t06592870365._9
1670- let totalPositionSizeAfter = $t06592870365._10
1671- let openInterestNotionalAfter = $t06592870365._11
1672- let totalLongAfter = $t06592870365._12
1673- let totalShortAfter = $t06592870365._13
1674- let totalLongOpenInterestAfter = $t06592870365._14
1675- let totalShortOpenInterestAfter = $t06592870365._15
1680+ let newPositionSize = $t06673371170._1
1681+ let newPositionMargin = $t06673371170._2
1682+ let newPositionOpenNotional = $t06673371170._3
1683+ let newPositionLstUpdCPF = $t06673371170._4
1684+ let positionBadDebt = $t06673371170._5
1685+ let realizedPnl = $t06673371170._6
1686+ let marginToVault = $t06673371170._7
1687+ let quoteAssetReserveAfter = $t06673371170._8
1688+ let baseAssetReserveAfter = $t06673371170._9
1689+ let totalPositionSizeAfter = $t06673371170._10
1690+ let openInterestNotionalAfter = $t06673371170._11
1691+ let totalLongAfter = $t06673371170._12
1692+ let totalShortAfter = $t06673371170._13
1693+ let totalLongOpenInterestAfter = $t06673371170._14
1694+ let totalShortOpenInterestAfter = $t06673371170._15
16761695 if ((positionBadDebt > 0))
16771696 then throw("Unable to close position with bad debt")
16781697 else {
16791698 let withdrawAmount = abs(marginToVault)
16801699 let ammBalance = (cbalance() - withdrawAmount)
1681- let $t07057470781 = if ((0 > ammBalance))
1700+ let $t07137971586 = if ((0 > ammBalance))
16821701 then $Tuple2(0, abs(ammBalance))
16831702 else $Tuple2(ammBalance, 0)
1684- let ammNewBalance = $t07057470781._1
1685- let x11 = $t07057470781._2
1686- let $t07078870842 = getBorrowedByTrader(_trader)
1687- let borrowed = $t07078870842._1
1688- let assetId = $t07078870842._2
1689- let $t07085771716 = if ((borrowed > 0))
1703+ let ammNewBalance = $t07137971586._1
1704+ let x11 = $t07137971586._2
1705+ let $t07159371647 = getBorrowedByTrader(_trader)
1706+ let borrowed = $t07159371647._1
1707+ let assetId = $t07159371647._2
1708+ let $t07166272521 = if ((borrowed > 0))
16901709 then if ((withdrawAmount >= borrowed))
16911710 then {
16921711 let doRepay = invoke(collateralAddress(), "repay", [_trader, borrowed, assetId], nil)
16931712 if ((doRepay == doRepay))
16941713 then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
16951714 else throw("Strict value is not equal to itself.")
16961715 }
16971716 else {
16981717 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, withdrawAmount, assetId], nil)
16991718 if ((realizeAndClose == realizeAndClose))
17001719 then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
17011720 else throw("Strict value is not equal to itself.")
17021721 }
17031722 else $Tuple2(nil, withdrawAmount)
1704- if (($t07085771716 == $t07085771716))
1723+ if (($t07166272521 == $t07166272521))
17051724 then {
1706- let quoteWithdrawAmount = $t07085771716._2
1707- let sendCollateralAction = $t07085771716._1
1725+ let quoteWithdrawAmount = $t07166272521._2
1726+ let sendCollateralAction = $t07166272521._1
17081727 let unstake = if ((quoteWithdrawAmount > 0))
17091728 then {
17101729 let unstake = invoke(vaultAddress(), "withdrawLocked", [quoteWithdrawAmount], nil)
17111730 if ((unstake == unstake))
17121731 then nil
17131732 else throw("Strict value is not equal to itself.")
17141733 }
17151734 else nil
17161735 if ((unstake == unstake))
17171736 then {
17181737 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
17191738 if ((notifyNotional == notifyNotional))
17201739 then (((((if ((newPositionSize == 0))
17211740 then deletePosition(_trader)
17221741 else updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((quoteWithdrawAmount > 0))
17231742 then withdraw(_traderAddress, quoteWithdrawAmount)
17241743 else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
17251744 else throw("Strict value is not equal to itself.")
17261745 }
17271746 else throw("Strict value is not equal to itself.")
17281747 }
17291748 else throw("Strict value is not equal to itself.")
17301749 }
17311750 }
17321751 }
17331752 else throw("Strict value is not equal to itself.")
17341753 }
17351754
17361755
17371756
17381757 @Callable(i)
17391758 func liquidate (_trader) = {
17401759 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17411760 if ((sync == sync))
17421761 then {
17431762 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
17441763 let marginRatio = if (isOverFluctuationLimit())
17451764 then {
17461765 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
17471766 vmax(spotMarginRatio, oracleMarginRatio)
17481767 }
17491768 else spotMarginRatio
17501769 if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
17511770 then true
17521771 else !(requireOpenPosition(_trader)))
17531772 then true
17541773 else !(initialized()))
17551774 then true
17561775 else paused())
17571776 then throw("Unable to liquidate")
17581777 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
17591778 then (partialLiquidationRatio() > 0)
17601779 else false)
17611780 then (DECIMAL_UNIT > partialLiquidationRatio())
17621781 else false)
17631782 then {
1764- let $t07401374163 = getPosition(_trader)
1765- let oldPositionSize = $t07401374163._1
1766- let oldPositionMargin = $t07401374163._2
1767- let oldPositionOpenNotional = $t07401374163._3
1768- let oldPositionLstUpdCPF = $t07401374163._4
1783+ let $t07481874968 = getPosition(_trader)
1784+ let oldPositionSize = $t07481874968._1
1785+ let oldPositionMargin = $t07481874968._2
1786+ let oldPositionOpenNotional = $t07481874968._3
1787+ let oldPositionLstUpdCPF = $t07481874968._4
17691788 let _direction = if ((oldPositionSize > 0))
17701789 then DIR_SHORT
17711790 else DIR_LONG
17721791 let isAdd = (_direction == DIR_LONG)
17731792 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1774- let $t07438874492 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1775- let oldPositionNotional = $t07438874492._1
1776- let unrealizedPnl = $t07438874492._2
1777- let $t07450074687 = swapInput(isAdd, exchangedQuoteAssetAmount)
1778- let exchangedPositionSize = $t07450074687._1
1779- let quoteAssetReserveAfter = $t07450074687._2
1780- let baseAssetReserveAfter = $t07450074687._3
1781- let totalPositionSizeAfter = $t07450074687._4
1793+ let $t07519375297 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1794+ let oldPositionNotional = $t07519375297._1
1795+ let unrealizedPnl = $t07519375297._2
1796+ let $t07530575492 = swapInput(isAdd, exchangedQuoteAssetAmount)
1797+ let exchangedPositionSize = $t07530575492._1
1798+ let quoteAssetReserveAfter = $t07530575492._2
1799+ let baseAssetReserveAfter = $t07530575492._3
1800+ let totalPositionSizeAfter = $t07530575492._4
17821801 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
17831802 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1784- let $t07497675209 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1785- let remainMargin = $t07497675209._1
1786- let badDebt = $t07497675209._2
1787- let fundingPayment = $t07497675209._3
1803+ let $t07578176014 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1804+ let remainMargin = $t07578176014._1
1805+ let badDebt = $t07578176014._2
1806+ let fundingPayment = $t07578176014._3
17881807 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
17891808 let remainOpenNotional = if ((oldPositionSize > 0))
17901809 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
17911810 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
17921811 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
17931812 let feeToLiquidator = (liquidationPenalty / 2)
17941813 let feeToVault = (liquidationPenalty - feeToLiquidator)
17951814 let newPositionMargin = (remainMargin - liquidationPenalty)
17961815 let newPositionSize = (oldPositionSize + exchangedPositionSize)
17971816 let newPositionOpenNotional = abs(remainOpenNotional)
17981817 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
17991818 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
18001819 let ammBalance = (cbalance() - liquidationPenalty)
1801- let $t07637876507 = if ((0 > ammBalance))
1820+ let $t07718377312 = if ((0 > ammBalance))
18021821 then $Tuple2(0, abs(ammBalance))
18031822 else $Tuple2(ammBalance, 0)
1804- let newAmmBalance = $t07637876507._1
1805- let x11 = $t07637876507._2
1806- let $t07651576569 = getBorrowedByTrader(_trader)
1807- let borrowed = $t07651576569._1
1808- let assetId = $t07651576569._2
1823+ let newAmmBalance = $t07718377312._1
1824+ let x11 = $t07718377312._2
1825+ let $t07732077374 = getBorrowedByTrader(_trader)
1826+ let borrowed = $t07732077374._1
1827+ let assetId = $t07732077374._2
18091828 let doLiquidateCollateral = if ((borrowed > 0))
18101829 then {
18111830 let collateralToSell = muld(borrowed, liquidationRatio)
18121831 let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
18131832 if ((realizeAndClose == realizeAndClose))
18141833 then nil
18151834 else throw("Strict value is not equal to itself.")
18161835 }
18171836 else nil
18181837 if ((doLiquidateCollateral == doLiquidateCollateral))
18191838 then {
18201839 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
18211840 if ((unstake == unstake))
18221841 then {
18231842 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
18241843 if ((depositInsurance == depositInsurance))
18251844 then {
18261845 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
18271846 if ((notifyNotional == notifyNotional))
18281847 then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
18291848 then abs(exchangedPositionSize)
18301849 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
18311850 then abs(exchangedPositionSize)
18321851 else 0)), (openInterestLong() - (if ((newPositionSize > 0))
18331852 then exchangedQuoteAssetAmount
18341853 else 0)), (openInterestShort() - (if ((0 > newPositionSize))
18351854 then exchangedQuoteAssetAmount
18361855 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
18371856 else throw("Strict value is not equal to itself.")
18381857 }
18391858 else throw("Strict value is not equal to itself.")
18401859 }
18411860 else throw("Strict value is not equal to itself.")
18421861 }
18431862 else throw("Strict value is not equal to itself.")
18441863 }
18451864 else {
1846- let $t07826478759 = internalClosePosition(_trader, false)
1847- let x1 = $t07826478759._1
1848- let badDebt = $t07826478759._2
1849- let x2 = $t07826478759._3
1850- let x3 = $t07826478759._4
1851- let quoteAssetReserveAfter = $t07826478759._5
1852- let baseAssetReserveAfter = $t07826478759._6
1853- let totalPositionSizeAfter = $t07826478759._7
1854- let openInterestNotionalAfter = $t07826478759._8
1855- let exchangedQuoteAssetAmount = $t07826478759._9
1856- let totalLongAfter = $t07826478759._10
1857- let totalShortAfter = $t07826478759._11
1858- let totalLongOpenInterestAfter = $t07826478759._12
1859- let totalShortOpenInterestAfter = $t07826478759._13
1865+ let $t07906979564 = internalClosePosition(_trader, false)
1866+ let x1 = $t07906979564._1
1867+ let badDebt = $t07906979564._2
1868+ let x2 = $t07906979564._3
1869+ let x3 = $t07906979564._4
1870+ let quoteAssetReserveAfter = $t07906979564._5
1871+ let baseAssetReserveAfter = $t07906979564._6
1872+ let totalPositionSizeAfter = $t07906979564._7
1873+ let openInterestNotionalAfter = $t07906979564._8
1874+ let exchangedQuoteAssetAmount = $t07906979564._9
1875+ let totalLongAfter = $t07906979564._10
1876+ let totalShortAfter = $t07906979564._11
1877+ let totalLongOpenInterestAfter = $t07906979564._12
1878+ let totalShortOpenInterestAfter = $t07906979564._13
18601879 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
18611880 let feeToLiquidator = (liquidationPenalty / 2)
18621881 let feeToVault = (liquidationPenalty - feeToLiquidator)
18631882 let ammBalance = (cbalance() - liquidationPenalty)
1864- let $t07916779296 = if ((0 > ammBalance))
1883+ let $t07997280101 = if ((0 > ammBalance))
18651884 then $Tuple2(0, abs(ammBalance))
18661885 else $Tuple2(ammBalance, 0)
1867- let newAmmBalance = $t07916779296._1
1868- let x11 = $t07916779296._2
1869- let $t07930479358 = getBorrowedByTrader(_trader)
1870- let borrowed = $t07930479358._1
1871- let assetId = $t07930479358._2
1886+ let newAmmBalance = $t07997280101._1
1887+ let x11 = $t07997280101._2
1888+ let $t08010980163 = getBorrowedByTrader(_trader)
1889+ let borrowed = $t08010980163._1
1890+ let assetId = $t08010980163._2
18721891 let doLiquidateCollateral = if ((borrowed > 0))
18731892 then {
18741893 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, 0, assetId], nil)
18751894 if ((realizeAndClose == realizeAndClose))
18761895 then nil
18771896 else throw("Strict value is not equal to itself.")
18781897 }
18791898 else nil
18801899 if ((doLiquidateCollateral == doLiquidateCollateral))
18811900 then {
18821901 let x = if ((badDebt > 0))
18831902 then {
18841903 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
18851904 if ((lockBadDebt == lockBadDebt))
18861905 then nil
18871906 else throw("Strict value is not equal to itself.")
18881907 }
18891908 else nil
18901909 if ((x == x))
18911910 then {
18921911 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
18931912 if ((unstake == unstake))
18941913 then {
18951914 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
18961915 if ((depositInsurance == depositInsurance))
18971916 then {
18981917 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
18991918 if ((notifyNotional == notifyNotional))
19001919 then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
19011920 else throw("Strict value is not equal to itself.")
19021921 }
19031922 else throw("Strict value is not equal to itself.")
19041923 }
19051924 else throw("Strict value is not equal to itself.")
19061925 }
19071926 else throw("Strict value is not equal to itself.")
19081927 }
19091928 else throw("Strict value is not equal to itself.")
19101929 }
19111930 }
19121931 else throw("Strict value is not equal to itself.")
19131932 }
19141933
19151934
19161935
19171936 @Callable(i)
19181937 func payFunding () = {
19191938 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19201939 if ((sync == sync))
19211940 then {
19221941 let fundingBlockTimestamp = nextFundingBlockTimestamp()
19231942 if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
19241943 then true
19251944 else !(initialized()))
19261945 then true
19271946 else paused())
19281947 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
19291948 else {
19301949 let underlyingPrice = getOracleTwapPrice()
1931- let $t08123481296 = getFunding()
1932- let shortPremiumFraction = $t08123481296._1
1933- let longPremiumFraction = $t08123481296._2
1950+ let $t08203982101 = getFunding()
1951+ let shortPremiumFraction = $t08203982101._1
1952+ let longPremiumFraction = $t08203982101._2
19341953 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
19351954 }
19361955 }
19371956 else throw("Strict value is not equal to itself.")
19381957 }
19391958
19401959
19411960
19421961 @Callable(i)
19431962 func syncTerminalPriceToOracle () = {
1944- let $t08167881799 = getSyncTerminalPrice(getOracleTwapPrice())
1945- let newQuoteAssetWeight = $t08167881799._1
1946- let newBaseAssetWeight = $t08167881799._2
1947- let marginToVault = $t08167881799._3
1963+ let _qtAstR = qtAstR()
1964+ let _bsAstR = bsAstR()
1965+ let $t08253382672 = getSyncTerminalPrice(getOracleTwapPrice(), _qtAstR, _bsAstR)
1966+ let newQuoteAssetWeight = $t08253382672._1
1967+ let newBaseAssetWeight = $t08253382672._2
1968+ let marginToVault = $t08253382672._3
19481969 let doExchangePnL = if ((marginToVault != 0))
19491970 then {
19501971 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
19511972 if ((doExchangePnL == doExchangePnL))
19521973 then nil
19531974 else throw("Strict value is not equal to itself.")
19541975 }
19551976 else nil
19561977 if ((doExchangePnL == doExchangePnL))
1957- then {
1958- let _qtAstR = qtAstR()
1959- let _bsAstR = bsAstR()
1960- (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
1961- }
1978+ then (updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight) ++ appendTwap(divd(muld(_qtAstR, newQuoteAssetWeight), muld(_bsAstR, newBaseAssetWeight))))
19621979 else throw("Strict value is not equal to itself.")
19631980 }
19641981
19651982
19661983
19671984 @Callable(i)
19681985 func view_calcRemainMarginWithFundingPayment (_trader) = {
19691986 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19701987 if ((sync == sync))
19711988 then {
1972- let $t08241982520 = getPosition(_trader)
1973- let positionSize = $t08241982520._1
1974- let positionMargin = $t08241982520._2
1975- let pon = $t08241982520._3
1976- let positionLstUpdCPF = $t08241982520._4
1977- let $t08252382624 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1978- let positionNotional = $t08252382624._1
1979- let unrealizedPnl = $t08252382624._2
1980- let $t08262782799 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1981- let remainMargin = $t08262782799._1
1982- let badDebt = $t08262782799._2
1983- let fundingPayment = $t08262782799._3
1989+ let $t08324183342 = getPosition(_trader)
1990+ let positionSize = $t08324183342._1
1991+ let positionMargin = $t08324183342._2
1992+ let pon = $t08324183342._3
1993+ let positionLstUpdCPF = $t08324183342._4
1994+ let $t08334583446 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1995+ let positionNotional = $t08334583446._1
1996+ let unrealizedPnl = $t08334583446._2
1997+ let $t08344983621 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1998+ let remainMargin = $t08344983621._1
1999+ let badDebt = $t08344983621._2
2000+ let fundingPayment = $t08344983621._3
19842001 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
19852002 }
19862003 else throw("Strict value is not equal to itself.")
19872004 }
19882005
19892006
19902007
19912008 @Callable(i)
19922009 func view_getPegAdjustCost (_price) = {
1993- let result = getSyncTerminalPrice(_price)
2010+ let _qtAstR = qtAstR()
2011+ let _bsAstR = bsAstR()
2012+ let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
19942013 throw(toString(result._3))
19952014 }
19962015
19972016
19982017
19992018 @Callable(i)
20002019 func view_getTerminalAmmPrice () = {
2001- let $t08314683227 = getTerminalAmmState()
2002- let terminalQuoteAssetReserve = $t08314683227._1
2003- let terminalBaseAssetReserve = $t08314683227._2
2020+ let $t08403784118 = getTerminalAmmState()
2021+ let terminalQuoteAssetReserve = $t08403784118._1
2022+ let terminalBaseAssetReserve = $t08403784118._2
20042023 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
20052024 throw(toString(price))
20062025 }
20072026
20082027
20092028
20102029 @Callable(i)
20112030 func view_getFunding () = {
20122031 let underlyingPrice = getOracleTwapPrice()
2013- let $t08344683508 = getFunding()
2014- let shortPremiumFraction = $t08344683508._1
2015- let longPremiumFraction = $t08344683508._2
2032+ let $t08433784399 = getFunding()
2033+ let shortPremiumFraction = $t08433784399._1
2034+ let longPremiumFraction = $t08433784399._2
20162035 let longFunding = divd(longPremiumFraction, underlyingPrice)
20172036 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
20182037 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
20192038 }
20202039
20212040
20222041
20232042 @Callable(i)
20242043 func view_getBorrowedByTrader (_trader) = {
2025- let $t08379883852 = getBorrowedByTrader(_trader)
2026- let borrowed = $t08379883852._1
2027- let assetId = $t08379883852._2
2044+ let $t08468984743 = getBorrowedByTrader(_trader)
2045+ let borrowed = $t08468984743._1
2046+ let assetId = $t08468984743._2
20282047 throw((s(borrowed) + assetId))
20292048 }
20302049
20312050
20322051
20332052 @Callable(i)
20342053 func computeSpotPrice () = {
20352054 let result = getSpotPrice()
20362055 $Tuple2(nil, result)
20372056 }
20382057
20392058
20402059
20412060 @Callable(i)
20422061 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
20432062 let result = getForTraderWithArtifact(_trader, _artifactId)
20442063 $Tuple2(nil, result)
20452064 }
20462065
20472066
20482067 @Verifier(tx)
20492068 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
20502069

github/deemru/w8io/026f985 
270.81 ms