tx · J7uKdaq1NavAeqpr1qshcZMfEx9sZ3mPT65fzBXvvu8G

3MtMZPVohRyxckRk11RZM4geun6itShmcXy:  -0.07000000 Waves

2022.11.29 21:25 [2338746] smart account 3MtMZPVohRyxckRk11RZM4geun6itShmcXy > SELF 0.00000000 Waves

{ "type": 13, "id": "J7uKdaq1NavAeqpr1qshcZMfEx9sZ3mPT65fzBXvvu8G", "fee": 7000000, "feeAssetId": null, "timestamp": 1669746306132, "version": 2, "chainId": 84, "sender": "3MtMZPVohRyxckRk11RZM4geun6itShmcXy", "senderPublicKey": "AcX4fkfjTbNodAULoBzLJcZwKsACkfzdq78cpEww7RP8", "proofs": [ "wqTyYKkkACziZGyEF9tBasbzFgVNurnmg8sL7NsaxVoXFX1q8XYdHoDWiSi5Q4bSvkkp47aiAAj3zVsMh3w58nN" ], "script": "base64:BgJtCAISABIAEgMKAQESAwoBARILCgkBAQEBAQEBAQESEAoOAQEBAQEBAQgICAEBAQESAwoBARIFCgMBAQESBgoEAQEBCBIAEgMKAQESABIDCgEIEgASABIDCgEIEgMKAQgSAwoBARIAEgASAwoBCLABAAlrX29yYV9rZXkCCWtfb3JhX2tleQAPa19vcmFfYmxvY2tfa2V5Ag9rX29yYV9ibG9ja19rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uABRrX3Bvc2l0aW9uQ2xvc2VkRGF0ZQIUa19wb3NpdGlvbkNsb3NlZERhdGUAD2tfcG9zaXRpb25Bc3NldAIPa19wb3NpdGlvbkFzc2V0AA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQABWtfZmVlAgVrX2ZlZQAPa19mdW5kaW5nUGVyaW9kAg9rX2Z1bmRpbmdQZXJpb2QAEWtfaW5pdE1hcmdpblJhdGlvAhFrX2luaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8AGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8CFmtfcGFydExpcXVpZGF0aW9uUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QAEGtfbWF4UHJpY2VTcHJlYWQCEGtfbWF4UHJpY2VTcHJlYWQADWtfbGFzdERhdGFTdHICDWtfbGFzdERhdGFTdHIADmtfbGFzdE1pbnV0ZUlkAg5rX2xhc3RNaW51dGVJZAAda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlABNrX3R3YXBEYXRhTGFzdFByaWNlAhNrX3R3YXBEYXRhTGFzdFByaWNlABprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAIaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQAJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CG2tfbGF0ZXN0TG9uZ1ByZW1pdW1GcmFjdGlvbgAma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CHGtfbGF0ZXN0U2hvcnRQcmVtaXVtRnJhY3Rpb24AEmtfbmV4dEZ1bmRpbmdCbG9jawIea19uZXh0RnVuZGluZ0Jsb2NrTWluVGltZXN0YW1wABFrX2xvbmdGdW5kaW5nUmF0ZQIRa19sb25nRnVuZGluZ1JhdGUAEmtfc2hvcnRGdW5kaW5nUmF0ZQISa19zaG9ydEZ1bmRpbmdSYXRlABNrX3F1b3RlQXNzZXRSZXNlcnZlAghrX3F0QXN0UgASa19iYXNlQXNzZXRSZXNlcnZlAghrX2JzQXN0UgASa19xdW90ZUFzc2V0V2VpZ2h0AghrX3F0QXN0VwARa19iYXNlQXNzZXRXZWlnaHQCCGtfYnNBc3RXABNrX3RvdGFsUG9zaXRpb25TaXplAhNrX3RvdGFsUG9zaXRpb25TaXplABdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIXa190b3RhbExvbmdQb3NpdGlvblNpemUAGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIYa190b3RhbFNob3J0UG9zaXRpb25TaXplABRrX2N1bXVsYXRpdmVOb3Rpb25hbAIUa19jdW11bGF0aXZlTm90aW9uYWwAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABFrX21hbmFnZXJfYWRkcmVzcwIRa19tYW5hZ2VyX2FkZHJlc3MAFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhRrX2NvbGxhdGVyYWxfYWRkcmVzcwASa19leGNoYW5nZV9hZGRyZXNzAhJrX2V4Y2hhbmdlX2FkZHJlc3MAFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwIVa19uZnRfbWFuYWdlcl9hZGRyZXNzACBrX3RyYWRlcl9tYXJrZXRfYXNzZXRfY29sbGF0ZXJhbAIga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEOYWRtaW5QdWJsaWNLZXkACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfYWRtaW5fcHVibGljX2tleQEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAERcXVvdGVBc3NldFN0YWtpbmcACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19xdW90ZV9zdGFraW5nAhtRdW90ZSBhc3NldCBzdGFraW5nIG5vdCBzZXQBDnN0YWtpbmdBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfc3Rha2luZ19hZGRyZXNzAg9TdGFraW5nIG5vdCBzZXQBDHZhdWx0QWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX3ZhdWx0X2FkZHJlc3MCDVZhdWx0IG5vdCBzZXQBDG1pbmVyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX21pbmVyX2FkZHJlc3MCDU1pbmVyIG5vdCBzZXQBDW9yZGVyc0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUQa19vcmRlcnNfYWRkcmVzcwIOT3JkZXJzIG5vdCBzZXQBD3JlZmVycmFsQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRJrX3JlZmVycmFsX2FkZHJlc3MCEFJlZmVycmFsIG5vdCBzZXQBEW5mdE1hbmFnZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwITTkZUIE1hbmFnZXIgbm90IHNldAERY29sbGF0ZXJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUUa19jb2xsYXRlcmFsX2FkZHJlc3MCGkNvbGxhdGVyYWwgTWFuYWdlciBub3Qgc2V0AQtzd2FwQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBC2Nvb3JkaW5hdG9yAAUSa19leGNoYW5nZV9hZGRyZXNzAg9ObyBzd2FwIGFkZHJlc3MCFEludmFsaWQgc3dhcCBhZGRyZXNzABFrX3doaXRlbGlzdF9hc3NldAIRa193aGl0ZWxpc3RfYXNzZXQBEGlzV2hpdGVsaXN0QXNzZXQBCF9hc3NldElkCQELdmFsdWVPckVsc2UCCQCbCAIJARFjb2xsYXRlcmFsQWRkcmVzcwAJAQ50b0NvbXBvc2l0ZUtleQIFEWtfd2hpdGVsaXN0X2Fzc2V0BQhfYXNzZXRJZAcADWtfdG9rZW5fcGFyYW0CDWtfdG9rZW5fcGFyYW0ADGtfdG9rZW5fdHlwZQIMa190b2tlbl90eXBlABhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUCDWZlZV9yZWR1Y3Rpb24ACERJUl9MT05HAAEACURJUl9TSE9SVAACAA1UV0FQX0lOVEVSVkFMAA8AD09SQUNMRV9JTlRFUlZBTAAPAAdTRUNPTkRTAOgHAA9ERUNJTUFMX05VTUJFUlMABgAMREVDSU1BTF9VTklUCQBoAgABCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoAB09ORV9EQVkJAGgCAICjBQUMREVDSU1BTF9VTklUAAhBTExfRkVFUwBkAA9QTkxfT1BUSU9OX1NQT1QAAQARUE5MX09QVElPTl9PUkFDTEUAAgEBcwECX3gJAKwCAgkApAMBBQJfeAIBLAEEZGl2ZAICX3gCX3kJAG4EBQJfeAUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBG11bGQCAl94Al95CQBuBAUCX3gFAl95BQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQVzcXJ0ZAECX3gJAQRzcXJ0BAUCX3gFD0RFQ0lNQUxfTlVNQkVSUwUPREVDSU1BTF9OVU1CRVJTBQhIQUxGRVZFTgEEcG93ZAICX3gCX3kJAGwGBQJfeAUPREVDSU1BTF9OVU1CRVJTBQJfeQUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQViZGl2ZAICX3gCX3kJAL0CBAUCX3gJALYCAQUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBWJtdWxkAgJfeAJfeQkAvQIEBQJfeAUCX3kJALYCAQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEGYnNxcnRkAQJfeAkBCnNxcnRCaWdJbnQEBQJfeAUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQVicG93ZAICX3gCX3kJAHYGBQJfeAUPREVDSU1BTF9OVU1CRVJTBQJfeQUPREVDSU1BTF9OVU1CRVJTBQ9ERUNJTUFMX05VTUJFUlMFCEhBTEZFVkVOAQNhYnMBAl94AwkAZgIFAl94AAAFAl94CQEBLQEFAl94AQR2bWF4AgJfeAJfeQMJAGcCBQJfeAUCX3kFAl94BQJfeQEJbGlzdFRvU3RyAQVfbGlzdAoBBV9qb2luAgthY2N1bXVsYXRvcgN2YWwJAKwCAgkArAICBQthY2N1bXVsYXRvcgUDdmFsAgEsBApuZXdMaXN0U3RyCgACJGwFBV9saXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVfam9pbgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUBAtuZXdMaXN0U3RyVQkAswICBQpuZXdMaXN0U3RyAAEEC25ld0xpc3RTdHJSAwkAAAIJAK8CAgULbmV3TGlzdFN0clUAAQIBLAkAsAICBQtuZXdMaXN0U3RyVQABBQtuZXdMaXN0U3RyVQULbmV3TGlzdFN0clIBCXN0clRvTGlzdAEEX3N0cgkAtQkCBQRfc3RyAgEsAQtwdXNoVG9RdWV1ZQMFX2xpc3QIX21heFNpemUGX3ZhbHVlAwkAZgIJAJADAQUFX2xpc3QFCF9tYXhTaXplCQDNCAIJANEIAgUFX2xpc3QAAAUGX3ZhbHVlCQDNCAIFBV9saXN0BQZfdmFsdWUBA2ludAEBawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFAWsJAKwCAgINbm8gdmFsdWUgZm9yIAUBawEFaW50T3ICAWsDZGVmCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAWsFA2RlZgEEc3RyQQIIX2FkZHJlc3MEX2tleQQDdmFsCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUIX2FkZHJlc3MFBF9rZXkJAKwCAgIRTm8gdmFsdWUgZm9yIGtleSAFBF9rZXkFA3ZhbAEEaW50QQIIX2FkZHJlc3MEX2tleQQDdmFsCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUIX2FkZHJlc3MFBF9rZXkJAKwCAgIRTm8gdmFsdWUgZm9yIGtleSAFBF9rZXkFA3ZhbAEIY2JhbGFuY2UACQEDaW50AQUJa19iYWxhbmNlAQNmZWUACQEDaW50AQUFa19mZWUBD2luaXRNYXJnaW5SYXRpbwAJAQNpbnQBBRFrX2luaXRNYXJnaW5SYXRpbwEGcXRBc3RSAAkBA2ludAEFE2tfcXVvdGVBc3NldFJlc2VydmUBBmJzQXN0UgAJAQNpbnQBBRJrX2Jhc2VBc3NldFJlc2VydmUBBnF0QXN0VwAJAQVpbnRPcgIFEmtfcXVvdGVBc3NldFdlaWdodAUMREVDSU1BTF9VTklUAQZic0FzdFcACQEFaW50T3ICBRFrX2Jhc2VBc3NldFdlaWdodAUMREVDSU1BTF9VTklUARF0b3RhbFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRNrX3RvdGFsUG9zaXRpb25TaXplARJjdW11bGF0aXZlTm90aW9uYWwACQEDaW50AQUUa19jdW11bGF0aXZlTm90aW9uYWwBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAkBA2ludAEFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAACQEDaW50AQUSa19uZXh0RnVuZGluZ0Jsb2NrARBmdW5kaW5nUGVyaW9kUmF3AAkBA2ludAEFD2tfZnVuZGluZ1BlcmlvZAEUZnVuZGluZ1BlcmlvZERlY2ltYWwACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQxERUNJTUFMX1VOSVQBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUHU0VDT05EUwEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAJAQNpbnQBBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8BE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEDaW50AQUVa19saXF1aWRhdGlvbkZlZVJhdGlvARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAQNpbnQBBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAQtzcHJlYWRMaW1pdAAJAQNpbnQBBQ1rX3NwcmVhZExpbWl0AQ5tYXhQcmljZUltcGFjdAAJAQNpbnQBBRBrX21heFByaWNlSW1wYWN0AQ5tYXhQcmljZVNwcmVhZAAJAQNpbnQBBRBrX21heFByaWNlU3ByZWFkASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJAQNpbnQBBSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEDaW50AQUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEDaW50AQUXa190b3RhbExvbmdQb3NpdGlvblNpemUBD2dldEFjdHVhbENhbGxlcgEBaQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQENb3JkZXJzQWRkcmVzcwACCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcJAAIBAg5JbnZhbGlkIG1hcmdpbgMDCQEBIQEFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBnAgUUcmVtYWluaW5nTWFyZ2luUmF0aW8AAAcJAAIBAg5JbnZhbGlkIG1hcmdpbgYBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BDV9wb3NpdGlvblNpemUDCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIsU2hvdWxkIG5vdCBiZSBjYWxsZWQgd2l0aCBfcG9zaXRpb25TaXplID09IDADCQBmAgUNX3Bvc2l0aW9uU2l6ZQAACQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAELZ2V0UG9zaXRpb24BB190cmFkZXIED3Bvc2l0aW9uU2l6ZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgQHJG1hdGNoMAUPcG9zaXRpb25TaXplT3B0AwkAAQIFByRtYXRjaDACA0ludAQMcG9zaXRpb25TaXplBQckbWF0Y2gwCQCWCgQFDHBvc2l0aW9uU2l6ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgkAlgoEAAAAAAAAAAABEGdldFBvc2l0aW9uQXNzZXQBB190cmFkZXIEEHBvc2l0aW9uQXNzZXRPcHQJAJ0IAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQdfdHJhZGVyBAckbWF0Y2gwBRBwb3NpdGlvbkFzc2V0T3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQNcG9zaXRpb25Bc3NldAUHJG1hdGNoMAUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAABE3JlcXVpcmVPcGVuUG9zaXRpb24BB190cmFkZXIDCQAAAggJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEAAAkAAgECEE5vIG9wZW4gcG9zaXRpb24GAQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUNa19pbml0aWFsaXplZAcBBnBhdXNlZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUIa19wYXVzZWQHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlgoECQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAkAZAIJARJjdW11bGF0aXZlTm90aW9uYWwABRFfcXVvdGVBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlgoEBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAkAZQIJARJjdW11bGF0aXZlTm90aW9uYWwABRFfcXVvdGVBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAQHX3F0QXN0UgdfcXRBc3RXB19ic0FzdFIHX2JzQXN0VwkBBG11bGQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwEJc3dhcElucHV0AgZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABAFrCQENY2FsY0ludmFyaWFudAQFB19xdEFzdFIFB19xdEFzdFcFB19ic0FzdFIFB19ic0FzdFcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIDBQZfaXNBZGQJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAkAZQIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAQRkaXZkAgUBawkBBG11bGQCBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfcXRBc3RXBBhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQRkaXZkAgkBA2FicwEJAGUCBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFB19ic0FzdFIFB19xdEFzdFcEFWFtb3VudEJhc2VBc3NldEJvdWdodAMFBl9pc0FkZAUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEBLQEFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQNJHQwMTYzMzMxNjUyNgkBDXVwZGF0ZVJlc2VydmUDBQZfaXNBZGQFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTYzMzMxNjUyNgJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE2MzMzMTY1MjYCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTYzMzMxNjUyNgJfMwQYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxCAUNJHQwMTYzMzMxNjUyNgJfNAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC21hcmtldFByaWNlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFB19xdEFzdFICFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFB19ic0FzdFICISBxdW90ZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRFfcXVvdGVBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg4gbWFya2V0UHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAlwoFBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQUYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BBBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCBQxfbWFyZ2luRGVsdGEFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE4MDQ1MTgxNzIDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTgwNDUxODE3MgJfMQQHYmFkRGVidAgFDSR0MDE4MDQ1MTgxNzICXzIJAJUKAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQENY2FsY0ludmFyaWFudAQFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BBhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIDBQZfaXNBZGQJAGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAkAZQIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50BA9xdW90ZUFzc2V0QWZ0ZXIJAQRkaXZkAgUBawkBBG11bGQCBRhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIFEF9iYXNlQXNzZXRXZWlnaHQEDnF1b3RlQXNzZXRTb2xkCQEDYWJzAQkAZQIFD3F1b3RlQXNzZXRBZnRlcgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QABA0kdDAxOTM0MDE5NTMzCQENdXBkYXRlUmVzZXJ2ZQMJAQEhAQUGX2lzQWRkBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxOTM0MDE5NTMzAl8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTkzNDAxOTUzMwJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxOTM0MDE5NTMzAl8zBBhjdW11bGF0aXZlTm90aW9uYWxBZnRlcjEIBQ0kdDAxOTM0MDE5NTMzAl80BAttYXJrZXRQcmljZQkBBGRpdmQCBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmAwMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUSX3F1b3RlQXNzZXRSZXNlcnZlAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBRFfYmFzZUFzc2V0UmVzZXJ2ZQIgIGJhc2UgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQUQX2Jhc2VBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg8gbWFya2V0IHByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJoKCAUOcXVvdGVBc3NldFNvbGQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQUYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAULcHJpY2VJbXBhY3QBCnN3YXBPdXRwdXQDBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0CQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcFBl9pc0FkZAUQX2Jhc2VBc3NldEFtb3VudAUUX2NoZWNrTWF4UHJpY2VJbXBhY3QJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcAARJnZXRPcmFjbGVUd2FwUHJpY2UABAZvcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQVrX29yYQIABAhwcmljZUtleQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUJa19vcmFfa2V5BAhibG9ja0tleQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUPa19vcmFfYmxvY2tfa2V5BAlsYXN0VmFsdWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgcHJpY2UuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhwcmljZUtleQUJbGFzdFZhbHVlARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AhJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUEC29yYWNsZVByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQKcHJpY2VBZnRlcgkBBGRpdmQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBAxhdmVyYWdlUHJpY2UJAQRkaXZkAgkAZAIFC29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFC29yYWNsZVByaWNlBQpwcmljZUFmdGVyBQxhdmVyYWdlUHJpY2UDCQBmAgUMYWJzUHJpY2VEaWZmCQEObWF4UHJpY2VTcHJlYWQACQACAQkArAICCQCsAgIJAKwCAgINUHJpY2Ugc3ByZWFkIAkApAMBBQxhYnNQcmljZURpZmYCFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYNX3Bvc2l0aW9uU2l6ZQdfb3B0aW9uEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ1fcG9zaXRpb25TaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsAwkAAAIFB19vcHRpb24FD1BOTF9PUFRJT05fU1BPVAQNJHQwMjI5MDgyMzEyOAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHCQEBIQEFB2lzU2hvcnQFD3Bvc2l0aW9uU2l6ZUFicwcFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BBNvdXRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMjI5MDgyMzEyOAJfMQQCeDEIBQ0kdDAyMjkwODIzMTI4Al8yBAJ4MggFDSR0MDIyOTA4MjMxMjgCXzMEAngzCAUNJHQwMjI5MDgyMzEyOAJfNAUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJARJnZXRPcmFjbGVUd2FwUHJpY2UABRBwb3NpdGlvbk5vdGlvbmFsAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBw1fcG9zaXRpb25TaXplFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAdfb3B0aW9uAwkAAAIFDV9wb3NpdGlvblNpemUAAAkAAgECFUludmFsaWQgcG9zaXRpb24gc2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAkBH2dldFBvc2l0aW9uQWRqdXN0ZWRPcGVuTm90aW9uYWwGBQ1fcG9zaXRpb25TaXplBQdfb3B0aW9uBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAQNdW5yZWFsaXplZFBubAMFB2lzU2hvcnQJAGUCBRVfcG9zaXRpb25PcGVuTm90aW9uYWwFEHBvc2l0aW9uTm90aW9uYWwJAGUCBRBwb3NpdGlvbk5vdGlvbmFsBRVfcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMjQ1NTMyNDY4MQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjQ1NTMyNDY4MQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNDU1MzI0NjgxAl8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI0NTUzMjQ2ODECXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjQ1NTMyNDY4MQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMjUxOTQyNTMwNQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMjUxOTQyNTMwNQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNTE5NDI1MzA1Al8yBANwb24IBQ0kdDAyNTE5NDI1MzA1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI1MTk0MjUzMDUCXzQEDSR0MDI1MzExMjU0MDQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyNTMxMTI1NDA0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjUzMTEyNTQwNAJfMgQNJHQwMjU0MDkyNTU3NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMjU0MDkyNTU3NQJfMQQHYmFkRGVidAgFDSR0MDI1NDA5MjU1NzUCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgdfdHJhZGVyDV9wb3NpdGlvblNpemUEDG1heGltdW1SYXRpbwkBBHZtYXgCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfOAMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRVleGNoYW5nZWRQb3NpdGlvblNpemUHAl8xBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50ARVpbnRlcm5hbENsb3NlUG9zaXRpb24CB190cmFkZXIUX2NoZWNrTWF4UHJpY2VJbXBhY3QEDSR0MDI2ODA4MjY5MzYJAQtnZXRQb3NpdGlvbgEFB190cmFkZXIEDHBvc2l0aW9uU2l6ZQgFDSR0MDI2ODA4MjY5MzYCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjY4MDgyNjkzNgJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyNjgwODI2OTM2Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI2ODA4MjY5MzYCXzQEDXVucmVhbGl6ZWRQbmwICQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QCXzIEDSR0MDI3MDMxMjcxOTkJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDI3MDMxMjcxOTkCXzEEB2JhZERlYnQIBQ0kdDAyNzAzMTI3MTk5Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDI3MzI2Mjc2MzEJAQpzd2FwT3V0cHV0AwkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDI3MzI2Mjc2MzECXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyNzMyNjI3NjMxAl8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAyNzMyNjI3NjMxAl8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMjczMjYyNzYzMQJfNAQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDAyNzMyNjI3NjMxAl81BA50b3RhbExvbmdBZnRlcggFDSR0MDI3MzI2Mjc2MzECXzYED3RvdGFsU2hvcnRBZnRlcggFDSR0MDI3MzI2Mjc2MzECXzcEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAkAngoMBRVleGNoYW5nZWRQb3NpdGlvblNpemUFB2JhZERlYnQFC3JlYWxpemVkUG5sBQ1tYXJnaW5Ub1ZhdWx0BRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyARBnZXRUd2FwU3BvdFByaWNlAAQIbWludXRlSWQJAGkCCQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAPAQNc3RhcnRNaW51dGVJZAkAZQIFCG1pbnV0ZUlkBQ1UV0FQX0lOVEVSVkFMBAdsaXN0U3RyCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFDWtfbGFzdERhdGFTdHICAAQEbGlzdAkAtQkCBQdsaXN0U3RyAgEsCgEIZmlsdGVyRm4CC2FjY3VtdWxhdG9yBG5leHQDCQBnAgUNc3RhcnRNaW51dGVJZAkBDXBhcnNlSW50VmFsdWUBBQRuZXh0CQDNCAIFC2FjY3VtdWxhdG9yCQENcGFyc2VJbnRWYWx1ZQEFBG5leHQFC2FjY3VtdWxhdG9yBAVsaXN0RgoAAiRsBQRsaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhmaWx0ZXJGbgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUBAhtYXhJbmRleAMJAGYCCQCQAwEFBWxpc3RGAAAJAJYDAQUFbGlzdEYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsaXN0AAAEDGxhc3RNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ5rX2xhc3RNaW51dGVJZAAABBZlbmRMYXN0Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBQxsYXN0TWludXRlSWQAAAQMZW5kTGFzdFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFDGxhc3RNaW51dGVJZAAABBJub3dDdW11bGF0aXZlUHJpY2UJAGQCBRZlbmRMYXN0Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFDGVuZExhc3RQcmljZQQYc3RhcnRMYXN0Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIBXwkApAMBBQhtYXhJbmRleAAABA5zdGFydExhc3RQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUTa190d2FwRGF0YUxhc3RQcmljZQIBXwkApAMBBQhtYXhJbmRleAAABBRzdGFydEN1bXVsYXRpdmVQcmljZQkAZAIFGHN0YXJ0TGFzdEN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQ1zdGFydE1pbnV0ZUlkBQhtYXhJbmRleAUOc3RhcnRMYXN0UHJpY2UJAGkCCQBlAgUSbm93Q3VtdWxhdGl2ZVByaWNlBRRzdGFydEN1bXVsYXRpdmVQcmljZQUNVFdBUF9JTlRFUlZBTAETZ2V0VGVybWluYWxBbW1TdGF0ZQAEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQCUCgIJAQZxdEFzdFIACQEGYnNBc3RSAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABA0kdDAyOTYxODI5Nzk3CQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHBBVjdXJyZW50TmV0TWFya2V0VmFsdWUIBQ0kdDAyOTYxODI5Nzk3Al8xBBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwMjk2MTgyOTc5NwJfMgQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwMjk2MTgyOTc5NwJfMwkAlAoCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUBE2dldFF1b3RlQXNzZXRXZWlnaHQEEGJhc2VBc3NldFJlc2VydmURdG90YWxQb3NpdGlvblNpemURcXVvdGVBc3NldFJlc2VydmULdGFyZ2V0UHJpY2UEAWIJALYCAQUQYmFzZUFzc2V0UmVzZXJ2ZQQCc3oJALYCAQURdG90YWxQb3NpdGlvblNpemUEAXEJALYCAQURcXVvdGVBc3NldFJlc2VydmUEAXAJALYCAQULdGFyZ2V0UHJpY2UEA2JzMgkBBWJwb3dkAgkAtwICBQFiBQJzegkAtgIBCQBoAgACBQxERUNJTUFMX1VOSVQEBHFiczIJAQVibXVsZAIFAXEFA2JzMgQDcHM0CQC5AgIJALYCAQAECQEFYm11bGQCBQFwBQJzegQDc3FyCQEGYnNxcnRkAQkBBWJtdWxkAgUEcWJzMgkAuAICBQFxBQNwczQEAmJxCQEFYm11bGQCBQFiBQFxBAJxcwkBBWJtdWxkAgUBcQUCc3oEA3RvcAkAtwICCQC3AgIJAL4CAQUDc3FyBQJicQUCcXMEA2JvdAkAuQICCQC2AgEAAgkBBWJtdWxkAgUBcQUCc3oEBnJlc3VsdAkBBWJkaXZkAgUDdG9wBQNib3QJAKADAQUGcmVzdWx0ARRnZXRTeW5jVGVybWluYWxQcmljZQEOX3Rlcm1pbmFsUHJpY2UEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAABAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAluZXdRdEFzdFcJARNnZXRRdW90ZUFzc2V0V2VpZ2h0BAUHX2JzQXN0UgUNX3Bvc2l0aW9uU2l6ZQUHX3F0QXN0UgUOX3Rlcm1pbmFsUHJpY2UECW5ld0JzQXN0VwUMREVDSU1BTF9VTklUBA1tYXJnaW5Ub1ZhdWx0CAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQ1fcG9zaXRpb25TaXplBRVjdXJyZW50TmV0TWFya2V0VmFsdWUFB19xdEFzdFIFCW5ld1F0QXN0VwUHX2JzQXN0UgUJbmV3QnNBc3RXBQ9QTkxfT1BUSU9OX1NQT1QCXzIJAJUKAwUJbmV3UXRBc3RXBQluZXdCc0FzdFcFDW1hcmdpblRvVmF1bHQBCmdldEZ1bmRpbmcABA91bmRlcmx5aW5nUHJpY2UJARJnZXRPcmFjbGVUd2FwUHJpY2UABA1zcG90VHdhcFByaWNlCQEQZ2V0VHdhcFNwb3RQcmljZQAEB3ByZW1pdW0JAGUCBQ1zcG90VHdhcFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwkAAAIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAAABgkAAAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAAAJAJQKAgAAAAADCQBmAgAABQdwcmVtaXVtBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkEE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUACQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkAlAoCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFB3ByZW1pdW0JARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAFB09ORV9EQVkEFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkAlAoCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgEOZ2V0QWRqdXN0ZWRGZWUCAWkQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwMzI4OTAzMzQ5OAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAEECmFydGlmYWN0SWQJANgEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAkAkQMCCAUBaQhwYXltZW50cwABB2Fzc2V0SWQCGUludmFsaWQgYXR0YWNoZWQgYXJ0aWZhY3QEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFCmFydGlmYWN0SWQDCQAAAgUMYXJ0aWZhY3RLaW5kBRhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUECXJlZHVjdGlvbgkBBGludEECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Rva2VuX3BhcmFtBQphcnRpZmFjdElkBAthZGp1c3RlZEZlZQkBBG11bGQCBQdiYXNlRmVlBQlyZWR1Y3Rpb24JAJQKAgULYWRqdXN0ZWRGZWUGCQACAQIZSW52YWxpZCBhdHRhY2hlZCBhcnRpZmFjdAkAlAoCBQdiYXNlRmVlBwQLYWRqdXN0ZWRGZWUIBQ0kdDAzMjg5MDMzNDk4Al8xBAxidXJuQXJ0aWZhY3QIBQ0kdDAzMjg5MDMzNDk4Al8yCQCUCgIFC2FkanVzdGVkRmVlBQxidXJuQXJ0aWZhY3QBDnVwZGF0ZVNldHRpbmdzCRBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfaW5pdE1hcmdpblJhdGlvBRBfaW5pdE1hcmdpblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8FBF9tbXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwUUX2xpcXVpZGF0aW9uRmVlUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFD2tfZnVuZGluZ1BlcmlvZAUOX2Z1bmRpbmdQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFBWtfZmVlBQRfZmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3NwcmVhZExpbWl0BQxfc3ByZWFkTGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VJbXBhY3QFD19tYXhQcmljZUltcGFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlU3ByZWFkBQ9fbWF4UHJpY2VTcHJlYWQFA25pbAENdXBkYXRlRnVuZGluZwURX25leHRGdW5kaW5nQmxvY2skX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24QX2xvbmdGdW5kaW5nUmF0ZRFfc2hvcnRGdW5kaW5nUmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19uZXh0RnVuZGluZ0Jsb2NrBRFfbmV4dEZ1bmRpbmdCbG9jawkAzAgCCQEMSW50ZWdlckVudHJ5AgUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUkX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBSZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19sb25nRnVuZGluZ1JhdGUFEF9sb25nRnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfc2hvcnRGdW5kaW5nUmF0ZQURX3Nob3J0RnVuZGluZ1JhdGUFA25pbAETdXBkYXRlUG9zaXRpb25Bc3NldAIIX2FkZHJlc3MIX2Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQhfYWRkcmVzcwUIX2Fzc2V0SWQFA25pbAEOdXBkYXRlUG9zaXRpb24FCF9hZGRyZXNzBV9zaXplB19tYXJnaW4NX29wZW5Ob3Rpb25hbCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzBQVfc2l6ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUIX2FkZHJlc3MFB19tYXJnaW4JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzBQ1fb3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQhfYWRkcmVzcwUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FA25pbAEKYXBwZW5kVHdhcAEFcHJpY2UECG1pbnV0ZUlkCQBpAgkAaQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wAOgHADwEEHByZXZpb3VzTWludXRlSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOa19sYXN0TWludXRlSWQAAAMJAGYCBRBwcmV2aW91c01pbnV0ZUlkBQhtaW51dGVJZAkAAgECEVRXQVAgb3V0LW9mLW9yZGVyBAxsYXN0TWludXRlSWQDCQAAAgUQcHJldmlvdXNNaW51dGVJZAAABQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAMJAGYCBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAQTcHJldkN1bXVsYXRpdmVQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCAV8JAKQDAQUQcHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUQcHJldmlvdXNNaW51dGVJZAUFcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBQxsYXN0TWludXRlSWQFCXByZXZQcmljZQQEbGlzdAkBC3B1c2hUb1F1ZXVlAwkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABQ1UV0FQX0lOVEVSVkFMCQCkAwEFCG1pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQkApAMBBQhtaW51dGVJZAUTbGFzdEN1bXVsYXRpdmVQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBQhtaW51dGVJZAUFcHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkBRBwcmV2aW91c01pbnV0ZUlkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5rX2xhc3RNaW51dGVJZAUIbWludXRlSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUNa19sYXN0RGF0YVN0cgkBCWxpc3RUb1N0cgEFBGxpc3QFA25pbAQYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkCQCkAwEFCG1pbnV0ZUlkAAAEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAAAECXByZXZQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAUFcHJpY2UEE2xhc3RDdW11bGF0aXZlUHJpY2UJAGQCBRNwcmV2Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFCG1pbnV0ZUlkBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFCXByZXZQcmljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUIbWludXRlSWQFE2xhc3RDdW11bGF0aXZlUHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFE2tfdHdhcERhdGFMYXN0UHJpY2UJAKQDAQUIbWludXRlSWQFBXByaWNlBQNuaWwBEXVwZGF0ZUFtbVJlc2VydmVzAgdfcXRBc3RSB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0UgUDbmlsARB1cGRhdGVBbW1XZWlnaHRzAgdfcXRBc3RXB19ic0FzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAEJdXBkYXRlQW1tBwdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIYX2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyFV9vcGVuSW50ZXJlc3ROb3Rpb25hbBZfdG90YWxMb25nUG9zaXRpb25TaXplF190b3RhbFNob3J0UG9zaXRpb25TaXplBAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwADCQECIT0CCQBlAgUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGEludmFsaWQgQU1NIHN0YXRlIGRhdGE6IAkApAMBBRZfdG90YWxMb25nUG9zaXRpb25TaXplAgQgKyAgCQCkAwEFF190b3RhbFNob3J0UG9zaXRpb25TaXplAgQgIT0gCQCkAwEFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDOCAIJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgUHX3F0QXN0UgUHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa190b3RhbFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFGtfY3VtdWxhdGl2ZU5vdGlvbmFsBRhfY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwFFV9vcGVuSW50ZXJlc3ROb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXa190b3RhbExvbmdQb3NpdGlvblNpemUFFl90b3RhbExvbmdQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFA25pbAkBCmFwcGVuZFR3YXABCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFD2tfcG9zaXRpb25Bc3NldAUIX2FkZHJlc3MJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFGtfcG9zaXRpb25DbG9zZWREYXRlBQhfYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAFA25pbAEId2l0aGRyYXcCCF9hZGRyZXNzB19hbW91bnQEB2JhbGFuY2UJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAZgIFB19hbW91bnQFB2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICAhNVbmFibGUgdG8gd2l0aGRyYXcgCQCkAwEFB19hbW91bnQCFyBmcm9tIGNvbnRyYWN0IGJhbGFuY2UgCQCkAwEFB2JhbGFuY2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUIX2FkZHJlc3MFB19hbW91bnQJAQpxdW90ZUFzc2V0AAUDbmlsAQ11cGRhdGVCYWxhbmNlAQFpAwkAZgIAAAUBaQkAAgECB0JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUBaQUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbAEXaXNTYW1lQXNzZXRPck5vUG9zaXRpb24CB190cmFkZXIIX2Fzc2V0SWQED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgEFB190cmFkZXICXzEDCQAAAgUPb2xkUG9zaXRpb25TaXplAAAGCQAAAgkBEGdldFBvc2l0aW9uQXNzZXQBBQdfdHJhZGVyBQhfYXNzZXRJZAELaXNTYW1lQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQJAAACCQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIFCF9hc3NldElkAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDBF9hbW0IX2Fzc2V0SWQHX3RyYWRlcgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgUga190cmFkZXJfbWFya2V0X2Fzc2V0X2NvbGxhdGVyYWwCAV8FBF9hbW0CAV8FCF9hc3NldElkAgFfBQdfdHJhZGVyARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQdfdHJhZGVyBA1wb3NpdGlvbkFzc2V0CQEQZ2V0UG9zaXRpb25Bc3NldAEFB190cmFkZXIDCQAAAgUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAAJAJQKAgAABQ1wb3NpdGlvbkFzc2V0BANrZXkJAR5nZXRCb3Jyb3dlZEJ5VHJhZGVySW5NYXJrZXRLZXkDCQClCAEFBHRoaXMFDXBvc2l0aW9uQXNzZXQFB190cmFkZXIEBmJvcnJvdwkBC3ZhbHVlT3JFbHNlAgkAmggCCQERY29sbGF0ZXJhbEFkZHJlc3MABQNrZXkAAAkAlAoCBQZib3Jyb3cFDXBvc2l0aW9uQXNzZXQVAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhpJbnZhbGlkIHRvZ2dsZVBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIaSW52YWxpZCB0b2dnbGVQYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBwUDbmlsAWkBDGFkZExpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIbSW52YWxpZCBhZGRMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEFGJhc2VBc3NldEFtb3VudFRvQWRkCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQVwcmljZQQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQLYnNBc3RSQWZ0ZXIJAGQCBQdfYnNBc3RSBRRiYXNlQXNzZXRBbW91bnRUb0FkZAkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyAWkBD3JlbW92ZUxpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIeSW52YWxpZCByZW1vdmVMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQVwcmljZQQLcXRBc3RSQWZ0ZXIJAGUCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQLYnNBc3RSQWZ0ZXIJAGUCBQdfYnNBc3RSBRdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyAWkBDmNoYW5nZVNldHRpbmdzCRBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQDCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCBjaGFuZ2VTZXR0aW5ncyBwYXJhbXMJAQ51cGRhdGVTZXR0aW5ncwkFEF9pbml0TWFyZ2luUmF0aW8FBF9tbXIFFF9saXF1aWRhdGlvbkZlZVJhdGlvBQ5fZnVuZGluZ1BlcmlvZAUEX2ZlZQUMX3NwcmVhZExpbWl0BQ9fbWF4UHJpY2VJbXBhY3QFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUPX21heFByaWNlU3ByZWFkAWkBCmluaXRpYWxpemUOB19xdEFzdFIHX2JzQXN0Ug5fZnVuZGluZ1BlcmlvZBBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8EX2ZlZQdfb3JhY2xlCl9vcmFjbGVLZXkMX2Nvb3JkaW5hdG9yDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvD19tYXhQcmljZVNwcmVhZAMDAwMDAwMDAwMDAwkAZwIAAAUHX3F0QXN0UgYJAGcCAAAFB19ic0FzdFIGCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkBC2luaXRpYWxpemVkAAkAAgECHUludmFsaWQgaW5pdGlhbGl6ZSBwYXJhbWV0ZXJzCQDOCAIJAM4IAgkAzggCCQDOCAIJAQl1cGRhdGVBbW0HBQdfcXRBc3RSBQdfYnNBc3RSAAAAAAAAAAAAAAkBDnVwZGF0ZVNldHRpbmdzCQUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQJAQ11cGRhdGVGdW5kaW5nBQkAZAIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQ5fZnVuZGluZ1BlcmlvZAAAAAAAAAAACQENdXBkYXRlQmFsYW5jZQEAAAkAzAgCCQEMQm9vbGVhbkVudHJ5AgUNa19pbml0aWFsaXplZAYJAMwIAgkBC1N0cmluZ0VudHJ5AgUFa19vcmEFB19vcmFjbGUJAMwIAgkBC1N0cmluZ0VudHJ5AgUJa19vcmFfa2V5BQpfb3JhY2xlS2V5CQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzBQxfY29vcmRpbmF0b3IFA25pbAFpARJzZXRJbml0TWFyZ2luUmF0aW8BEF9pbml0TWFyZ2luUmF0aW8DAwkAZwIAAAUQX2luaXRNYXJnaW5SYXRpbwYJAQEhAQkBC2luaXRpYWxpemVkAAkAAgECJUludmFsaWQgc2V0SW5pdE1hcmdpblJhdGlvIHBhcmFtZXRlcnMJAQ51cGRhdGVTZXR0aW5ncwkFEF9pbml0TWFyZ2luUmF0aW8JARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQEQZnVuZGluZ1BlcmlvZFJhdwAJAQNmZWUACQELc3ByZWFkTGltaXQACQEObWF4UHJpY2VJbXBhY3QACQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ACQEObWF4UHJpY2VTcHJlYWQAAWkBEGRlY3JlYXNlUG9zaXRpb24DB19hbW91bnQJX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQZwYXVzZWQACQACAQIjSW52YWxpZCBkZWNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDQ1NDc4NDU2MzAJAQtnZXRQb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA0NTQ3ODQ1NjMwAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDQ1NDc4NDU2MzACXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNDU0Nzg0NTYzMAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA0NTQ3ODQ1NjMwAl80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA0NTgwMzQ1OTE5CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCCQClCAEIBQFpBmNhbGxlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNDU4MDM0NTkxOQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDQ1ODAzNDU5MTkCXzIEDSR0MDQ1OTI1NDg0NzQDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsBA0kdDA0NjMwMjQ2NTIxCQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCAUNJHQwNDYzMDI0NjUyMQJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ2MzAyNDY1MjECXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ2MzAyNDY1MjECXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA0NjMwMjQ2NTIxAl80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDQ2MzAyNDY1MjECXzUEGGV4Y2hhbmdlZFBvc2l0aW9uU2l6ZUFicwkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50BRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMHCQACAQkArAICCQCsAgIJAKwCAgIlVG9vIGxpdHRsZSBiYXNlIGFzc2V0IGV4Y2hhbmdlZCwgZ290IAkApAMBBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMCCiBleHBlY3RlZCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQLcmVhbGl6ZWRQbmwJAQRkaXZkAgkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDQ2OTU4NDcyMDMJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA0Njk1ODQ3MjAzAl8xBAdiYWREZWJ0CAUNJHQwNDY5NTg0NzIwMwJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA0Njk1ODQ3MjAzAl8zBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQxvcGVuTm90aW9uYWwEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAJ0KCwUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDQ1OTI1NDg0NzQCXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNDU5MjU0ODQ3NAJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA0NTkyNTQ4NDc0Al8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDQ1OTI1NDg0NzQCXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDQ1OTI1NDg0NzQCXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA0NTkyNTQ4NDc0Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNDU5MjU0ODQ3NAJfNwQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDA0NTkyNTQ4NDc0Al84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNDU5MjU0ODQ3NAJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA0NTkyNTQ4NDc0A18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNDU5MjU0ODQ3NANfMTEEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCCQClCAEIBQFpBmNhbGxlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUJAKUIAQgFAWkGY2FsbGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMDAwkBAiE9AgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAQIhPQIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAcGCQBnAgAABQpfcmF3QW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBF2lzU2FtZUFzc2V0T3JOb1Bvc2l0aW9uAgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwkBBGRpdmQCBQxERUNJTUFMX1VOSVQFCV9sZXZlcmFnZQkBD2luaXRNYXJnaW5SYXRpbwAGBgkBBnBhdXNlZAAJAAIBAiNJbnZhbGlkIGluY3JlYXNlUG9zaXRpb24gcGFyYW1ldGVycwQQZG9HZXRGZWVEaXNjb3VudAkA/AcECQEMbWluZXJBZGRyZXNzAAISY29tcHV0ZUZlZURpc2NvdW50CQDMCAIFB190cmFkZXIFA25pbAUDbmlsAwkAAAIFEGRvR2V0RmVlRGlzY291bnQFEGRvR2V0RmVlRGlzY291bnQEC2ZlZURpc2NvdW50BAckbWF0Y2gwBRBkb0dldEZlZURpc2NvdW50AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECIUludmFsaWQgY29tcHV0ZUZlZURpc2NvdW50IHJlc3VsdAQNJHQwNTAxMzc1MDIwMQkBDmdldEFkanVzdGVkRmVlAgUBaQULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwNTAxMzc1MDIwMQJfMQQMYnVybkFydGlmYWN0CAUNJHQwNTAxMzc1MDIwMQJfMgQMcmF3RmVlQW1vdW50CQEEbXVsZAIFCl9yYXdBbW91bnQFC2FkanVzdGVkRmVlBAdfYW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUMcmF3RmVlQW1vdW50BBNkaXN0cmlidXRlRmVlQW1vdW50AwURaXNDb2xsYXRlcmFsQXNzZXQECGRvQm9ycm93CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBmJvcnJvdwkAzAgCBQdfdHJhZGVyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQdfYW1vdW50BQNuaWwDCQAAAgUIZG9Cb3Jyb3cFCGRvQm9ycm93BA1iYWxhbmNlQmVmb3JlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQ1iYWxhbmNlQmVmb3JlBQ1iYWxhbmNlQmVmb3JlBAZkb1N3YXAJAPwHBAkBC3N3YXBBZGRyZXNzAAIEc3dhcAkAzAgCCQDYBAEJAQpxdW90ZUFzc2V0AAkAzAgCAAAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUIX2Fzc2V0SWQFDHJhd0ZlZUFtb3VudAUDbmlsAwkAAAIFBmRvU3dhcAUGZG9Td2FwBAxiYWxhbmNlQWZ0ZXIJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAAAIFDGJhbGFuY2VBZnRlcgUMYmFsYW5jZUFmdGVyBA9leGNoYW5nZWRBbW91bnQJAGUCBQxiYWxhbmNlQWZ0ZXIFDWJhbGFuY2VCZWZvcmUDCQAAAgUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQFD2V4Y2hhbmdlZEFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUMcmF3RmVlQW1vdW50AwkAAAIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFE2Rpc3RyaWJ1dGVGZWVBbW91bnQEDnJlZmVycmVyRmVlQW55CQD8BwQJAQ9yZWZlcnJhbEFkZHJlc3MAAhVhY2NlcHRQYXltZW50V2l0aExpbmsJAMwIAgUHX3RyYWRlcgkAzAgCBQhfcmVmTGluawUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFA25pbAMJAAACBQ5yZWZlcnJlckZlZUFueQUOcmVmZXJyZXJGZWVBbnkEC3JlZmVycmVyRmVlBAckbWF0Y2gwBQ5yZWZlcnJlckZlZUFueQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAhNJbnZhbGlkIHJlZmVycmVyRmVlBAlmZWVBbW91bnQJAGUCBRNkaXN0cmlidXRlRmVlQW1vdW50BQtyZWZlcnJlckZlZQQNJHQwNTE1MTc1MTY1NwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNTE1MTc1MTY1NwJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA1MTUxNzUxNjU3Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDUxNTE3NTE2NTcCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNTE1MTc1MTY1NwJfNAQNaXNOZXdQb3NpdGlvbgkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABA9pc1NhbWVEaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkAAAIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAQOZXhwYW5kRXhpc3RpbmcDCQEBIQEFDWlzTmV3UG9zaXRpb24FD2lzU2FtZURpcmVjdGlvbgcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDUxOTQ2NTQ1MzEDAwUNaXNOZXdQb3NpdGlvbgYFDmV4cGFuZEV4aXN0aW5nBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA1MjM3MDUyNTc2CQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0CAUNJHQwNTIzNzA1MjU3NgJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDUyMzcwNTI1NzYCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUyMzcwNTI1NzYCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA1MjM3MDUyNTc2Al80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDUyMzcwNTI1NzYCXzUDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQCAyA8IAkApAMBBRNfbWluQmFzZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWFtb3VudEJhc2VBc3NldEJvdWdodAQZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAkBBGRpdmQCBQxvcGVuTm90aW9uYWwFCV9sZXZlcmFnZQQNJHQwNTI5NTc1MzE5NgkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAQMcmVtYWluTWFyZ2luCAUNJHQwNTI5NTc1MzE5NgJfMQQCeDEIBQ0kdDA1Mjk1NzUzMTk2Al8yBAJ4MggFDSR0MDUyOTU3NTMxOTYCXzMDCQEBIQEJARlyZXF1aXJlTm90T3ZlclNwcmVhZExpbWl0AgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQACAQIVT3ZlciBtYXggc3ByZWFkIGxpbWl0CQCdCgsFD25ld1Bvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luCQBkAgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAEDG9wZW5Ob3Rpb25hbAkBBG11bGQCBQdfYW1vdW50BQlfbGV2ZXJhZ2UEDSR0MDU0MjI0NTQzNDAJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIJAKUIAQgFAWkGY2FsbGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA1NDIyNDU0MzQwAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwNTQyMjQ1NDM0MAJfMgMJAGYCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQxvcGVuTm90aW9uYWwJAAIBAi5Vc2UgZGVjcmVhc2VQb3NpdGlvbiB0byBkZWNyZWFzZSBwb3NpdGlvbiBzaXplCQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDUxOTQ2NTQ1MzECXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwNTE5NDY1NDUzMQJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA1MTk0NjU0NTMxAl8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDUxOTQ2NTQ1MzECXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDUxOTQ2NTQ1MzECXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1MTk0NjU0NTMxAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTE5NDY1NDUzMQJfNwQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDA1MTk0NjU0NTMxAl84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNTE5NDY1NDUzMQJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA1MTk0NjU0NTMxA18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNTE5NDY1NDUzMQNfMTEEDGZlZVRvU3Rha2VycwkAaQIFCWZlZUFtb3VudAACBA5mZWVUb0luc3VyYW5jZQkAZQIFCWZlZUFtb3VudAUMZmVlVG9TdGFrZXJzBAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQUXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxhdGVzdENQRgkBE3VwZGF0ZVBvc2l0aW9uQXNzZXQCBQdfdHJhZGVyBQtfYXNzZXRJZFN0cgkBCXVwZGF0ZUFtbQcFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWFkZE1hcmdpbgAEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQHX3RyYWRlcgkApQgBCAUBaQZjYWxsZXIECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BAhfYXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtfYXNzZXRJZFN0cgkA2AQBCQEFdmFsdWUBBQhfYXNzZXRJZAQMaXNRdW90ZUFzc2V0CQAAAgUIX2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAQRaXNDb2xsYXRlcmFsQXNzZXQJARBpc1doaXRlbGlzdEFzc2V0AQULX2Fzc2V0SWRTdHIDAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0CQEBIQEFEWlzQ29sbGF0ZXJhbEFzc2V0BwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2lzU2FtZUFzc2V0AgUHX3RyYWRlcgULX2Fzc2V0SWRTdHIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgECHEludmFsaWQgYWRkTWFyZ2luIHBhcmFtZXRlcnMEEGRvR2V0RmVlRGlzY291bnQJAPwHBAkBDG1pbmVyQWRkcmVzcwACEmNvbXB1dGVGZWVEaXNjb3VudAkAzAgCBQdfdHJhZGVyBQNuaWwFA25pbAMJAAACBRBkb0dldEZlZURpc2NvdW50BRBkb0dldEZlZURpc2NvdW50BAtmZWVEaXNjb3VudAQHJG1hdGNoMAUQZG9HZXRGZWVEaXNjb3VudAMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAiFJbnZhbGlkIGNvbXB1dGVGZWVEaXNjb3VudCByZXN1bHQEDSR0MDU2NjA4NTY2NzIJAQ5nZXRBZGp1c3RlZEZlZQIFAWkFC2ZlZURpc2NvdW50BAthZGp1c3RlZEZlZQgFDSR0MDU2NjA4NTY2NzICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU2NjA4NTY2NzICXzIEDHJhd0ZlZUFtb3VudAkBBG11bGQCBQpfcmF3QW1vdW50BQthZGp1c3RlZEZlZQQHX2Ftb3VudAkAZQIFCl9yYXdBbW91bnQFDHJhd0ZlZUFtb3VudAQTZGlzdHJpYnV0ZUZlZUFtb3VudAMFEWlzQ29sbGF0ZXJhbEFzc2V0BAhkb0JvcnJvdwkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAgZib3Jyb3cJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQhfYXNzZXRJZAUHX2Ftb3VudAUDbmlsAwkAAAIFCGRvQm9ycm93BQhkb0JvcnJvdwQNYmFsYW5jZUJlZm9yZQkA8AcCBQR0aGlzCQEKcXVvdGVBc3NldAADCQAAAgUNYmFsYW5jZUJlZm9yZQUNYmFsYW5jZUJlZm9yZQQGZG9Td2FwCQD8BwQJAQtzd2FwQWRkcmVzcwACBHN3YXAJAMwIAgkA2AQBCQEKcXVvdGVBc3NldAAJAMwIAgAABQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCF9hc3NldElkBQxyYXdGZWVBbW91bnQFA25pbAMJAAACBQZkb1N3YXAFBmRvU3dhcAQMYmFsYW5jZUFmdGVyCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAAACBQxiYWxhbmNlQWZ0ZXIFDGJhbGFuY2VBZnRlcgQPZXhjaGFuZ2VkQW1vdW50CQBlAgUMYmFsYW5jZUFmdGVyBQ1iYWxhbmNlQmVmb3JlAwkAAAIFD2V4Y2hhbmdlZEFtb3VudAUPZXhjaGFuZ2VkQW1vdW50BQ9leGNoYW5nZWRBbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FDHJhd0ZlZUFtb3VudAMJAAACBRNkaXN0cmlidXRlRmVlQW1vdW50BRNkaXN0cmlidXRlRmVlQW1vdW50BA5yZWZlcnJlckZlZUFueQkA/AcECQEPcmVmZXJyYWxBZGRyZXNzAAINYWNjZXB0UGF5bWVudAkAzAgCBQdfdHJhZGVyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1Nzk3MTU4MTExCQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1Nzk3MTU4MTExAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDU3OTcxNTgxMTECXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTc5NzE1ODExMQJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1Nzk3MTU4MTExAl80BAxmZWVUb1N0YWtlcnMJAGkCBQlmZWVBbW91bnQAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBQlmZWVBbW91bnQFDGZlZVRvU3Rha2VycwQFc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACCWFkZExvY2tlZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACB2FkZEZyZWUFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQ5mZWVUb0luc3VyYW5jZQUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UECW5vdGlmeUZlZQkA/AcECQEMbWluZXJBZGRyZXNzAAIKbm90aWZ5RmVlcwkAzAgCBQdfdHJhZGVyCQDMCAIFCWZlZUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQkAZAIFEW9sZFBvc2l0aW9uTWFyZ2luBQdfYW1vdW50BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUb2xkUG9zaXRpb25Mc3RVcGRDUEYJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkBDmRvQnVybkFydGlmYWN0AgUMYnVybkFydGlmYWN0BQFpCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHJlbW92ZU1hcmdpbgEHX2Ftb3VudAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQIfSW52YWxpZCByZW1vdmVNYXJnaW4gcGFyYW1ldGVycwQNJHQwNTkyMTc1OTM1NwkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNTkyMTc1OTM1NwJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA1OTIxNzU5MzU3Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDU5MjE3NTkzNTcCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNTkyMTc1OTM1NwJfNAQLbWFyZ2luRGVsdGEJAQEtAQUHX2Ftb3VudAQNJHQwNTkzOTQ1OTU3MwkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgULbWFyZ2luRGVsdGEEDHJlbWFpbk1hcmdpbggFDSR0MDU5Mzk0NTk1NzMCXzEEB2JhZERlYnQIBQ0kdDA1OTM5NDU5NTczAl8yAwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA1xdW90ZUFzc2V0U3RyCQDYBAEJAQpxdW90ZUFzc2V0AAQNJHQwNjAwMTc2MDA3MQkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDYwMDE3NjAwNzECXzEEB2Fzc2V0SWQIBQ0kdDA2MDAxNzYwMDcxAl8yBAd0b1JlcGF5AwkAZgIFB19hbW91bnQFCGJvcnJvd2VkBQhib3Jyb3dlZAUHX2Ftb3VudAQKdG9XaXRoZHJhdwMJAGYCBQhib3Jyb3dlZAUHX2Ftb3VudAAACQBlAgUHX2Ftb3VudAUIYm9ycm93ZWQEC2ZpbmFsQm9ycm93CQBlAgUIYm9ycm93ZWQFB3RvUmVwYXkEFXN3aXRjaFBvc2l0aW9uVG9RdW90ZQMJAGYCBQtmaW5hbEJvcnJvdwAABQNuaWwJARN1cGRhdGVQb3NpdGlvbkFzc2V0AgUHX3RyYWRlcgUNcXVvdGVBc3NldFN0cgQNZG9TYW5pdHlDaGVjawMJAQIhPQIJAGQCBQd0b1JlcGF5BQp0b1dpdGhkcmF3BQdfYW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCHRvUmVwYXk9CQCkAwEFB3RvUmVwYXkCDiArIHRvV2l0aGRyYXc9CQCkAwEFCnRvV2l0aGRyYXcCBCAhPSAJAKQDAQUHX2Ftb3VudAUDbmlsAwkAAAIFDWRvU2FuaXR5Q2hlY2sFDWRvU2FuaXR5Q2hlY2sECWRvVW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUHX2Ftb3VudAUDbmlsBQNuaWwDCQAAAgUJZG9VbnN0YWtlBQlkb1Vuc3Rha2UEFnJldHVybkNvbGxhdGVyYWxBY3Rpb24DCQBmAgUHdG9SZXBheQAABAdkb1JlcGF5CQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACBXJlcGF5CQDMCAIFB190cmFkZXIJAMwIAgUHYXNzZXRJZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB3RvUmVwYXkFA25pbAMJAAACBQdkb1JlcGF5BQdkb1JlcGF5CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUHdG9SZXBheQkA2QQBBQdhc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uBRZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uCQDOCAIJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9vbGRQb3NpdGlvblNpemUDCQBmAgUKdG9XaXRoZHJhdwAACQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFCnRvV2l0aGRyYXcFA25pbAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAUVc3dpdGNoUG9zaXRpb25Ub1F1b3RlBRZyZXR1cm5Db2xsYXRlcmFsQWN0aW9uCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNsb3NlUG9zaXRpb24ABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEB190cmFkZXIJAQ9nZXRBY3R1YWxDYWxsZXIBBQFpBA5fdHJhZGVyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFB190cmFkZXICDkludmFsaWQgY2FsbGVyAwMDCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAQUHX3RyYWRlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQIgSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDYyMzIxNjI2OTkJARVpbnRlcm5hbENsb3NlUG9zaXRpb24CBQdfdHJhZGVyBgQCeDEIBQ0kdDA2MjMyMTYyNjk5Al8xBA9wb3NpdGlvbkJhZERlYnQIBQ0kdDA2MjMyMTYyNjk5Al8yBAtyZWFsaXplZFBubAgFDSR0MDYyMzIxNjI2OTkCXzMEDW1hcmdpblRvVmF1bHQIBQ0kdDA2MjMyMTYyNjk5Al80BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjIzMjE2MjY5OQJfNQQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjIzMjE2MjY5OQJfNgQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDYyMzIxNjI2OTkCXzcEF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCAUNJHQwNjIzMjE2MjY5OQJfOAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDYyMzIxNjI2OTkCXzkEAngyCAUNJHQwNjIzMjE2MjY5OQNfMTAEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjIzMjE2MjY5OQNfMTEED3RvdGFsU2hvcnRBZnRlcggFDSR0MDYyMzIxNjI2OTkDXzEyAwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAACQACAQImVW5hYmxlIHRvIGNsb3NlIHBvc2l0aW9uIHdpdGggYmFkIGRlYnQEDndpdGhkcmF3QW1vdW50CQEDYWJzAQUNbWFyZ2luVG9WYXVsdAQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA0kdDA2MzAyMzYzNTM4AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNYW1tTmV3QmFsYW5jZQgFDSR0MDYzMDIzNjM1MzgCXzEEA3gxMQgFDSR0MDYzMDIzNjM1MzgCXzIEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFDndpdGhkcmF3QW1vdW50BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBA0kdDA2Mzc1MDYzODA0CQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNjM3NTA2MzgwNAJfMQQHYXNzZXRJZAgFDSR0MDYzNzUwNjM4MDQCXzIEDSR0MDYzODE5NjQ3MzYDCQBmAgUIYm9ycm93ZWQAAAMJAGcCBQ53aXRoZHJhd0Ftb3VudAUIYm9ycm93ZWQEB2RvUmVwYXkJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIFcmVwYXkJAMwIAgUHX3RyYWRlcgkAzAgCBQdhc3NldElkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUIYm9ycm93ZWQFA25pbAMJAAACBQdkb1JlcGF5BQdkb1JlcGF5CQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOX3RyYWRlckFkZHJlc3MFCGJvcnJvd2VkCQDZBAEFB2Fzc2V0SWQFA25pbAkAZQIFDndpdGhkcmF3QW1vdW50BQhib3Jyb3dlZAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQPcmVhbGl6ZUFuZENsb3NlCQD8BwQJARFjb2xsYXRlcmFsQWRkcmVzcwACGHJlYWxpemVQYXJ0aWFsbHlBbmRDbG9zZQkAzAgCBQdfdHJhZGVyCQDMCAIFB2Fzc2V0SWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQ53aXRoZHJhd0Ftb3VudAUDbmlsAwkAAAIFD3JlYWxpemVBbmRDbG9zZQUPcmVhbGl6ZUFuZENsb3NlCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOX3RyYWRlckFkZHJlc3MFDndpdGhkcmF3QW1vdW50CQDZBAEFB2Fzc2V0SWQFA25pbAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIFA25pbAUOd2l0aGRyYXdBbW91bnQDCQAAAgUNJHQwNjM4MTk2NDczNgUNJHQwNjM4MTk2NDczNgQTcXVvdGVXaXRoZHJhd0Ftb3VudAgFDSR0MDYzODE5NjQ3MzYCXzIEFHNlbmRDb2xsYXRlcmFsQWN0aW9uCAUNJHQwNjM4MTk2NDczNgJfMQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgkBDmRlbGV0ZVBvc2l0aW9uAQUHX3RyYWRlcgkBCXVwZGF0ZUFtbQcFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIDCQBmAgUTcXVvdGVXaXRoZHJhd0Ftb3VudAAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUTcXVvdGVXaXRoZHJhd0Ftb3VudAUDbmlsCQENdXBkYXRlQmFsYW5jZQEFDWFtbU5ld0JhbGFuY2UFFHNlbmRDb2xsYXRlcmFsQWN0aW9uCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBAttYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgECE1VuYWJsZSB0byBsaXF1aWRhdGUDAwMJAGYCBQ9zcG90TWFyZ2luUmF0aW8JARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkAZgIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAAAAcJAGYCBQxERUNJTUFMX1VOSVQJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAHBA0kdDA2NjUwNDY2NjU0CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2NjUwNDY2NjU0Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY2NTA0NjY2NTQCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjY1MDQ2NjY1NAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2NjUwNDY2NjU0Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQEbZ2V0UGFydGlhbExpcXVpZGF0aW9uQW1vdW50AgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplBA0kdDA2Njg3OTY2OTgzCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEE29sZFBvc2l0aW9uTm90aW9uYWwIBQ0kdDA2Njg3OTY2OTgzAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwNjY4Nzk2Njk4MwJfMgQNJHQwNjY5OTE2NzIyMwkBCXN3YXBJbnB1dAIFBWlzQWRkBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBVleGNoYW5nZWRQb3NpdGlvblNpemUIBQ0kdDA2Njk5MTY3MjIzAl8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjY5OTE2NzIyMwJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNjY5OTE2NzIyMwJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDY2OTkxNjcyMjMCXzQEF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCAUNJHQwNjY5OTE2NzIyMwJfNQQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRBsaXF1aWRhdGlvblJhdGlvBA0kdDA2NzUxMjY3NzQ1CQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBQtyZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwNjc1MTI2Nzc0NQJfMQQHYmFkRGVidAgFDSR0MDY3NTEyNjc3NDUCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjc1MTI2Nzc0NQJfMwQSdW5yZWFsaXplZFBubEFmdGVyCQBlAgUNdW5yZWFsaXplZFBubAULcmVhbGl6ZWRQbmwEEnJlbWFpbk9wZW5Ob3Rpb25hbAMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkAZQIJAGUCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BRJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCCQBkAgUSdW5yZWFsaXplZFBubEFmdGVyBRNvbGRQb3NpdGlvbk5vdGlvbmFsBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQRbmV3UG9zaXRpb25NYXJnaW4JAGUCBQxyZW1haW5NYXJnaW4FEmxpcXVpZGF0aW9uUGVuYWx0eQQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCQEDYWJzAQUScmVtYWluT3Blbk5vdGlvbmFsBBRuZXdQb3NpdGlvbkxzdFVwZENQRgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIJAGUCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUSbGlxdWlkYXRpb25QZW5hbHR5BA0kdDA2ODkxODY5MDQ3AwkAZgIAAAUKYW1tQmFsYW5jZQkAlAoCAAAJAQNhYnMBBQphbW1CYWxhbmNlCQCUCgIFCmFtbUJhbGFuY2UAAAQNbmV3QW1tQmFsYW5jZQgFDSR0MDY4OTE4NjkwNDcCXzEEA3gxMQgFDSR0MDY4OTE4NjkwNDcCXzIEDSR0MDY5MDU1NjkxMDkJARNnZXRCb3Jyb3dlZEJ5VHJhZGVyAQUHX3RyYWRlcgQIYm9ycm93ZWQIBQ0kdDA2OTA1NTY5MTA5Al8xBAdhc3NldElkCAUNJHQwNjkwNTU2OTEwOQJfMgQVZG9MaXF1aWRhdGVDb2xsYXRlcmFsAwkAZgIFCGJvcnJvd2VkAAAEEGNvbGxhdGVyYWxUb1NlbGwJAQRtdWxkAgUIYm9ycm93ZWQFEGxpcXVpZGF0aW9uUmF0aW8ED3JlYWxpemVBbmRDbG9zZQkA/AcECQERY29sbGF0ZXJhbEFkZHJlc3MAAhByZWFsaXplUGFydGlhbGx5CQDMCAIFB190cmFkZXIJAMwIAgUHYXNzZXRJZAkAzAgCBRBjb2xsYXRlcmFsVG9TZWxsBQNuaWwFA25pbAMJAAACBQ9yZWFsaXplQW5kQ2xvc2UFD3JlYWxpemVBbmRDbG9zZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBRVkb0xpcXVpZGF0ZUNvbGxhdGVyYWwEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQEJdXBkYXRlQW1tBwUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRdjdW11bGF0aXZlTm90aW9uYWxBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQ9mZWVUb0xpcXVpZGF0b3IJAQ11cGRhdGVCYWxhbmNlAQUNbmV3QW1tQmFsYW5jZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQNJHQwNzA5MTQ3MTM2OQkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgIFB190cmFkZXIHBAJ4MQgFDSR0MDcwOTE0NzEzNjkCXzEEB2JhZERlYnQIBQ0kdDA3MDkxNDcxMzY5Al8yBAJ4MggFDSR0MDcwOTE0NzEzNjkCXzMEAngzCAUNJHQwNzA5MTQ3MTM2OQJfNAQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwOTE0NzEzNjkCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDcwOTE0NzEzNjkCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA3MDkxNDcxMzY5Al83BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDcwOTE0NzEzNjkCXzgEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MDkxNDcxMzY5Al85BBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwNzA5MTQ3MTM2OQNfMTAEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzA5MTQ3MTM2OQNfMTEED3RvdGFsU2hvcnRBZnRlcggFDSR0MDcwOTE0NzEzNjkDXzEyBBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNzE3ODE3MTkxMAMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA3MTc4MTcxOTEwAl8xBAN4MTEIBQ0kdDA3MTc4MTcxOTEwAl8yBA0kdDA3MTkxODcxOTcyCQETZ2V0Qm9ycm93ZWRCeVRyYWRlcgEFB190cmFkZXIECGJvcnJvd2VkCAUNJHQwNzE5MTg3MTk3MgJfMQQHYXNzZXRJZAgFDSR0MDcxOTE4NzE5NzICXzIEFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAMJAGYCBQhib3Jyb3dlZAAABA9yZWFsaXplQW5kQ2xvc2UJAPwHBAkBEWNvbGxhdGVyYWxBZGRyZXNzAAIYcmVhbGl6ZVBhcnRpYWxseUFuZENsb3NlCQDMCAIFB190cmFkZXIJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQAAAgUPcmVhbGl6ZUFuZENsb3NlBQ9yZWFsaXplQW5kQ2xvc2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFWRvTGlxdWlkYXRlQ29sbGF0ZXJhbAUVZG9MaXF1aWRhdGVDb2xsYXRlcmFsBAF4AwkAZgIFB2JhZERlYnQAAAQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBQdiYWREZWJ0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFAXgFAXgEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABBVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAMDAwkAZgIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAgFCWxhc3RCbG9jawl0aW1lc3RhbXAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQNJHQwNzM5OTk3NDA2MQkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDczOTk5NzQwNjECXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3Mzk5OTc0MDYxAl8yCQENdXBkYXRlRnVuZGluZwUJAGQCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGQCCQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRNsb25nUHJlbWl1bUZyYWN0aW9uCQBkAgkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlAWkBGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUABA0kdDA3NDQ0Mzc0NTY0CQEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UBCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDc0NDQzNzQ1NjQCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDc0NDQzNzQ1NjQCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA3NDQ0Mzc0NTY0Al8zCQEQdXBkYXRlQW1tV2VpZ2h0cwIFE25ld1F1b3RlQXNzZXRXZWlnaHQFEm5ld0Jhc2VBc3NldFdlaWdodAFpAQV2X2dldAEHX3RyYWRlcgQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA0kdDA3NDc0Mjc0ODAyCQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uAgUHX3RyYWRlcgcEAngxCAUNJHQwNzQ3NDI3NDgwMgJfMQQCeDIIBQ0kdDA3NDc0Mjc0ODAyAl8yBAJ4MwgFDSR0MDc0NzQyNzQ4MDICXzMEAng0CAUNJHQwNzQ3NDI3NDgwMgJfNAkAAgEJAKwCAgkArAICCQCsAgIJAQFzAQUCeDIJAQFzAQUCeDMJAQFzAQUCeDQJAQFzAQkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASd2aWV3X2NhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQBB190cmFkZXIEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQNJHQwNzUwMTM3NTExNAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwNzUwMTM3NTExNAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDA3NTAxMzc1MTE0Al8yBANwb24IBQ0kdDA3NTAxMzc1MTE0Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDc1MDEzNzUxMTQCXzQEDSR0MDc1MTE3NzUyMTgJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDc1MTE3NzUyMTgCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA3NTExNzc1MjE4Al8yBA0kdDA3NTIyMTc1MzkzCQEiY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAQFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FEXBvc2l0aW9uTHN0VXBkQ1BGBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA3NTIyMTc1MzkzAl8xBAdiYWREZWJ0CAUNJHQwNzUyMjE3NTM5MwJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA3NTIyMTc1MzkzAl8zCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAQFzAQUMcmVtYWluTWFyZ2luCQEBcwEFDmZ1bmRpbmdQYXltZW50CQEBcwEJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIJAQFzAQUNdW5yZWFsaXplZFBubAkBAXMBBQdiYWREZWJ0CQEBcwEFEHBvc2l0aW9uTm90aW9uYWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVdmlld19nZXRQZWdBZGp1c3RDb3N0AQZfcHJpY2UEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAQUGX3ByaWNlCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDc1NzQwNzU4MjEJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDc1NzQwNzU4MjECXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDc1NzQwNzU4MjECXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQNJHQwNzYwNDA3NjEwMgkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDc2MDQwNzYxMDICXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3NjA0MDc2MTAyAl8yBAtsb25nRnVuZGluZwkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UEDHNob3J0RnVuZGluZwkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQkArAICCQCsAgIJAKwCAgkBAXMBBQtsb25nRnVuZGluZwkBAXMBBQxzaG9ydEZ1bmRpbmcJAQFzAQkBEGdldFR3YXBTcG90UHJpY2UACQEBcwEJARJnZXRPcmFjbGVUd2FwUHJpY2UAAWkBGHZpZXdfZ2V0Qm9ycm93ZWRCeVRyYWRlcgEHX3RyYWRlcgQNJHQwNzYzOTI3NjQ0NgkBE2dldEJvcnJvd2VkQnlUcmFkZXIBBQdfdHJhZGVyBAhib3Jyb3dlZAgFDSR0MDc2MzkyNzY0NDYCXzEEB2Fzc2V0SWQIBQ0kdDA3NjM5Mjc2NDQ2Al8yCQACAQkArAICCQEBcwEFCGJvcnJvd2VkBQdhc3NldElkAQJ0eAEGdmVyaWZ5AAkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkBDmFkbWluUHVibGljS2V5AOSlq+E=", "height": 2338746, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: CjPr1ZUbvHhwCp5H3doEPXc15xKDeNpQkf3Wk5L56KHH Next: Ds8AKnKzvELv1CDkJdSiB3h5ayuwMLje1nN26Vw3mvgv Diff:
OldNewDifferences
430430 let quoteAssetReserveAfter = if (_isAdd)
431431 then (_qtAstR + _quoteAssetAmount)
432432 else (_qtAstR - _quoteAssetAmount)
433- let baseAssetReserveAfter = divd(k, quoteAssetReserveAfter)
433+ let baseAssetReserveAfter = divd(k, muld(quoteAssetReserveAfter, _qtAstW))
434434 let amountBaseAssetBoughtAbs = divd(abs((baseAssetReserveAfter - _bsAstR)), _qtAstW)
435435 let amountBaseAssetBought = if (_isAdd)
436436 then amountBaseAssetBoughtAbs
437437 else -(amountBaseAssetBoughtAbs)
438- let $t01631916512 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
439- let quoteAssetReserveAfter1 = $t01631916512._1
440- let baseAssetReserveAfter1 = $t01631916512._2
441- let totalPositionSizeAfter1 = $t01631916512._3
442- let cumulativeNotionalAfter1 = $t01631916512._4
438+ let $t01633316526 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
439+ let quoteAssetReserveAfter1 = $t01633316526._1
440+ let baseAssetReserveAfter1 = $t01633316526._2
441+ let totalPositionSizeAfter1 = $t01633316526._3
442+ let cumulativeNotionalAfter1 = $t01633316526._4
443443 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
444444 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
445445 let priceDiff = abs((priceBefore - marketPrice))
459459 }
460460 else 0
461461 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
462- let $t01803118158 = if ((0 > signedMargin))
462+ let $t01804518172 = if ((0 > signedMargin))
463463 then $Tuple2(0, abs(signedMargin))
464464 else $Tuple2(abs(signedMargin), 0)
465- let remainMargin = $t01803118158._1
466- let badDebt = $t01803118158._2
465+ let remainMargin = $t01804518172._1
466+ let badDebt = $t01804518172._2
467467 $Tuple3(remainMargin, badDebt, fundingPayment)
468468 }
469469
480480 let quoteAssetAfter = divd(k, muld(baseAssetPoolAmountAfter, _baseAssetWeight))
481481 let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
482482 let maxPriceImpactValue = maxPriceImpact()
483- let $t01932619519 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
484- let quoteAssetReserveAfter1 = $t01932619519._1
485- let baseAssetReserveAfter1 = $t01932619519._2
486- let totalPositionSizeAfter1 = $t01932619519._3
487- let cumulativeNotionalAfter1 = $t01932619519._4
483+ let $t01934019533 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
484+ let quoteAssetReserveAfter1 = $t01934019533._1
485+ let baseAssetReserveAfter1 = $t01934019533._2
486+ let totalPositionSizeAfter1 = $t01934019533._3
487+ let cumulativeNotionalAfter1 = $t01934019533._4
488488 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
489489 let priceDiff = abs((priceBefore - marketPrice))
490490 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
545545 let isShort = (0 > _positionSize)
546546 let positionNotional = if ((_option == PNL_OPTION_SPOT))
547547 then {
548- let $t02289423114 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
549- let outPositionNotional = $t02289423114._1
550- let x1 = $t02289423114._2
551- let x2 = $t02289423114._3
552- let x3 = $t02289423114._4
548+ let $t02290823128 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
549+ let outPositionNotional = $t02290823128._1
550+ let x1 = $t02290823128._2
551+ let x2 = $t02290823128._3
552+ let x3 = $t02290823128._4
553553 outPositionNotional
554554 }
555555 else muld(positionSizeAbs, getOracleTwapPrice())
570570
571571
572572 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
573- let $t02453924667 = getPosition(_trader)
574- let positionSize = $t02453924667._1
575- let positionMargin = $t02453924667._2
576- let positionOpenNotional = $t02453924667._3
577- let positionLstUpdCPF = $t02453924667._4
573+ let $t02455324681 = getPosition(_trader)
574+ let positionSize = $t02455324681._1
575+ let positionMargin = $t02455324681._2
576+ let positionOpenNotional = $t02455324681._3
577+ let positionLstUpdCPF = $t02455324681._4
578578 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
579579 }
580580
583583
584584
585585 func getMarginRatioByOption (_trader,_option) = {
586- let $t02518025291 = getPosition(_trader)
587- let positionSize = $t02518025291._1
588- let positionMargin = $t02518025291._2
589- let pon = $t02518025291._3
590- let positionLstUpdCPF = $t02518025291._4
591- let $t02529725390 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
592- let positionNotional = $t02529725390._1
593- let unrealizedPnl = $t02529725390._2
594- let $t02539525561 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
595- let remainMargin = $t02539525561._1
596- let badDebt = $t02539525561._2
586+ let $t02519425305 = getPosition(_trader)
587+ let positionSize = $t02519425305._1
588+ let positionMargin = $t02519425305._2
589+ let pon = $t02519425305._3
590+ let positionLstUpdCPF = $t02519425305._4
591+ let $t02531125404 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
592+ let positionNotional = $t02531125404._1
593+ let unrealizedPnl = $t02531125404._2
594+ let $t02540925575 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
595+ let remainMargin = $t02540925575._1
596+ let badDebt = $t02540925575._2
597597 calcMarginRatio(remainMargin, badDebt, positionNotional)
598598 }
599599
618618
619619
620620 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
621- let $t02679426922 = getPosition(_trader)
622- let positionSize = $t02679426922._1
623- let positionMargin = $t02679426922._2
624- let positionOpenNotional = $t02679426922._3
625- let positionLstUpdCPF = $t02679426922._4
621+ let $t02680826936 = getPosition(_trader)
622+ let positionSize = $t02680826936._1
623+ let positionMargin = $t02680826936._2
624+ let positionOpenNotional = $t02680826936._3
625+ let positionLstUpdCPF = $t02680826936._4
626626 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
627- let $t02701727185 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
628- let remainMargin = $t02701727185._1
629- let badDebt = $t02701727185._2
627+ let $t02703127199 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
628+ let remainMargin = $t02703127199._1
629+ let badDebt = $t02703127199._2
630630 let exchangedPositionSize = -(positionSize)
631631 let realizedPnl = unrealizedPnl
632632 let marginToVault = -(remainMargin)
633- let $t02731227617 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
634- let exchangedQuoteAssetAmount = $t02731227617._1
635- let quoteAssetReserveAfter = $t02731227617._2
636- let baseAssetReserveAfter = $t02731227617._3
637- let totalPositionSizeAfter = $t02731227617._4
638- let cumulativeNotionalAfter = $t02731227617._5
639- let totalLongAfter = $t02731227617._6
640- let totalShortAfter = $t02731227617._7
633+ let $t02732627631 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
634+ let exchangedQuoteAssetAmount = $t02732627631._1
635+ let quoteAssetReserveAfter = $t02732627631._2
636+ let baseAssetReserveAfter = $t02732627631._3
637+ let totalPositionSizeAfter = $t02732627631._4
638+ let cumulativeNotionalAfter = $t02732627631._5
639+ let totalLongAfter = $t02732627631._6
640+ let totalShortAfter = $t02732627631._7
641641 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
642642 $Tuple12(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter)
643643 }
686686 then $Tuple2(qtAstR(), bsAstR())
687687 else {
688688 let direction = (_positionSize > 0)
689- let $t02960429783 = swapOutput(direction, abs(_positionSize), false)
690- let currentNetMarketValue = $t02960429783._1
691- let terminalQuoteAssetReserve = $t02960429783._2
692- let terminalBaseAssetReserve = $t02960429783._3
689+ let $t02961829797 = swapOutput(direction, abs(_positionSize), false)
690+ let currentNetMarketValue = $t02961829797._1
691+ let terminalQuoteAssetReserve = $t02961829797._2
692+ let terminalBaseAssetReserve = $t02961829797._3
693693 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
694694 }
695695 }
760760 func getAdjustedFee (i,_baseFeeDiscount) = {
761761 let baseFeeRaw = fee()
762762 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
763- let $t03287633484 = if ((size(i.payments) > 1))
763+ let $t03289033498 = if ((size(i.payments) > 1))
764764 then {
765765 let artifactId = toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid attached artifact"))
766766 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, artifactId))
773773 else throw("Invalid attached artifact")
774774 }
775775 else $Tuple2(baseFee, false)
776- let adjustedFee = $t03287633484._1
777- let burnArtifact = $t03287633484._2
776+ let adjustedFee = $t03289033498._1
777+ let burnArtifact = $t03289033498._2
778778 $Tuple2(adjustedFee, burnArtifact)
779779 }
780780
996996 else paused())
997997 then throw("Invalid decreasePosition parameters")
998998 else {
999- let $t04546445616 = getPosition(toString(i.caller))
1000- let oldPositionSize = $t04546445616._1
1001- let oldPositionMargin = $t04546445616._2
1002- let oldPositionOpenNotional = $t04546445616._3
1003- let oldPositionLstUpdCPF = $t04546445616._4
999+ let $t04547845630 = getPosition(toString(i.caller))
1000+ let oldPositionSize = $t04547845630._1
1001+ let oldPositionMargin = $t04547845630._2
1002+ let oldPositionOpenNotional = $t04547845630._3
1003+ let oldPositionLstUpdCPF = $t04547845630._4
10041004 let _direction = if ((oldPositionSize > 0))
10051005 then DIR_SHORT
10061006 else DIR_LONG
10071007 let isAdd = (_direction == DIR_LONG)
10081008 let openNotional = muld(_amount, _leverage)
1009- let $t04578945905 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1010- let oldPositionNotional = $t04578945905._1
1011- let unrealizedPnl = $t04578945905._2
1012- let $t04591148460 = if ((oldPositionNotional > openNotional))
1009+ let $t04580345919 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1010+ let oldPositionNotional = $t04580345919._1
1011+ let unrealizedPnl = $t04580345919._2
1012+ let $t04592548474 = if ((oldPositionNotional > openNotional))
10131013 then {
1014- let $t04628846507 = swapInput(isAdd, openNotional)
1015- let exchangedPositionSize = $t04628846507._1
1016- let quoteAssetReserveAfter = $t04628846507._2
1017- let baseAssetReserveAfter = $t04628846507._3
1018- let totalPositionSizeAfter = $t04628846507._4
1019- let cumulativeNotionalAfter = $t04628846507._5
1014+ let $t04630246521 = swapInput(isAdd, openNotional)
1015+ let exchangedPositionSize = $t04630246521._1
1016+ let quoteAssetReserveAfter = $t04630246521._2
1017+ let baseAssetReserveAfter = $t04630246521._3
1018+ let totalPositionSizeAfter = $t04630246521._4
1019+ let cumulativeNotionalAfter = $t04630246521._5
10201020 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
10211021 if (if ((_minBaseAssetAmount != 0))
10221022 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
10241024 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
10251025 else {
10261026 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1027- let $t04694447189 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1028- let remainMargin = $t04694447189._1
1029- let badDebt = $t04694447189._2
1030- let fundingPayment = $t04694447189._3
1027+ let $t04695847203 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1028+ let remainMargin = $t04695847203._1
1029+ let badDebt = $t04695847203._2
1030+ let fundingPayment = $t04695847203._3
10311031 let exchangedQuoteAssetAmount = openNotional
10321032 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
10331033 let remainOpenNotional = if ((oldPositionSize > 0))
10421042 }
10431043 }
10441044 else throw("Close position first")
1045- let newPositionSize = $t04591148460._1
1046- let newPositionRemainMargin = $t04591148460._2
1047- let newPositionOpenNotional = $t04591148460._3
1048- let newPositionLatestCPF = $t04591148460._4
1049- let baseAssetReserveAfter = $t04591148460._5
1050- let quoteAssetReserveAfter = $t04591148460._6
1051- let totalPositionSizeAfter = $t04591148460._7
1052- let cumulativeNotionalAfter = $t04591148460._8
1053- let openInterestNotionalAfter = $t04591148460._9
1054- let totalLongAfter = $t04591148460._10
1055- let totalShortAfter = $t04591148460._11
1045+ let newPositionSize = $t04592548474._1
1046+ let newPositionRemainMargin = $t04592548474._2
1047+ let newPositionOpenNotional = $t04592548474._3
1048+ let newPositionLatestCPF = $t04592548474._4
1049+ let baseAssetReserveAfter = $t04592548474._5
1050+ let quoteAssetReserveAfter = $t04592548474._6
1051+ let totalPositionSizeAfter = $t04592548474._7
1052+ let cumulativeNotionalAfter = $t04592548474._8
1053+ let openInterestNotionalAfter = $t04592548474._9
1054+ let totalLongAfter = $t04592548474._10
1055+ let totalShortAfter = $t04592548474._11
10561056 let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
10571057 if ((notifyNotional == notifyNotional))
10581058 then (updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter))
11021102 case _ =>
11031103 throw("Invalid computeFeeDiscount result")
11041104 }
1105- let $t05012350187 = getAdjustedFee(i, feeDiscount)
1106- let adjustedFee = $t05012350187._1
1107- let burnArtifact = $t05012350187._2
1105+ let $t05013750201 = getAdjustedFee(i, feeDiscount)
1106+ let adjustedFee = $t05013750201._1
1107+ let burnArtifact = $t05013750201._2
11081108 let rawFeeAmount = muld(_rawAmount, adjustedFee)
11091109 let _amount = (_rawAmount - rawFeeAmount)
11101110 let distributeFeeAmount = if (isCollateralAsset)
11471147 throw("Invalid referrerFee")
11481148 }
11491149 let feeAmount = (distributeFeeAmount - referrerFee)
1150- let $t05150351643 = getPosition(_trader)
1151- let oldPositionSize = $t05150351643._1
1152- let oldPositionMargin = $t05150351643._2
1153- let oldPositionOpenNotional = $t05150351643._3
1154- let oldPositionLstUpdCPF = $t05150351643._4
1150+ let $t05151751657 = getPosition(_trader)
1151+ let oldPositionSize = $t05151751657._1
1152+ let oldPositionMargin = $t05151751657._2
1153+ let oldPositionOpenNotional = $t05151751657._3
1154+ let oldPositionLstUpdCPF = $t05151751657._4
11551155 let isNewPosition = (oldPositionSize == 0)
11561156 let isSameDirection = if ((oldPositionSize > 0))
11571157 then (_direction == DIR_LONG)
11601160 then isSameDirection
11611161 else false
11621162 let isAdd = (_direction == DIR_LONG)
1163- let $t05193254517 = if (if (isNewPosition)
1163+ let $t05194654531 = if (if (isNewPosition)
11641164 then true
11651165 else expandExisting)
11661166 then {
11671167 let openNotional = muld(_amount, _leverage)
1168- let $t05235652562 = swapInput(isAdd, openNotional)
1169- let amountBaseAssetBought = $t05235652562._1
1170- let quoteAssetReserveAfter = $t05235652562._2
1171- let baseAssetReserveAfter = $t05235652562._3
1172- let totalPositionSizeAfter = $t05235652562._4
1173- let cumulativeNotionalAfter = $t05235652562._5
1168+ let $t05237052576 = swapInput(isAdd, openNotional)
1169+ let amountBaseAssetBought = $t05237052576._1
1170+ let quoteAssetReserveAfter = $t05237052576._2
1171+ let baseAssetReserveAfter = $t05237052576._3
1172+ let totalPositionSizeAfter = $t05237052576._4
1173+ let cumulativeNotionalAfter = $t05237052576._5
11741174 if (if ((_minBaseAssetAmount != 0))
11751175 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
11761176 else false)
11781178 else {
11791179 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
11801180 let increaseMarginRequirement = divd(openNotional, _leverage)
1181- let $t05294353182 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1182- let remainMargin = $t05294353182._1
1183- let x1 = $t05294353182._2
1184- let x2 = $t05294353182._3
1181+ let $t05295753196 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1182+ let remainMargin = $t05295753196._1
1183+ let x1 = $t05295753196._2
1184+ let x2 = $t05295753196._3
11851185 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
11861186 then throw("Over max spread limit")
11871187 else $Tuple11(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
11931193 }
11941194 else {
11951195 let openNotional = muld(_amount, _leverage)
1196- let $t05421054326 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1197- let oldPositionNotional = $t05421054326._1
1198- let unrealizedPnl = $t05421054326._2
1196+ let $t05422454340 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1197+ let oldPositionNotional = $t05422454340._1
1198+ let unrealizedPnl = $t05422454340._2
11991199 if ((oldPositionNotional > openNotional))
12001200 then throw("Use decreasePosition to decrease position size")
12011201 else throw("Close position first")
12021202 }
1203- let newPositionSize = $t05193254517._1
1204- let newPositionRemainMargin = $t05193254517._2
1205- let newPositionOpenNotional = $t05193254517._3
1206- let newPositionLatestCPF = $t05193254517._4
1207- let baseAssetReserveAfter = $t05193254517._5
1208- let quoteAssetReserveAfter = $t05193254517._6
1209- let totalPositionSizeAfter = $t05193254517._7
1210- let cumulativeNotionalAfter = $t05193254517._8
1211- let openInterestNotionalAfter = $t05193254517._9
1212- let totalLongAfter = $t05193254517._10
1213- let totalShortAfter = $t05193254517._11
1203+ let newPositionSize = $t05194654531._1
1204+ let newPositionRemainMargin = $t05194654531._2
1205+ let newPositionOpenNotional = $t05194654531._3
1206+ let newPositionLatestCPF = $t05194654531._4
1207+ let baseAssetReserveAfter = $t05194654531._5
1208+ let quoteAssetReserveAfter = $t05194654531._6
1209+ let totalPositionSizeAfter = $t05194654531._7
1210+ let cumulativeNotionalAfter = $t05194654531._8
1211+ let openInterestNotionalAfter = $t05194654531._9
1212+ let totalLongAfter = $t05194654531._10
1213+ let totalShortAfter = $t05194654531._11
12141214 let feeToStakers = (feeAmount / 2)
12151215 let feeToInsurance = (feeAmount - feeToStakers)
12161216 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
12781278 case _ =>
12791279 throw("Invalid computeFeeDiscount result")
12801280 }
1281- let $t05659456658 = getAdjustedFee(i, feeDiscount)
1282- let adjustedFee = $t05659456658._1
1283- let burnArtifact = $t05659456658._2
1281+ let $t05660856672 = getAdjustedFee(i, feeDiscount)
1282+ let adjustedFee = $t05660856672._1
1283+ let burnArtifact = $t05660856672._2
12841284 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12851285 let _amount = (_rawAmount - rawFeeAmount)
12861286 let distributeFeeAmount = if (isCollateralAsset)
13231323 throw("Invalid referrerFee")
13241324 }
13251325 let feeAmount = (distributeFeeAmount - referrerFee)
1326- let $t05795758097 = getPosition(_trader)
1327- let oldPositionSize = $t05795758097._1
1328- let oldPositionMargin = $t05795758097._2
1329- let oldPositionOpenNotional = $t05795758097._3
1330- let oldPositionLstUpdCPF = $t05795758097._4
1326+ let $t05797158111 = getPosition(_trader)
1327+ let oldPositionSize = $t05797158111._1
1328+ let oldPositionMargin = $t05797158111._2
1329+ let oldPositionOpenNotional = $t05797158111._3
1330+ let oldPositionLstUpdCPF = $t05797158111._4
13311331 let feeToStakers = (feeAmount / 2)
13321332 let feeToInsurance = (feeAmount - feeToStakers)
13331333 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13721372 else paused())
13731373 then throw("Invalid removeMargin parameters")
13741374 else {
1375- let $t05920359343 = getPosition(_trader)
1376- let oldPositionSize = $t05920359343._1
1377- let oldPositionMargin = $t05920359343._2
1378- let oldPositionOpenNotional = $t05920359343._3
1379- let oldPositionLstUpdCPF = $t05920359343._4
1375+ let $t05921759357 = getPosition(_trader)
1376+ let oldPositionSize = $t05921759357._1
1377+ let oldPositionMargin = $t05921759357._2
1378+ let oldPositionOpenNotional = $t05921759357._3
1379+ let oldPositionLstUpdCPF = $t05921759357._4
13801380 let marginDelta = -(_amount)
1381- let $t05938059559 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1382- let remainMargin = $t05938059559._1
1383- let badDebt = $t05938059559._2
1381+ let $t05939459573 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1382+ let remainMargin = $t05939459573._1
1383+ let badDebt = $t05939459573._2
13841384 if ((badDebt != 0))
13851385 then throw("Invalid removed margin amount")
13861386 else {
13891389 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
13901390 else {
13911391 let quoteAssetStr = toBase58String(quoteAsset())
1392- let $t06000360057 = getBorrowedByTrader(_trader)
1393- let borrowed = $t06000360057._1
1394- let assetId = $t06000360057._2
1392+ let $t06001760071 = getBorrowedByTrader(_trader)
1393+ let borrowed = $t06001760071._1
1394+ let assetId = $t06001760071._2
13951395 let toRepay = if ((_amount > borrowed))
13961396 then borrowed
13971397 else _amount
14501450 else paused())
14511451 then throw("Invalid closePosition parameters")
14521452 else {
1453- let $t06230762685 = internalClosePosition(_trader, true)
1454- let x1 = $t06230762685._1
1455- let positionBadDebt = $t06230762685._2
1456- let realizedPnl = $t06230762685._3
1457- let marginToVault = $t06230762685._4
1458- let quoteAssetReserveAfter = $t06230762685._5
1459- let baseAssetReserveAfter = $t06230762685._6
1460- let totalPositionSizeAfter = $t06230762685._7
1461- let cumulativeNotionalAfter = $t06230762685._8
1462- let openInterestNotionalAfter = $t06230762685._9
1463- let x2 = $t06230762685._10
1464- let totalLongAfter = $t06230762685._11
1465- let totalShortAfter = $t06230762685._12
1453+ let $t06232162699 = internalClosePosition(_trader, true)
1454+ let x1 = $t06232162699._1
1455+ let positionBadDebt = $t06232162699._2
1456+ let realizedPnl = $t06232162699._3
1457+ let marginToVault = $t06232162699._4
1458+ let quoteAssetReserveAfter = $t06232162699._5
1459+ let baseAssetReserveAfter = $t06232162699._6
1460+ let totalPositionSizeAfter = $t06232162699._7
1461+ let cumulativeNotionalAfter = $t06232162699._8
1462+ let openInterestNotionalAfter = $t06232162699._9
1463+ let x2 = $t06232162699._10
1464+ let totalLongAfter = $t06232162699._11
1465+ let totalShortAfter = $t06232162699._12
14661466 if ((positionBadDebt > 0))
14671467 then throw("Unable to close position with bad debt")
14681468 else {
14691469 let withdrawAmount = abs(marginToVault)
14701470 let ammBalance = (cbalance() - withdrawAmount)
1471- let $t06300963524 = if ((0 > ammBalance))
1471+ let $t06302363538 = if ((0 > ammBalance))
14721472 then $Tuple2(0, abs(ammBalance))
14731473 else $Tuple2(ammBalance, 0)
1474- let ammNewBalance = $t06300963524._1
1475- let x11 = $t06300963524._2
1474+ let ammNewBalance = $t06302363538._1
1475+ let x11 = $t06302363538._2
14761476 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
14771477 if ((unstake == unstake))
14781478 then {
1479- let $t06373663790 = getBorrowedByTrader(_trader)
1480- let borrowed = $t06373663790._1
1481- let assetId = $t06373663790._2
1482- let $t06380564722 = if ((borrowed > 0))
1479+ let $t06375063804 = getBorrowedByTrader(_trader)
1480+ let borrowed = $t06375063804._1
1481+ let assetId = $t06375063804._2
1482+ let $t06381964736 = if ((borrowed > 0))
14831483 then if ((withdrawAmount >= borrowed))
14841484 then {
14851485 let doRepay = invoke(collateralAddress(), "repay", [_trader, assetId], [AttachedPayment(quoteAsset(), borrowed)])
14941494 else throw("Strict value is not equal to itself.")
14951495 }
14961496 else $Tuple2(nil, withdrawAmount)
1497- if (($t06380564722 == $t06380564722))
1497+ if (($t06381964736 == $t06381964736))
14981498 then {
1499- let quoteWithdrawAmount = $t06380564722._2
1500- let sendCollateralAction = $t06380564722._1
1499+ let quoteWithdrawAmount = $t06381964736._2
1500+ let sendCollateralAction = $t06381964736._1
15011501 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
15021502 if ((notifyNotional == notifyNotional))
15031503 then ((((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ (if ((quoteWithdrawAmount > 0))
15421542 then (DECIMAL_UNIT > partialLiquidationRatio())
15431543 else false)
15441544 then {
1545- let $t06649066640 = getPosition(_trader)
1546- let oldPositionSize = $t06649066640._1
1547- let oldPositionMargin = $t06649066640._2
1548- let oldPositionOpenNotional = $t06649066640._3
1549- let oldPositionLstUpdCPF = $t06649066640._4
1545+ let $t06650466654 = getPosition(_trader)
1546+ let oldPositionSize = $t06650466654._1
1547+ let oldPositionMargin = $t06650466654._2
1548+ let oldPositionOpenNotional = $t06650466654._3
1549+ let oldPositionLstUpdCPF = $t06650466654._4
15501550 let _direction = if ((oldPositionSize > 0))
15511551 then DIR_SHORT
15521552 else DIR_LONG
15531553 let isAdd = (_direction == DIR_LONG)
15541554 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1555- let $t06686566969 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1556- let oldPositionNotional = $t06686566969._1
1557- let unrealizedPnl = $t06686566969._2
1558- let $t06697767209 = swapInput(isAdd, exchangedQuoteAssetAmount)
1559- let exchangedPositionSize = $t06697767209._1
1560- let quoteAssetReserveAfter = $t06697767209._2
1561- let baseAssetReserveAfter = $t06697767209._3
1562- let totalPositionSizeAfter = $t06697767209._4
1563- let cumulativeNotionalAfter = $t06697767209._5
1555+ let $t06687966983 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1556+ let oldPositionNotional = $t06687966983._1
1557+ let unrealizedPnl = $t06687966983._2
1558+ let $t06699167223 = swapInput(isAdd, exchangedQuoteAssetAmount)
1559+ let exchangedPositionSize = $t06699167223._1
1560+ let quoteAssetReserveAfter = $t06699167223._2
1561+ let baseAssetReserveAfter = $t06699167223._3
1562+ let totalPositionSizeAfter = $t06699167223._4
1563+ let cumulativeNotionalAfter = $t06699167223._5
15641564 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
15651565 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1566- let $t06749867731 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1567- let remainMargin = $t06749867731._1
1568- let badDebt = $t06749867731._2
1569- let fundingPayment = $t06749867731._3
1566+ let $t06751267745 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1567+ let remainMargin = $t06751267745._1
1568+ let badDebt = $t06751267745._2
1569+ let fundingPayment = $t06751267745._3
15701570 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
15711571 let remainOpenNotional = if ((oldPositionSize > 0))
15721572 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
15801580 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
15811581 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
15821582 let ammBalance = (cbalance() - liquidationPenalty)
1583- let $t06890469033 = if ((0 > ammBalance))
1583+ let $t06891869047 = if ((0 > ammBalance))
15841584 then $Tuple2(0, abs(ammBalance))
15851585 else $Tuple2(ammBalance, 0)
1586- let newAmmBalance = $t06890469033._1
1587- let x11 = $t06890469033._2
1588- let $t06904169095 = getBorrowedByTrader(_trader)
1589- let borrowed = $t06904169095._1
1590- let assetId = $t06904169095._2
1586+ let newAmmBalance = $t06891869047._1
1587+ let x11 = $t06891869047._2
1588+ let $t06905569109 = getBorrowedByTrader(_trader)
1589+ let borrowed = $t06905569109._1
1590+ let assetId = $t06905569109._2
15911591 let doLiquidateCollateral = if ((borrowed > 0))
15921592 then {
15931593 let collateralToSell = muld(borrowed, liquidationRatio)
16211621 else throw("Strict value is not equal to itself.")
16221622 }
16231623 else {
1624- let $t07090071355 = internalClosePosition(_trader, false)
1625- let x1 = $t07090071355._1
1626- let badDebt = $t07090071355._2
1627- let x2 = $t07090071355._3
1628- let x3 = $t07090071355._4
1629- let quoteAssetReserveAfter = $t07090071355._5
1630- let baseAssetReserveAfter = $t07090071355._6
1631- let totalPositionSizeAfter = $t07090071355._7
1632- let cumulativeNotionalAfter = $t07090071355._8
1633- let openInterestNotionalAfter = $t07090071355._9
1634- let exchangedQuoteAssetAmount = $t07090071355._10
1635- let totalLongAfter = $t07090071355._11
1636- let totalShortAfter = $t07090071355._12
1624+ let $t07091471369 = internalClosePosition(_trader, false)
1625+ let x1 = $t07091471369._1
1626+ let badDebt = $t07091471369._2
1627+ let x2 = $t07091471369._3
1628+ let x3 = $t07091471369._4
1629+ let quoteAssetReserveAfter = $t07091471369._5
1630+ let baseAssetReserveAfter = $t07091471369._6
1631+ let totalPositionSizeAfter = $t07091471369._7
1632+ let cumulativeNotionalAfter = $t07091471369._8
1633+ let openInterestNotionalAfter = $t07091471369._9
1634+ let exchangedQuoteAssetAmount = $t07091471369._10
1635+ let totalLongAfter = $t07091471369._11
1636+ let totalShortAfter = $t07091471369._12
16371637 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
16381638 let feeToLiquidator = (liquidationPenalty / 2)
16391639 let feeToInsurance = (liquidationPenalty - feeToLiquidator)
16401640 let ammBalance = (cbalance() - liquidationPenalty)
1641- let $t07176771896 = if ((0 > ammBalance))
1641+ let $t07178171910 = if ((0 > ammBalance))
16421642 then $Tuple2(0, abs(ammBalance))
16431643 else $Tuple2(ammBalance, 0)
1644- let newAmmBalance = $t07176771896._1
1645- let x11 = $t07176771896._2
1646- let $t07190471958 = getBorrowedByTrader(_trader)
1647- let borrowed = $t07190471958._1
1648- let assetId = $t07190471958._2
1644+ let newAmmBalance = $t07178171910._1
1645+ let x11 = $t07178171910._2
1646+ let $t07191871972 = getBorrowedByTrader(_trader)
1647+ let borrowed = $t07191871972._1
1648+ let assetId = $t07191871972._2
16491649 let doLiquidateCollateral = if ((borrowed > 0))
16501650 then {
16511651 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, assetId], nil)
17021702 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
17031703 else {
17041704 let underlyingPrice = getOracleTwapPrice()
1705- let $t07398574047 = getFunding()
1706- let shortPremiumFraction = $t07398574047._1
1707- let longPremiumFraction = $t07398574047._2
1705+ let $t07399974061 = getFunding()
1706+ let shortPremiumFraction = $t07399974061._1
1707+ let longPremiumFraction = $t07399974061._2
17081708 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
17091709 }
17101710 }
17131713
17141714 @Callable(i)
17151715 func syncTerminalPriceToOracle () = {
1716- let $t07442974550 = getSyncTerminalPrice(getOracleTwapPrice())
1717- let newQuoteAssetWeight = $t07442974550._1
1718- let newBaseAssetWeight = $t07442974550._2
1719- let marginToVault = $t07442974550._3
1716+ let $t07444374564 = getSyncTerminalPrice(getOracleTwapPrice())
1717+ let newQuoteAssetWeight = $t07444374564._1
1718+ let newBaseAssetWeight = $t07444374564._2
1719+ let marginToVault = $t07444374564._3
17201720 updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)
17211721 }
17221722
17271727 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17281728 if ((sync == sync))
17291729 then {
1730- let $t07472874788 = internalClosePosition(_trader, false)
1731- let x1 = $t07472874788._1
1732- let x2 = $t07472874788._2
1733- let x3 = $t07472874788._3
1734- let x4 = $t07472874788._4
1730+ let $t07474274802 = internalClosePosition(_trader, false)
1731+ let x1 = $t07474274802._1
1732+ let x2 = $t07474274802._2
1733+ let x3 = $t07474274802._3
1734+ let x4 = $t07474274802._4
17351735 throw((((s(x2) + s(x3)) + s(x4)) + s(getMarginRatio(_trader))))
17361736 }
17371737 else throw("Strict value is not equal to itself.")
17441744 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17451745 if ((sync == sync))
17461746 then {
1747- let $t07499975100 = getPosition(_trader)
1748- let positionSize = $t07499975100._1
1749- let positionMargin = $t07499975100._2
1750- let pon = $t07499975100._3
1751- let positionLstUpdCPF = $t07499975100._4
1752- let $t07510375204 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1753- let positionNotional = $t07510375204._1
1754- let unrealizedPnl = $t07510375204._2
1755- let $t07520775379 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1756- let remainMargin = $t07520775379._1
1757- let badDebt = $t07520775379._2
1758- let fundingPayment = $t07520775379._3
1747+ let $t07501375114 = getPosition(_trader)
1748+ let positionSize = $t07501375114._1
1749+ let positionMargin = $t07501375114._2
1750+ let pon = $t07501375114._3
1751+ let positionLstUpdCPF = $t07501375114._4
1752+ let $t07511775218 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1753+ let positionNotional = $t07511775218._1
1754+ let unrealizedPnl = $t07511775218._2
1755+ let $t07522175393 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1756+ let remainMargin = $t07522175393._1
1757+ let badDebt = $t07522175393._2
1758+ let fundingPayment = $t07522175393._3
17591759 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
17601760 }
17611761 else throw("Strict value is not equal to itself.")
17731773
17741774 @Callable(i)
17751775 func view_getTerminalAmmPrice () = {
1776- let $t07572675807 = getTerminalAmmState()
1777- let terminalQuoteAssetReserve = $t07572675807._1
1778- let terminalBaseAssetReserve = $t07572675807._2
1776+ let $t07574075821 = getTerminalAmmState()
1777+ let terminalQuoteAssetReserve = $t07574075821._1
1778+ let terminalBaseAssetReserve = $t07574075821._2
17791779 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17801780 throw(toString(price))
17811781 }
17851785 @Callable(i)
17861786 func view_getFunding () = {
17871787 let underlyingPrice = getOracleTwapPrice()
1788- let $t07602676088 = getFunding()
1789- let shortPremiumFraction = $t07602676088._1
1790- let longPremiumFraction = $t07602676088._2
1788+ let $t07604076102 = getFunding()
1789+ let shortPremiumFraction = $t07604076102._1
1790+ let longPremiumFraction = $t07604076102._2
17911791 let longFunding = divd(longPremiumFraction, underlyingPrice)
17921792 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17931793 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
17971797
17981798 @Callable(i)
17991799 func view_getBorrowedByTrader (_trader) = {
1800- let $t07637876432 = getBorrowedByTrader(_trader)
1801- let borrowed = $t07637876432._1
1802- let assetId = $t07637876432._2
1800+ let $t07639276446 = getBorrowedByTrader(_trader)
1801+ let borrowed = $t07639276446._1
1802+ let assetId = $t07639276446._2
18031803 throw((s(borrowed) + assetId))
18041804 }
18051805
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_positionSize = "k_positionSize"
1313
1414 let k_positionMargin = "k_positionMargin"
1515
1616 let k_positionOpenNotional = "k_positionOpenNotional"
1717
1818 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
1919
2020 let k_positionClosedDate = "k_positionClosedDate"
2121
2222 let k_positionAsset = "k_positionAsset"
2323
2424 let k_initialized = "k_initialized"
2525
2626 let k_paused = "k_paused"
2727
2828 let k_fee = "k_fee"
2929
3030 let k_fundingPeriod = "k_fundingPeriod"
3131
3232 let k_initMarginRatio = "k_initMarginRatio"
3333
3434 let k_maintenanceMarginRatio = "k_mmr"
3535
3636 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
3737
3838 let k_partialLiquidationRatio = "k_partLiquidationRatio"
3939
4040 let k_spreadLimit = "k_spreadLimit"
4141
4242 let k_maxPriceImpact = "k_maxPriceImpact"
4343
4444 let k_maxPriceSpread = "k_maxPriceSpread"
4545
4646 let k_lastDataStr = "k_lastDataStr"
4747
4848 let k_lastMinuteId = "k_lastMinuteId"
4949
5050 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
5151
5252 let k_twapDataLastPrice = "k_twapDataLastPrice"
5353
5454 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
5555
5656 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
5757
5858 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
5959
6060 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
6161
6262 let k_longFundingRate = "k_longFundingRate"
6363
6464 let k_shortFundingRate = "k_shortFundingRate"
6565
6666 let k_quoteAssetReserve = "k_qtAstR"
6767
6868 let k_baseAssetReserve = "k_bsAstR"
6969
7070 let k_quoteAssetWeight = "k_qtAstW"
7171
7272 let k_baseAssetWeight = "k_bsAstW"
7373
7474 let k_totalPositionSize = "k_totalPositionSize"
7575
7676 let k_totalLongPositionSize = "k_totalLongPositionSize"
7777
7878 let k_totalShortPositionSize = "k_totalShortPositionSize"
7979
8080 let k_cumulativeNotional = "k_cumulativeNotional"
8181
8282 let k_openInterestNotional = "k_openInterestNotional"
8383
8484 let k_coordinatorAddress = "k_coordinatorAddress"
8585
8686 let k_vault_address = "k_vault_address"
8787
8888 let k_admin_address = "k_admin_address"
8989
9090 let k_admin_public_key = "k_admin_public_key"
9191
9292 let k_quote_asset = "k_quote_asset"
9393
9494 let k_quote_staking = "k_quote_staking"
9595
9696 let k_staking_address = "k_staking_address"
9797
9898 let k_miner_address = "k_miner_address"
9999
100100 let k_orders_address = "k_orders_address"
101101
102102 let k_referral_address = "k_referral_address"
103103
104104 let k_manager_address = "k_manager_address"
105105
106106 let k_collateral_address = "k_collateral_address"
107107
108108 let k_exchange_address = "k_exchange_address"
109109
110110 let k_nft_manager_address = "k_nft_manager_address"
111111
112112 let k_trader_market_asset_collateral = "k_trader_market_asset_collateral"
113113
114114 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
115115
116116
117117 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
118118
119119
120120 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
121121
122122
123123 func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
124124
125125
126126 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
127127
128128
129129 func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
130130
131131
132132 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
133133
134134
135135 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
136136
137137
138138 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
139139
140140
141141 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
142142
143143
144144 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
145145
146146
147147 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
148148
149149
150150 func collateralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_collateral_address)), "Collateral Manager not set")
151151
152152
153153 func swapAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_exchange_address), "No swap address")), "Invalid swap address")
154154
155155
156156 let k_whitelist_asset = "k_whitelist_asset"
157157
158158 func isWhitelistAsset (_assetId) = valueOrElse(getBoolean(collateralAddress(), toCompositeKey(k_whitelist_asset, _assetId)), false)
159159
160160
161161 let k_token_param = "k_token_param"
162162
163163 let k_token_type = "k_token_type"
164164
165165 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
166166
167167 let DIR_LONG = 1
168168
169169 let DIR_SHORT = 2
170170
171171 let TWAP_INTERVAL = 15
172172
173173 let ORACLE_INTERVAL = 15
174174
175175 let SECONDS = 1000
176176
177177 let DECIMAL_NUMBERS = 6
178178
179179 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
180180
181181 let ONE_DAY = (86400 * DECIMAL_UNIT)
182182
183183 let ALL_FEES = 100
184184
185185 let PNL_OPTION_SPOT = 1
186186
187187 let PNL_OPTION_ORACLE = 2
188188
189189 func s (_x) = (toString(_x) + ",")
190190
191191
192192 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
193193
194194
195195 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
196196
197197
198198 func sqrtd (_x) = sqrt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
199199
200200
201201 func powd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
202202
203203
204204 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
205205
206206
207207 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
208208
209209
210210 func bsqrtd (_x) = sqrtBigInt(_x, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
211211
212212
213213 func bpowd (_x,_y) = pow(_x, DECIMAL_NUMBERS, _y, DECIMAL_NUMBERS, DECIMAL_NUMBERS, HALFEVEN)
214214
215215
216216 func abs (_x) = if ((_x > 0))
217217 then _x
218218 else -(_x)
219219
220220
221221 func vmax (_x,_y) = if ((_x >= _y))
222222 then _x
223223 else _y
224224
225225
226226 func listToStr (_list) = {
227227 func _join (accumulator,val) = ((accumulator + val) + ",")
228228
229229 let newListStr = {
230230 let $l = _list
231231 let $s = size($l)
232232 let $acc0 = ""
233233 func $f0_1 ($a,$i) = if (($i >= $s))
234234 then $a
235235 else _join($a, $l[$i])
236236
237237 func $f0_2 ($a,$i) = if (($i >= $s))
238238 then $a
239239 else throw("List size exceeds 20")
240240
241241 $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)
242242 }
243243 let newListStrU = dropRight(newListStr, 1)
244244 let newListStrR = if ((take(newListStrU, 1) == ","))
245245 then drop(newListStrU, 1)
246246 else newListStrU
247247 newListStrR
248248 }
249249
250250
251251 func strToList (_str) = split(_str, ",")
252252
253253
254254 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
255255 then (removeByIndex(_list, 0) :+ _value)
256256 else (_list :+ _value)
257257
258258
259259 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
260260
261261
262262 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
263263
264264
265265 func strA (_address,_key) = {
266266 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
267267 val
268268 }
269269
270270
271271 func intA (_address,_key) = {
272272 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
273273 val
274274 }
275275
276276
277277 func cbalance () = int(k_balance)
278278
279279
280280 func fee () = int(k_fee)
281281
282282
283283 func initMarginRatio () = int(k_initMarginRatio)
284284
285285
286286 func qtAstR () = int(k_quoteAssetReserve)
287287
288288
289289 func bsAstR () = int(k_baseAssetReserve)
290290
291291
292292 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
293293
294294
295295 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
296296
297297
298298 func totalPositionSize () = int(k_totalPositionSize)
299299
300300
301301 func cumulativeNotional () = int(k_cumulativeNotional)
302302
303303
304304 func openInterestNotional () = int(k_openInterestNotional)
305305
306306
307307 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
308308
309309
310310 func fundingPeriodRaw () = int(k_fundingPeriod)
311311
312312
313313 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
314314
315315
316316 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
317317
318318
319319 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
320320
321321
322322 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
323323
324324
325325 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
326326
327327
328328 func spreadLimit () = int(k_spreadLimit)
329329
330330
331331 func maxPriceImpact () = int(k_maxPriceImpact)
332332
333333
334334 func maxPriceSpread () = int(k_maxPriceSpread)
335335
336336
337337 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
338338
339339
340340 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
341341
342342
343343 func totalShortPositionSize () = int(k_totalShortPositionSize)
344344
345345
346346 func totalLongPositionSize () = int(k_totalLongPositionSize)
347347
348348
349349 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
350350
351351
352352 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
353353 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
354354 if (if (_largerThanOrEqualTo)
355355 then (0 > remainingMarginRatio)
356356 else false)
357357 then throw("Invalid margin")
358358 else if (if (!(_largerThanOrEqualTo))
359359 then (remainingMarginRatio >= 0)
360360 else false)
361361 then throw("Invalid margin")
362362 else true
363363 }
364364
365365
366366 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
367367 then throw("Should not be called with _positionSize == 0")
368368 else if ((_positionSize > 0))
369369 then latestLongCumulativePremiumFraction()
370370 else latestShortCumulativePremiumFraction()
371371
372372
373373 func getPosition (_trader) = {
374374 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
375375 match positionSizeOpt {
376376 case positionSize: Int =>
377377 $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
378378 case _ =>
379379 $Tuple4(0, 0, 0, 0)
380380 }
381381 }
382382
383383
384384 func getPositionAsset (_trader) = {
385385 let positionAssetOpt = getString(this, toCompositeKey(k_positionAsset, _trader))
386386 match positionAssetOpt {
387387 case positionAsset: String =>
388388 positionAsset
389389 case _ =>
390390 toBase58String(quoteAsset())
391391 }
392392 }
393393
394394
395395 func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
396396 then throw("No open position")
397397 else true
398398
399399
400400 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
401401
402402
403403 func paused () = valueOrElse(getBoolean(this, k_paused), false)
404404
405405
406406 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
407407 then {
408408 let newBase = (bsAstR() - _baseAssetAmount)
409409 if ((0 >= newBase))
410410 then throw("Tx lead to base asset reserve <= 0, revert")
411411 else $Tuple4((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount), (cumulativeNotional() + _quoteAssetAmount))
412412 }
413413 else {
414414 let newQuote = (qtAstR() - _quoteAssetAmount)
415415 if ((0 >= newQuote))
416416 then throw("Tx lead to base quote reserve <= 0, revert")
417417 else $Tuple4(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount), (cumulativeNotional() - _quoteAssetAmount))
418418 }
419419
420420
421421 func calcInvariant (_qtAstR,_qtAstW,_bsAstR,_bsAstW) = muld(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
422422
423423
424424 func swapInput (_isAdd,_quoteAssetAmount) = {
425425 let _qtAstR = qtAstR()
426426 let _bsAstR = bsAstR()
427427 let _qtAstW = qtAstW()
428428 let _bsAstW = bsAstW()
429429 let k = calcInvariant(_qtAstR, _qtAstW, _bsAstR, _bsAstW)
430430 let quoteAssetReserveAfter = if (_isAdd)
431431 then (_qtAstR + _quoteAssetAmount)
432432 else (_qtAstR - _quoteAssetAmount)
433- let baseAssetReserveAfter = divd(k, quoteAssetReserveAfter)
433+ let baseAssetReserveAfter = divd(k, muld(quoteAssetReserveAfter, _qtAstW))
434434 let amountBaseAssetBoughtAbs = divd(abs((baseAssetReserveAfter - _bsAstR)), _qtAstW)
435435 let amountBaseAssetBought = if (_isAdd)
436436 then amountBaseAssetBoughtAbs
437437 else -(amountBaseAssetBoughtAbs)
438- let $t01631916512 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
439- let quoteAssetReserveAfter1 = $t01631916512._1
440- let baseAssetReserveAfter1 = $t01631916512._2
441- let totalPositionSizeAfter1 = $t01631916512._3
442- let cumulativeNotionalAfter1 = $t01631916512._4
438+ let $t01633316526 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
439+ let quoteAssetReserveAfter1 = $t01633316526._1
440+ let baseAssetReserveAfter1 = $t01633316526._2
441+ let totalPositionSizeAfter1 = $t01633316526._3
442+ let cumulativeNotionalAfter1 = $t01633316526._4
443443 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
444444 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
445445 let priceDiff = abs((priceBefore - marketPrice))
446446 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
447447 let maxPriceImpactValue = maxPriceImpact()
448448 if ((priceImpact > maxPriceImpactValue))
449449 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)))
450450 else $Tuple5(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1)
451451 }
452452
453453
454454 func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
455455 let fundingPayment = if ((_oldPositionSize != 0))
456456 then {
457457 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
458458 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
459459 }
460460 else 0
461461 let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
462- let $t01803118158 = if ((0 > signedMargin))
462+ let $t01804518172 = if ((0 > signedMargin))
463463 then $Tuple2(0, abs(signedMargin))
464464 else $Tuple2(abs(signedMargin), 0)
465- let remainMargin = $t01803118158._1
466- let badDebt = $t01803118158._2
465+ let remainMargin = $t01804518172._1
466+ let badDebt = $t01804518172._2
467467 $Tuple3(remainMargin, badDebt, fundingPayment)
468468 }
469469
470470
471471 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
472472 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
473473 if ((_baseAssetAmount == 0))
474474 then throw("Invalid base asset amount")
475475 else {
476476 let k = calcInvariant(_quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
477477 let baseAssetPoolAmountAfter = if (_isAdd)
478478 then (_baseAssetReserve + _baseAssetAmount)
479479 else (_baseAssetReserve - _baseAssetAmount)
480480 let quoteAssetAfter = divd(k, muld(baseAssetPoolAmountAfter, _baseAssetWeight))
481481 let quoteAssetSold = abs((quoteAssetAfter - muld(_quoteAssetReserve, _quoteAssetWeight)))
482482 let maxPriceImpactValue = maxPriceImpact()
483- let $t01932619519 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
484- let quoteAssetReserveAfter1 = $t01932619519._1
485- let baseAssetReserveAfter1 = $t01932619519._2
486- let totalPositionSizeAfter1 = $t01932619519._3
487- let cumulativeNotionalAfter1 = $t01932619519._4
483+ let $t01934019533 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
484+ let quoteAssetReserveAfter1 = $t01934019533._1
485+ let baseAssetReserveAfter1 = $t01934019533._2
486+ let totalPositionSizeAfter1 = $t01934019533._3
487+ let cumulativeNotionalAfter1 = $t01934019533._4
488488 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
489489 let priceDiff = abs((priceBefore - marketPrice))
490490 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
491491 if (if ((priceImpact > maxPriceImpactValue))
492492 then _checkMaxPriceImpact
493493 else false)
494494 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)))
495495 else $Tuple8(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1, (totalLongPositionSize() - (if (_isAdd)
496496 then abs(_baseAssetAmount)
497497 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
498498 then abs(_baseAssetAmount)
499499 else 0)), priceImpact)
500500 }
501501 }
502502
503503
504504 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
505505
506506
507507 func getOracleTwapPrice () = {
508508 let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
509509 let priceKey = getStringValue(this, k_ora_key)
510510 let blockKey = getStringValue(this, k_ora_block_key)
511511 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
512512 lastValue
513513 }
514514
515515
516516 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
517517 let oraclePrice = getOracleTwapPrice()
518518 let priceAfter = divd(_quoteAssetReserve, _baseAssetReserve)
519519 let averagePrice = divd((oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
520520 let absPriceDiff = divd(abs((oraclePrice - priceAfter)), averagePrice)
521521 if ((absPriceDiff > maxPriceSpread()))
522522 then throw(((("Price spread " + toString(absPriceDiff)) + " > max price spread ") + toString(maxPriceSpread())))
523523 else true
524524 }
525525
526526
527527 func getSpotPrice () = {
528528 let _quoteAssetReserve = qtAstR()
529529 let _baseAssetReserve = bsAstR()
530530 let _qtAstW = qtAstW()
531531 let _bsAstW = bsAstW()
532532 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
533533 }
534534
535535
536536 func isOverFluctuationLimit () = {
537537 let oraclePrice = getOracleTwapPrice()
538538 let currentPrice = getSpotPrice()
539539 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
540540 }
541541
542542
543543 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
544544 let positionSizeAbs = abs(_positionSize)
545545 let isShort = (0 > _positionSize)
546546 let positionNotional = if ((_option == PNL_OPTION_SPOT))
547547 then {
548- let $t02289423114 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
549- let outPositionNotional = $t02289423114._1
550- let x1 = $t02289423114._2
551- let x2 = $t02289423114._3
552- let x3 = $t02289423114._4
548+ let $t02290823128 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
549+ let outPositionNotional = $t02290823128._1
550+ let x1 = $t02290823128._2
551+ let x2 = $t02290823128._3
552+ let x3 = $t02290823128._4
553553 outPositionNotional
554554 }
555555 else muld(positionSizeAbs, getOracleTwapPrice())
556556 positionNotional
557557 }
558558
559559
560560 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
561561 then throw("Invalid position size")
562562 else {
563563 let isShort = (0 > _positionSize)
564564 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
565565 let unrealizedPnl = if (isShort)
566566 then (_positionOpenNotional - positionNotional)
567567 else (positionNotional - _positionOpenNotional)
568568 $Tuple2(positionNotional, unrealizedPnl)
569569 }
570570
571571
572572 func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
573- let $t02453924667 = getPosition(_trader)
574- let positionSize = $t02453924667._1
575- let positionMargin = $t02453924667._2
576- let positionOpenNotional = $t02453924667._3
577- let positionLstUpdCPF = $t02453924667._4
573+ let $t02455324681 = getPosition(_trader)
574+ let positionSize = $t02455324681._1
575+ let positionMargin = $t02455324681._2
576+ let positionOpenNotional = $t02455324681._3
577+ let positionLstUpdCPF = $t02455324681._4
578578 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
579579 }
580580
581581
582582 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
583583
584584
585585 func getMarginRatioByOption (_trader,_option) = {
586- let $t02518025291 = getPosition(_trader)
587- let positionSize = $t02518025291._1
588- let positionMargin = $t02518025291._2
589- let pon = $t02518025291._3
590- let positionLstUpdCPF = $t02518025291._4
591- let $t02529725390 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
592- let positionNotional = $t02529725390._1
593- let unrealizedPnl = $t02529725390._2
594- let $t02539525561 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
595- let remainMargin = $t02539525561._1
596- let badDebt = $t02539525561._2
586+ let $t02519425305 = getPosition(_trader)
587+ let positionSize = $t02519425305._1
588+ let positionMargin = $t02519425305._2
589+ let pon = $t02519425305._3
590+ let positionLstUpdCPF = $t02519425305._4
591+ let $t02531125404 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
592+ let positionNotional = $t02531125404._1
593+ let unrealizedPnl = $t02531125404._2
594+ let $t02540925575 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
595+ let remainMargin = $t02540925575._1
596+ let badDebt = $t02540925575._2
597597 calcMarginRatio(remainMargin, badDebt, positionNotional)
598598 }
599599
600600
601601 func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
602602
603603
604604 func getPartialLiquidationAmount (_trader,_positionSize) = {
605605 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
606606 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
607607 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
608608 let maxExchangedQuoteAssetAmount = swapResult._1
609609 let priceImpact = swapResult._8
610610 if ((maxPriceImpact() > priceImpact))
611611 then maxExchangedQuoteAssetAmount
612612 else {
613613 let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
614614 let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
615615 exchangedQuoteAssetAmount
616616 }
617617 }
618618
619619
620620 func internalClosePosition (_trader,_checkMaxPriceImpact) = {
621- let $t02679426922 = getPosition(_trader)
622- let positionSize = $t02679426922._1
623- let positionMargin = $t02679426922._2
624- let positionOpenNotional = $t02679426922._3
625- let positionLstUpdCPF = $t02679426922._4
621+ let $t02680826936 = getPosition(_trader)
622+ let positionSize = $t02680826936._1
623+ let positionMargin = $t02680826936._2
624+ let positionOpenNotional = $t02680826936._3
625+ let positionLstUpdCPF = $t02680826936._4
626626 let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
627- let $t02701727185 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
628- let remainMargin = $t02701727185._1
629- let badDebt = $t02701727185._2
627+ let $t02703127199 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
628+ let remainMargin = $t02703127199._1
629+ let badDebt = $t02703127199._2
630630 let exchangedPositionSize = -(positionSize)
631631 let realizedPnl = unrealizedPnl
632632 let marginToVault = -(remainMargin)
633- let $t02731227617 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
634- let exchangedQuoteAssetAmount = $t02731227617._1
635- let quoteAssetReserveAfter = $t02731227617._2
636- let baseAssetReserveAfter = $t02731227617._3
637- let totalPositionSizeAfter = $t02731227617._4
638- let cumulativeNotionalAfter = $t02731227617._5
639- let totalLongAfter = $t02731227617._6
640- let totalShortAfter = $t02731227617._7
633+ let $t02732627631 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
634+ let exchangedQuoteAssetAmount = $t02732627631._1
635+ let quoteAssetReserveAfter = $t02732627631._2
636+ let baseAssetReserveAfter = $t02732627631._3
637+ let totalPositionSizeAfter = $t02732627631._4
638+ let cumulativeNotionalAfter = $t02732627631._5
639+ let totalLongAfter = $t02732627631._6
640+ let totalShortAfter = $t02732627631._7
641641 let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
642642 $Tuple12(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter)
643643 }
644644
645645
646646 func getTwapSpotPrice () = {
647647 let minuteId = ((lastBlock.timestamp / 1000) / 60)
648648 let startMinuteId = (minuteId - TWAP_INTERVAL)
649649 let listStr = valueOrElse(getString(this, k_lastDataStr), "")
650650 let list = split(listStr, ",")
651651 func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
652652 then (accumulator :+ parseIntValue(next))
653653 else accumulator
654654
655655 let listF = {
656656 let $l = list
657657 let $s = size($l)
658658 let $acc0 = nil
659659 func $f0_1 ($a,$i) = if (($i >= $s))
660660 then $a
661661 else filterFn($a, $l[$i])
662662
663663 func $f0_2 ($a,$i) = if (($i >= $s))
664664 then $a
665665 else throw("List size exceeds 20")
666666
667667 $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)
668668 }
669669 let maxIndex = if ((size(listF) > 0))
670670 then max(listF)
671671 else parseIntValue(list[0])
672672 let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
673673 let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
674674 let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
675675 let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
676676 let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
677677 let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
678678 let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
679679 ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
680680 }
681681
682682
683683 func getTerminalAmmState () = {
684684 let _positionSize = totalPositionSize()
685685 if ((_positionSize == 0))
686686 then $Tuple2(qtAstR(), bsAstR())
687687 else {
688688 let direction = (_positionSize > 0)
689- let $t02960429783 = swapOutput(direction, abs(_positionSize), false)
690- let currentNetMarketValue = $t02960429783._1
691- let terminalQuoteAssetReserve = $t02960429783._2
692- let terminalBaseAssetReserve = $t02960429783._3
689+ let $t02961829797 = swapOutput(direction, abs(_positionSize), false)
690+ let currentNetMarketValue = $t02961829797._1
691+ let terminalQuoteAssetReserve = $t02961829797._2
692+ let terminalBaseAssetReserve = $t02961829797._3
693693 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
694694 }
695695 }
696696
697697
698698 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
699699 let b = toBigInt(baseAssetReserve)
700700 let sz = toBigInt(totalPositionSize)
701701 let q = toBigInt(quoteAssetReserve)
702702 let p = toBigInt(targetPrice)
703703 let bs2 = bpowd((b + sz), toBigInt((2 * DECIMAL_UNIT)))
704704 let qbs2 = bmuld(q, bs2)
705705 let ps4 = (toBigInt(4) * bmuld(p, sz))
706706 let sqr = bsqrtd(bmuld(qbs2, (q - ps4)))
707707 let bq = bmuld(b, q)
708708 let qs = bmuld(q, sz)
709709 let top = ((-(sqr) + bq) + qs)
710710 let bot = (toBigInt(2) * bmuld(q, sz))
711711 let result = bdivd(top, bot)
712712 toInt(result)
713713 }
714714
715715
716716 func getSyncTerminalPrice (_terminalPrice) = {
717717 let _positionSize = totalPositionSize()
718718 if ((_positionSize == 0))
719719 then {
720720 let _qtAstR = qtAstR()
721721 let _bsAstR = bsAstR()
722722 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
723723 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
724724 }
725725 else {
726726 let direction = (_positionSize > 0)
727727 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
728728 let _qtAstR = qtAstR()
729729 let _bsAstR = bsAstR()
730730 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
731731 let newBsAstW = DECIMAL_UNIT
732732 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
733733 $Tuple3(newQtAstW, newBsAstW, marginToVault)
734734 }
735735 }
736736
737737
738738 func getFunding () = {
739739 let underlyingPrice = getOracleTwapPrice()
740740 let spotTwapPrice = getTwapSpotPrice()
741741 let premium = (spotTwapPrice - underlyingPrice)
742742 if (if ((totalShortPositionSize() == 0))
743743 then true
744744 else (totalLongPositionSize() == 0))
745745 then $Tuple2(0, 0)
746746 else if ((0 > premium))
747747 then {
748748 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
749749 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
750750 $Tuple2(shortPremiumFraction, longPremiumFraction)
751751 }
752752 else {
753753 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
754754 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
755755 $Tuple2(shortPremiumFraction, longPremiumFraction)
756756 }
757757 }
758758
759759
760760 func getAdjustedFee (i,_baseFeeDiscount) = {
761761 let baseFeeRaw = fee()
762762 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
763- let $t03287633484 = if ((size(i.payments) > 1))
763+ let $t03289033498 = if ((size(i.payments) > 1))
764764 then {
765765 let artifactId = toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid attached artifact"))
766766 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, artifactId))
767767 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
768768 then {
769769 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, artifactId))
770770 let adjustedFee = muld(baseFee, reduction)
771771 $Tuple2(adjustedFee, true)
772772 }
773773 else throw("Invalid attached artifact")
774774 }
775775 else $Tuple2(baseFee, false)
776- let adjustedFee = $t03287633484._1
777- let burnArtifact = $t03287633484._2
776+ let adjustedFee = $t03289033498._1
777+ let burnArtifact = $t03289033498._2
778778 $Tuple2(adjustedFee, burnArtifact)
779779 }
780780
781781
782782 func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = [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)]
783783
784784
785785 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)]
786786
787787
788788 func updatePositionAsset (_address,_assetId) = [StringEntry(toCompositeKey(k_positionAsset, _address), _assetId)]
789789
790790
791791 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)]
792792
793793
794794 func appendTwap (price) = {
795795 let minuteId = ((lastBlock.timestamp / 1000) / 60)
796796 let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
797797 if ((previousMinuteId > minuteId))
798798 then throw("TWAP out-of-order")
799799 else {
800800 let lastMinuteId = if ((previousMinuteId == 0))
801801 then minuteId
802802 else previousMinuteId
803803 if ((minuteId > previousMinuteId))
804804 then {
805805 let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
806806 let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), price)
807807 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
808808 let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
809809 [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))]
810810 }
811811 else {
812812 let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
813813 let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
814814 let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), price)
815815 let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
816816 [IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price)]
817817 }
818818 }
819819 }
820820
821821
822822 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
823823
824824
825825 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
826826
827827
828828 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_cumulativeNotionalAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize) = {
829829 let _qtAstW = qtAstW()
830830 let _bsAstW = bsAstW()
831831 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
832832 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
833833 else ((updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_cumulativeNotional, _cumulativeNotionalAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize)]) ++ appendTwap(divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))))
834834 }
835835
836836
837837 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)), IntegerEntry(toCompositeKey(k_positionClosedDate, _address), lastBlock.timestamp)]
838838
839839
840840 func withdraw (_address,_amount) = {
841841 let balance = assetBalance(this, quoteAsset())
842842 if ((_amount > balance))
843843 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
844844 else [ScriptTransfer(_address, _amount, quoteAsset())]
845845 }
846846
847847
848848 func updateBalance (i) = if ((0 > i))
849849 then throw("Balance")
850850 else [IntegerEntry(k_balance, i)]
851851
852852
853853 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
854854
855855
856856 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
857857 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
858858 else nil
859859
860860
861861 func isSameAssetOrNoPosition (_trader,_assetId) = {
862862 let oldPositionSize = getPosition(_trader)._1
863863 if ((oldPositionSize == 0))
864864 then true
865865 else (getPositionAsset(_trader) == _assetId)
866866 }
867867
868868
869869 func isSameAsset (_trader,_assetId) = (getPositionAsset(_trader) == _assetId)
870870
871871
872872 func getBorrowedByTraderInMarketKey (_amm,_assetId,_trader) = ((((((k_trader_market_asset_collateral + "_") + _amm) + "_") + _assetId) + "_") + _trader)
873873
874874
875875 func getBorrowedByTrader (_trader) = {
876876 let positionAsset = getPositionAsset(_trader)
877877 if ((positionAsset == toBase58String(quoteAsset())))
878878 then $Tuple2(0, positionAsset)
879879 else {
880880 let key = getBorrowedByTraderInMarketKey(toString(this), positionAsset, _trader)
881881 let borrow = valueOrElse(getInteger(collateralAddress(), key), 0)
882882 $Tuple2(borrow, positionAsset)
883883 }
884884 }
885885
886886
887887 @Callable(i)
888888 func pause () = if ((i.caller != adminAddress()))
889889 then throw("Invalid togglePause params")
890890 else [BooleanEntry(k_paused, true)]
891891
892892
893893
894894 @Callable(i)
895895 func unpause () = if ((i.caller != adminAddress()))
896896 then throw("Invalid togglePause params")
897897 else [BooleanEntry(k_paused, false)]
898898
899899
900900
901901 @Callable(i)
902902 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
903903 then true
904904 else (0 >= _quoteAssetAmount))
905905 then throw("Invalid addLiquidity params")
906906 else {
907907 let _qtAstR = qtAstR()
908908 let _bsAstR = bsAstR()
909909 let _qtAstW = qtAstW()
910910 let _bsAstW = bsAstW()
911911 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
912912 let baseAssetAmountToAdd = divd(_quoteAssetAmount, price)
913913 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
914914 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
915915 updateAmmReserves(qtAstRAfter, bsAstRAfter)
916916 }
917917
918918
919919
920920 @Callable(i)
921921 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
922922 then true
923923 else (0 >= _quoteAssetAmount))
924924 then throw("Invalid removeLiquidity params")
925925 else {
926926 let _qtAstR = qtAstR()
927927 let _bsAstR = bsAstR()
928928 let _qtAstW = qtAstW()
929929 let _bsAstW = bsAstW()
930930 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
931931 let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
932932 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
933933 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
934934 updateAmmReserves(qtAstRAfter, bsAstRAfter)
935935 }
936936
937937
938938
939939 @Callable(i)
940940 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = if ((i.caller != adminAddress()))
941941 then throw("Invalid changeSettings params")
942942 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread)
943943
944944
945945
946946 @Callable(i)
947947 func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_oracle,_oracleKey,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
948948 then true
949949 else (0 >= _bsAstR))
950950 then true
951951 else (0 >= _fundingPeriod))
952952 then true
953953 else (0 >= _initMarginRatio))
954954 then true
955955 else (0 >= _mmr))
956956 then true
957957 else (0 >= _liquidationFeeRatio))
958958 then true
959959 else (0 >= _fee))
960960 then true
961961 else (0 >= _spreadLimit))
962962 then true
963963 else (0 >= _maxPriceImpact))
964964 then true
965965 else (0 >= _partialLiquidationRatio))
966966 then true
967967 else (0 >= _maxPriceSpread))
968968 then true
969969 else initialized())
970970 then throw("Invalid initialize parameters")
971971 else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread)) ++ 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_coordinatorAddress, _coordinator)])
972972
973973
974974
975975 @Callable(i)
976976 func setInitMarginRatio (_initMarginRatio) = if (if ((0 >= _initMarginRatio))
977977 then true
978978 else !(initialized()))
979979 then throw("Invalid setInitMarginRatio parameters")
980980 else updateSettings(_initMarginRatio, maintenanceMarginRatio(), liquidationFeeRatio(), fundingPeriodRaw(), fee(), spreadLimit(), maxPriceImpact(), partialLiquidationRatio(), maxPriceSpread())
981981
982982
983983
984984 @Callable(i)
985985 func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = {
986986 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
987987 if ((sync == sync))
988988 then if (if (if (if (if ((0 >= _amount))
989989 then true
990990 else !(initialized()))
991991 then true
992992 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
993993 then true
994994 else !(requireOpenPosition(toString(i.caller))))
995995 then true
996996 else paused())
997997 then throw("Invalid decreasePosition parameters")
998998 else {
999- let $t04546445616 = getPosition(toString(i.caller))
1000- let oldPositionSize = $t04546445616._1
1001- let oldPositionMargin = $t04546445616._2
1002- let oldPositionOpenNotional = $t04546445616._3
1003- let oldPositionLstUpdCPF = $t04546445616._4
999+ let $t04547845630 = getPosition(toString(i.caller))
1000+ let oldPositionSize = $t04547845630._1
1001+ let oldPositionMargin = $t04547845630._2
1002+ let oldPositionOpenNotional = $t04547845630._3
1003+ let oldPositionLstUpdCPF = $t04547845630._4
10041004 let _direction = if ((oldPositionSize > 0))
10051005 then DIR_SHORT
10061006 else DIR_LONG
10071007 let isAdd = (_direction == DIR_LONG)
10081008 let openNotional = muld(_amount, _leverage)
1009- let $t04578945905 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1010- let oldPositionNotional = $t04578945905._1
1011- let unrealizedPnl = $t04578945905._2
1012- let $t04591148460 = if ((oldPositionNotional > openNotional))
1009+ let $t04580345919 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1010+ let oldPositionNotional = $t04580345919._1
1011+ let unrealizedPnl = $t04580345919._2
1012+ let $t04592548474 = if ((oldPositionNotional > openNotional))
10131013 then {
1014- let $t04628846507 = swapInput(isAdd, openNotional)
1015- let exchangedPositionSize = $t04628846507._1
1016- let quoteAssetReserveAfter = $t04628846507._2
1017- let baseAssetReserveAfter = $t04628846507._3
1018- let totalPositionSizeAfter = $t04628846507._4
1019- let cumulativeNotionalAfter = $t04628846507._5
1014+ let $t04630246521 = swapInput(isAdd, openNotional)
1015+ let exchangedPositionSize = $t04630246521._1
1016+ let quoteAssetReserveAfter = $t04630246521._2
1017+ let baseAssetReserveAfter = $t04630246521._3
1018+ let totalPositionSizeAfter = $t04630246521._4
1019+ let cumulativeNotionalAfter = $t04630246521._5
10201020 let exchangedPositionSizeAbs = abs(exchangedPositionSize)
10211021 if (if ((_minBaseAssetAmount != 0))
10221022 then (_minBaseAssetAmount > exchangedPositionSizeAbs)
10231023 else false)
10241024 then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
10251025 else {
10261026 let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
1027- let $t04694447189 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1028- let remainMargin = $t04694447189._1
1029- let badDebt = $t04694447189._2
1030- let fundingPayment = $t04694447189._3
1027+ let $t04695847203 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1028+ let remainMargin = $t04695847203._1
1029+ let badDebt = $t04695847203._2
1030+ let fundingPayment = $t04695847203._3
10311031 let exchangedQuoteAssetAmount = openNotional
10321032 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
10331033 let remainOpenNotional = if ((oldPositionSize > 0))
10341034 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
10351035 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
10361036 let newPositionSize = (oldPositionSize + exchangedPositionSize)
10371037 $Tuple11(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
10381038 then abs(exchangedPositionSize)
10391039 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
10401040 then abs(exchangedPositionSize)
10411041 else 0)))
10421042 }
10431043 }
10441044 else throw("Close position first")
1045- let newPositionSize = $t04591148460._1
1046- let newPositionRemainMargin = $t04591148460._2
1047- let newPositionOpenNotional = $t04591148460._3
1048- let newPositionLatestCPF = $t04591148460._4
1049- let baseAssetReserveAfter = $t04591148460._5
1050- let quoteAssetReserveAfter = $t04591148460._6
1051- let totalPositionSizeAfter = $t04591148460._7
1052- let cumulativeNotionalAfter = $t04591148460._8
1053- let openInterestNotionalAfter = $t04591148460._9
1054- let totalLongAfter = $t04591148460._10
1055- let totalShortAfter = $t04591148460._11
1045+ let newPositionSize = $t04592548474._1
1046+ let newPositionRemainMargin = $t04592548474._2
1047+ let newPositionOpenNotional = $t04592548474._3
1048+ let newPositionLatestCPF = $t04592548474._4
1049+ let baseAssetReserveAfter = $t04592548474._5
1050+ let quoteAssetReserveAfter = $t04592548474._6
1051+ let totalPositionSizeAfter = $t04592548474._7
1052+ let cumulativeNotionalAfter = $t04592548474._8
1053+ let openInterestNotionalAfter = $t04592548474._9
1054+ let totalLongAfter = $t04592548474._10
1055+ let totalShortAfter = $t04592548474._11
10561056 let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
10571057 if ((notifyNotional == notifyNotional))
10581058 then (updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter))
10591059 else throw("Strict value is not equal to itself.")
10601060 }
10611061 else throw("Strict value is not equal to itself.")
10621062 }
10631063
10641064
10651065
10661066 @Callable(i)
10671067 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
10681068 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
10691069 if ((sync == sync))
10701070 then {
10711071 let _trader = toString(i.caller)
10721072 let _rawAmount = i.payments[0].amount
10731073 let _assetId = i.payments[0].assetId
10741074 let _assetIdStr = toBase58String(value(_assetId))
10751075 let isQuoteAsset = (_assetId == quoteAsset())
10761076 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
10771077 if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
10781078 then (_direction != DIR_SHORT)
10791079 else false)
10801080 then true
10811081 else (0 >= _rawAmount))
10821082 then true
10831083 else !(initialized()))
10841084 then true
10851085 else if (!(isQuoteAsset))
10861086 then !(isCollateralAsset)
10871087 else false)
10881088 then true
10891089 else !(isSameAssetOrNoPosition(_trader, _assetIdStr)))
10901090 then true
10911091 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
10921092 then true
10931093 else paused())
10941094 then throw("Invalid increasePosition parameters")
10951095 else {
10961096 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
10971097 if ((doGetFeeDiscount == doGetFeeDiscount))
10981098 then {
10991099 let feeDiscount = match doGetFeeDiscount {
11001100 case x: Int =>
11011101 x
11021102 case _ =>
11031103 throw("Invalid computeFeeDiscount result")
11041104 }
1105- let $t05012350187 = getAdjustedFee(i, feeDiscount)
1106- let adjustedFee = $t05012350187._1
1107- let burnArtifact = $t05012350187._2
1105+ let $t05013750201 = getAdjustedFee(i, feeDiscount)
1106+ let adjustedFee = $t05013750201._1
1107+ let burnArtifact = $t05013750201._2
11081108 let rawFeeAmount = muld(_rawAmount, adjustedFee)
11091109 let _amount = (_rawAmount - rawFeeAmount)
11101110 let distributeFeeAmount = if (isCollateralAsset)
11111111 then {
11121112 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
11131113 if ((doBorrow == doBorrow))
11141114 then {
11151115 let balanceBefore = assetBalance(this, quoteAsset())
11161116 if ((balanceBefore == balanceBefore))
11171117 then {
11181118 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
11191119 if ((doSwap == doSwap))
11201120 then {
11211121 let balanceAfter = assetBalance(this, quoteAsset())
11221122 if ((balanceAfter == balanceAfter))
11231123 then {
11241124 let exchangedAmount = (balanceAfter - balanceBefore)
11251125 if ((exchangedAmount == exchangedAmount))
11261126 then exchangedAmount
11271127 else throw("Strict value is not equal to itself.")
11281128 }
11291129 else throw("Strict value is not equal to itself.")
11301130 }
11311131 else throw("Strict value is not equal to itself.")
11321132 }
11331133 else throw("Strict value is not equal to itself.")
11341134 }
11351135 else throw("Strict value is not equal to itself.")
11361136 }
11371137 else rawFeeAmount
11381138 if ((distributeFeeAmount == distributeFeeAmount))
11391139 then {
11401140 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
11411141 if ((referrerFeeAny == referrerFeeAny))
11421142 then {
11431143 let referrerFee = match referrerFeeAny {
11441144 case x: Int =>
11451145 x
11461146 case _ =>
11471147 throw("Invalid referrerFee")
11481148 }
11491149 let feeAmount = (distributeFeeAmount - referrerFee)
1150- let $t05150351643 = getPosition(_trader)
1151- let oldPositionSize = $t05150351643._1
1152- let oldPositionMargin = $t05150351643._2
1153- let oldPositionOpenNotional = $t05150351643._3
1154- let oldPositionLstUpdCPF = $t05150351643._4
1150+ let $t05151751657 = getPosition(_trader)
1151+ let oldPositionSize = $t05151751657._1
1152+ let oldPositionMargin = $t05151751657._2
1153+ let oldPositionOpenNotional = $t05151751657._3
1154+ let oldPositionLstUpdCPF = $t05151751657._4
11551155 let isNewPosition = (oldPositionSize == 0)
11561156 let isSameDirection = if ((oldPositionSize > 0))
11571157 then (_direction == DIR_LONG)
11581158 else (_direction == DIR_SHORT)
11591159 let expandExisting = if (!(isNewPosition))
11601160 then isSameDirection
11611161 else false
11621162 let isAdd = (_direction == DIR_LONG)
1163- let $t05193254517 = if (if (isNewPosition)
1163+ let $t05194654531 = if (if (isNewPosition)
11641164 then true
11651165 else expandExisting)
11661166 then {
11671167 let openNotional = muld(_amount, _leverage)
1168- let $t05235652562 = swapInput(isAdd, openNotional)
1169- let amountBaseAssetBought = $t05235652562._1
1170- let quoteAssetReserveAfter = $t05235652562._2
1171- let baseAssetReserveAfter = $t05235652562._3
1172- let totalPositionSizeAfter = $t05235652562._4
1173- let cumulativeNotionalAfter = $t05235652562._5
1168+ let $t05237052576 = swapInput(isAdd, openNotional)
1169+ let amountBaseAssetBought = $t05237052576._1
1170+ let quoteAssetReserveAfter = $t05237052576._2
1171+ let baseAssetReserveAfter = $t05237052576._3
1172+ let totalPositionSizeAfter = $t05237052576._4
1173+ let cumulativeNotionalAfter = $t05237052576._5
11741174 if (if ((_minBaseAssetAmount != 0))
11751175 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
11761176 else false)
11771177 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
11781178 else {
11791179 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
11801180 let increaseMarginRequirement = divd(openNotional, _leverage)
1181- let $t05294353182 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1182- let remainMargin = $t05294353182._1
1183- let x1 = $t05294353182._2
1184- let x2 = $t05294353182._3
1181+ let $t05295753196 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
1182+ let remainMargin = $t05295753196._1
1183+ let x1 = $t05295753196._2
1184+ let x2 = $t05295753196._3
11851185 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
11861186 then throw("Over max spread limit")
11871187 else $Tuple11(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
11881188 then abs(amountBaseAssetBought)
11891189 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
11901190 then abs(amountBaseAssetBought)
11911191 else 0)))
11921192 }
11931193 }
11941194 else {
11951195 let openNotional = muld(_amount, _leverage)
1196- let $t05421054326 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1197- let oldPositionNotional = $t05421054326._1
1198- let unrealizedPnl = $t05421054326._2
1196+ let $t05422454340 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
1197+ let oldPositionNotional = $t05422454340._1
1198+ let unrealizedPnl = $t05422454340._2
11991199 if ((oldPositionNotional > openNotional))
12001200 then throw("Use decreasePosition to decrease position size")
12011201 else throw("Close position first")
12021202 }
1203- let newPositionSize = $t05193254517._1
1204- let newPositionRemainMargin = $t05193254517._2
1205- let newPositionOpenNotional = $t05193254517._3
1206- let newPositionLatestCPF = $t05193254517._4
1207- let baseAssetReserveAfter = $t05193254517._5
1208- let quoteAssetReserveAfter = $t05193254517._6
1209- let totalPositionSizeAfter = $t05193254517._7
1210- let cumulativeNotionalAfter = $t05193254517._8
1211- let openInterestNotionalAfter = $t05193254517._9
1212- let totalLongAfter = $t05193254517._10
1213- let totalShortAfter = $t05193254517._11
1203+ let newPositionSize = $t05194654531._1
1204+ let newPositionRemainMargin = $t05194654531._2
1205+ let newPositionOpenNotional = $t05194654531._3
1206+ let newPositionLatestCPF = $t05194654531._4
1207+ let baseAssetReserveAfter = $t05194654531._5
1208+ let quoteAssetReserveAfter = $t05194654531._6
1209+ let totalPositionSizeAfter = $t05194654531._7
1210+ let cumulativeNotionalAfter = $t05194654531._8
1211+ let openInterestNotionalAfter = $t05194654531._9
1212+ let totalLongAfter = $t05194654531._10
1213+ let totalShortAfter = $t05194654531._11
12141214 let feeToStakers = (feeAmount / 2)
12151215 let feeToInsurance = (feeAmount - feeToStakers)
12161216 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
12171217 if ((stake == stake))
12181218 then {
12191219 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
12201220 if ((depositInsurance == depositInsurance))
12211221 then {
12221222 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
12231223 if ((notifyFee == notifyFee))
12241224 then {
12251225 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
12261226 if ((notifyNotional == notifyNotional))
12271227 then (((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updatePositionAsset(_trader, _assetIdStr)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
12281228 else throw("Strict value is not equal to itself.")
12291229 }
12301230 else throw("Strict value is not equal to itself.")
12311231 }
12321232 else throw("Strict value is not equal to itself.")
12331233 }
12341234 else throw("Strict value is not equal to itself.")
12351235 }
12361236 else throw("Strict value is not equal to itself.")
12371237 }
12381238 else throw("Strict value is not equal to itself.")
12391239 }
12401240 else throw("Strict value is not equal to itself.")
12411241 }
12421242 }
12431243 else throw("Strict value is not equal to itself.")
12441244 }
12451245
12461246
12471247
12481248 @Callable(i)
12491249 func addMargin () = {
12501250 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12511251 if ((sync == sync))
12521252 then {
12531253 let _trader = toString(i.caller)
12541254 let _rawAmount = i.payments[0].amount
12551255 let _assetId = i.payments[0].assetId
12561256 let _assetIdStr = toBase58String(value(_assetId))
12571257 let isQuoteAsset = (_assetId == quoteAsset())
12581258 let isCollateralAsset = isWhitelistAsset(_assetIdStr)
12591259 if (if (if (if (if (if (!(isQuoteAsset))
12601260 then !(isCollateralAsset)
12611261 else false)
12621262 then true
12631263 else !(requireOpenPosition(toString(i.caller))))
12641264 then true
12651265 else !(isSameAsset(_trader, _assetIdStr)))
12661266 then true
12671267 else !(initialized()))
12681268 then true
12691269 else paused())
12701270 then throw("Invalid addMargin parameters")
12711271 else {
12721272 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
12731273 if ((doGetFeeDiscount == doGetFeeDiscount))
12741274 then {
12751275 let feeDiscount = match doGetFeeDiscount {
12761276 case x: Int =>
12771277 x
12781278 case _ =>
12791279 throw("Invalid computeFeeDiscount result")
12801280 }
1281- let $t05659456658 = getAdjustedFee(i, feeDiscount)
1282- let adjustedFee = $t05659456658._1
1283- let burnArtifact = $t05659456658._2
1281+ let $t05660856672 = getAdjustedFee(i, feeDiscount)
1282+ let adjustedFee = $t05660856672._1
1283+ let burnArtifact = $t05660856672._2
12841284 let rawFeeAmount = muld(_rawAmount, adjustedFee)
12851285 let _amount = (_rawAmount - rawFeeAmount)
12861286 let distributeFeeAmount = if (isCollateralAsset)
12871287 then {
12881288 let doBorrow = invoke(collateralAddress(), "borrow", [_trader], [AttachedPayment(_assetId, _amount)])
12891289 if ((doBorrow == doBorrow))
12901290 then {
12911291 let balanceBefore = assetBalance(this, quoteAsset())
12921292 if ((balanceBefore == balanceBefore))
12931293 then {
12941294 let doSwap = invoke(swapAddress(), "swap", [toBase58String(quoteAsset()), 0], [AttachedPayment(_assetId, rawFeeAmount)])
12951295 if ((doSwap == doSwap))
12961296 then {
12971297 let balanceAfter = assetBalance(this, quoteAsset())
12981298 if ((balanceAfter == balanceAfter))
12991299 then {
13001300 let exchangedAmount = (balanceAfter - balanceBefore)
13011301 if ((exchangedAmount == exchangedAmount))
13021302 then exchangedAmount
13031303 else throw("Strict value is not equal to itself.")
13041304 }
13051305 else throw("Strict value is not equal to itself.")
13061306 }
13071307 else throw("Strict value is not equal to itself.")
13081308 }
13091309 else throw("Strict value is not equal to itself.")
13101310 }
13111311 else throw("Strict value is not equal to itself.")
13121312 }
13131313 else rawFeeAmount
13141314 if ((distributeFeeAmount == distributeFeeAmount))
13151315 then {
13161316 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
13171317 if ((referrerFeeAny == referrerFeeAny))
13181318 then {
13191319 let referrerFee = match referrerFeeAny {
13201320 case x: Int =>
13211321 x
13221322 case _ =>
13231323 throw("Invalid referrerFee")
13241324 }
13251325 let feeAmount = (distributeFeeAmount - referrerFee)
1326- let $t05795758097 = getPosition(_trader)
1327- let oldPositionSize = $t05795758097._1
1328- let oldPositionMargin = $t05795758097._2
1329- let oldPositionOpenNotional = $t05795758097._3
1330- let oldPositionLstUpdCPF = $t05795758097._4
1326+ let $t05797158111 = getPosition(_trader)
1327+ let oldPositionSize = $t05797158111._1
1328+ let oldPositionMargin = $t05797158111._2
1329+ let oldPositionOpenNotional = $t05797158111._3
1330+ let oldPositionLstUpdCPF = $t05797158111._4
13311331 let feeToStakers = (feeAmount / 2)
13321332 let feeToInsurance = (feeAmount - feeToStakers)
13331333 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13341334 if ((stake == stake))
13351335 then {
13361336 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
13371337 if ((depositInsurance == depositInsurance))
13381338 then {
13391339 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13401340 if ((notifyFee == notifyFee))
13411341 then (((updatePosition(_trader, oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount))) ++ doBurnArtifact(burnArtifact, i))
13421342 else throw("Strict value is not equal to itself.")
13431343 }
13441344 else throw("Strict value is not equal to itself.")
13451345 }
13461346 else throw("Strict value is not equal to itself.")
13471347 }
13481348 else throw("Strict value is not equal to itself.")
13491349 }
13501350 else throw("Strict value is not equal to itself.")
13511351 }
13521352 else throw("Strict value is not equal to itself.")
13531353 }
13541354 }
13551355 else throw("Strict value is not equal to itself.")
13561356 }
13571357
13581358
13591359
13601360 @Callable(i)
13611361 func removeMargin (_amount) = {
13621362 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13631363 if ((sync == sync))
13641364 then {
13651365 let _trader = toString(i.caller)
13661366 if (if (if (if ((0 >= _amount))
13671367 then true
13681368 else !(requireOpenPosition(_trader)))
13691369 then true
13701370 else !(initialized()))
13711371 then true
13721372 else paused())
13731373 then throw("Invalid removeMargin parameters")
13741374 else {
1375- let $t05920359343 = getPosition(_trader)
1376- let oldPositionSize = $t05920359343._1
1377- let oldPositionMargin = $t05920359343._2
1378- let oldPositionOpenNotional = $t05920359343._3
1379- let oldPositionLstUpdCPF = $t05920359343._4
1375+ let $t05921759357 = getPosition(_trader)
1376+ let oldPositionSize = $t05921759357._1
1377+ let oldPositionMargin = $t05921759357._2
1378+ let oldPositionOpenNotional = $t05921759357._3
1379+ let oldPositionLstUpdCPF = $t05921759357._4
13801380 let marginDelta = -(_amount)
1381- let $t05938059559 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1382- let remainMargin = $t05938059559._1
1383- let badDebt = $t05938059559._2
1381+ let $t05939459573 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
1382+ let remainMargin = $t05939459573._1
1383+ let badDebt = $t05939459573._2
13841384 if ((badDebt != 0))
13851385 then throw("Invalid removed margin amount")
13861386 else {
13871387 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
13881388 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
13891389 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
13901390 else {
13911391 let quoteAssetStr = toBase58String(quoteAsset())
1392- let $t06000360057 = getBorrowedByTrader(_trader)
1393- let borrowed = $t06000360057._1
1394- let assetId = $t06000360057._2
1392+ let $t06001760071 = getBorrowedByTrader(_trader)
1393+ let borrowed = $t06001760071._1
1394+ let assetId = $t06001760071._2
13951395 let toRepay = if ((_amount > borrowed))
13961396 then borrowed
13971397 else _amount
13981398 let toWithdraw = if ((borrowed > _amount))
13991399 then 0
14001400 else (_amount - borrowed)
14011401 let finalBorrow = (borrowed - toRepay)
14021402 let switchPositionToQuote = if ((finalBorrow > 0))
14031403 then nil
14041404 else updatePositionAsset(_trader, quoteAssetStr)
14051405 let doSanityCheck = if (((toRepay + toWithdraw) != _amount))
14061406 then throw(((((("toRepay=" + toString(toRepay)) + " + toWithdraw=") + toString(toWithdraw)) + " != ") + toString(_amount)))
14071407 else nil
14081408 if ((doSanityCheck == doSanityCheck))
14091409 then {
14101410 let doUnstake = invoke(vaultAddress(), "withdrawLocked", [_amount], nil)
14111411 if ((doUnstake == doUnstake))
14121412 then {
14131413 let returnCollateralAction = if ((toRepay > 0))
14141414 then {
14151415 let doRepay = invoke(collateralAddress(), "repay", [_trader, assetId], [AttachedPayment(quoteAsset(), toRepay)])
14161416 if ((doRepay == doRepay))
14171417 then [ScriptTransfer(i.caller, toRepay, fromBase58String(assetId))]
14181418 else throw("Strict value is not equal to itself.")
14191419 }
14201420 else nil
14211421 if ((returnCollateralAction == returnCollateralAction))
14221422 then ((((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ (if ((toWithdraw > 0))
14231423 then withdraw(i.caller, toWithdraw)
14241424 else nil)) ++ updateBalance((cbalance() - _amount))) ++ switchPositionToQuote) ++ returnCollateralAction)
14251425 else throw("Strict value is not equal to itself.")
14261426 }
14271427 else throw("Strict value is not equal to itself.")
14281428 }
14291429 else throw("Strict value is not equal to itself.")
14301430 }
14311431 }
14321432 }
14331433 }
14341434 else throw("Strict value is not equal to itself.")
14351435 }
14361436
14371437
14381438
14391439 @Callable(i)
14401440 func closePosition () = {
14411441 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14421442 if ((sync == sync))
14431443 then {
14441444 let _trader = getActualCaller(i)
14451445 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
14461446 if (if (if (!(requireOpenPosition(_trader)))
14471447 then true
14481448 else !(initialized()))
14491449 then true
14501450 else paused())
14511451 then throw("Invalid closePosition parameters")
14521452 else {
1453- let $t06230762685 = internalClosePosition(_trader, true)
1454- let x1 = $t06230762685._1
1455- let positionBadDebt = $t06230762685._2
1456- let realizedPnl = $t06230762685._3
1457- let marginToVault = $t06230762685._4
1458- let quoteAssetReserveAfter = $t06230762685._5
1459- let baseAssetReserveAfter = $t06230762685._6
1460- let totalPositionSizeAfter = $t06230762685._7
1461- let cumulativeNotionalAfter = $t06230762685._8
1462- let openInterestNotionalAfter = $t06230762685._9
1463- let x2 = $t06230762685._10
1464- let totalLongAfter = $t06230762685._11
1465- let totalShortAfter = $t06230762685._12
1453+ let $t06232162699 = internalClosePosition(_trader, true)
1454+ let x1 = $t06232162699._1
1455+ let positionBadDebt = $t06232162699._2
1456+ let realizedPnl = $t06232162699._3
1457+ let marginToVault = $t06232162699._4
1458+ let quoteAssetReserveAfter = $t06232162699._5
1459+ let baseAssetReserveAfter = $t06232162699._6
1460+ let totalPositionSizeAfter = $t06232162699._7
1461+ let cumulativeNotionalAfter = $t06232162699._8
1462+ let openInterestNotionalAfter = $t06232162699._9
1463+ let x2 = $t06232162699._10
1464+ let totalLongAfter = $t06232162699._11
1465+ let totalShortAfter = $t06232162699._12
14661466 if ((positionBadDebt > 0))
14671467 then throw("Unable to close position with bad debt")
14681468 else {
14691469 let withdrawAmount = abs(marginToVault)
14701470 let ammBalance = (cbalance() - withdrawAmount)
1471- let $t06300963524 = if ((0 > ammBalance))
1471+ let $t06302363538 = if ((0 > ammBalance))
14721472 then $Tuple2(0, abs(ammBalance))
14731473 else $Tuple2(ammBalance, 0)
1474- let ammNewBalance = $t06300963524._1
1475- let x11 = $t06300963524._2
1474+ let ammNewBalance = $t06302363538._1
1475+ let x11 = $t06302363538._2
14761476 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
14771477 if ((unstake == unstake))
14781478 then {
1479- let $t06373663790 = getBorrowedByTrader(_trader)
1480- let borrowed = $t06373663790._1
1481- let assetId = $t06373663790._2
1482- let $t06380564722 = if ((borrowed > 0))
1479+ let $t06375063804 = getBorrowedByTrader(_trader)
1480+ let borrowed = $t06375063804._1
1481+ let assetId = $t06375063804._2
1482+ let $t06381964736 = if ((borrowed > 0))
14831483 then if ((withdrawAmount >= borrowed))
14841484 then {
14851485 let doRepay = invoke(collateralAddress(), "repay", [_trader, assetId], [AttachedPayment(quoteAsset(), borrowed)])
14861486 if ((doRepay == doRepay))
14871487 then $Tuple2([ScriptTransfer(_traderAddress, borrowed, fromBase58String(assetId))], (withdrawAmount - borrowed))
14881488 else throw("Strict value is not equal to itself.")
14891489 }
14901490 else {
14911491 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, assetId], [AttachedPayment(quoteAsset(), withdrawAmount)])
14921492 if ((realizeAndClose == realizeAndClose))
14931493 then $Tuple2([ScriptTransfer(_traderAddress, withdrawAmount, fromBase58String(assetId))], 0)
14941494 else throw("Strict value is not equal to itself.")
14951495 }
14961496 else $Tuple2(nil, withdrawAmount)
1497- if (($t06380564722 == $t06380564722))
1497+ if (($t06381964736 == $t06381964736))
14981498 then {
1499- let quoteWithdrawAmount = $t06380564722._2
1500- let sendCollateralAction = $t06380564722._1
1499+ let quoteWithdrawAmount = $t06381964736._2
1500+ let sendCollateralAction = $t06381964736._1
15011501 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
15021502 if ((notifyNotional == notifyNotional))
15031503 then ((((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ (if ((quoteWithdrawAmount > 0))
15041504 then withdraw(_traderAddress, quoteWithdrawAmount)
15051505 else nil)) ++ updateBalance(ammNewBalance)) ++ sendCollateralAction)
15061506 else throw("Strict value is not equal to itself.")
15071507 }
15081508 else throw("Strict value is not equal to itself.")
15091509 }
15101510 else throw("Strict value is not equal to itself.")
15111511 }
15121512 }
15131513 }
15141514 else throw("Strict value is not equal to itself.")
15151515 }
15161516
15171517
15181518
15191519 @Callable(i)
15201520 func liquidate (_trader) = {
15211521 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15221522 if ((sync == sync))
15231523 then {
15241524 let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
15251525 let marginRatio = if (isOverFluctuationLimit())
15261526 then {
15271527 let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
15281528 vmax(spotMarginRatio, oracleMarginRatio)
15291529 }
15301530 else spotMarginRatio
15311531 if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
15321532 then true
15331533 else !(requireOpenPosition(_trader)))
15341534 then true
15351535 else !(initialized()))
15361536 then true
15371537 else paused())
15381538 then throw("Unable to liquidate")
15391539 else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
15401540 then (partialLiquidationRatio() > 0)
15411541 else false)
15421542 then (DECIMAL_UNIT > partialLiquidationRatio())
15431543 else false)
15441544 then {
1545- let $t06649066640 = getPosition(_trader)
1546- let oldPositionSize = $t06649066640._1
1547- let oldPositionMargin = $t06649066640._2
1548- let oldPositionOpenNotional = $t06649066640._3
1549- let oldPositionLstUpdCPF = $t06649066640._4
1545+ let $t06650466654 = getPosition(_trader)
1546+ let oldPositionSize = $t06650466654._1
1547+ let oldPositionMargin = $t06650466654._2
1548+ let oldPositionOpenNotional = $t06650466654._3
1549+ let oldPositionLstUpdCPF = $t06650466654._4
15501550 let _direction = if ((oldPositionSize > 0))
15511551 then DIR_SHORT
15521552 else DIR_LONG
15531553 let isAdd = (_direction == DIR_LONG)
15541554 let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1555- let $t06686566969 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1556- let oldPositionNotional = $t06686566969._1
1557- let unrealizedPnl = $t06686566969._2
1558- let $t06697767209 = swapInput(isAdd, exchangedQuoteAssetAmount)
1559- let exchangedPositionSize = $t06697767209._1
1560- let quoteAssetReserveAfter = $t06697767209._2
1561- let baseAssetReserveAfter = $t06697767209._3
1562- let totalPositionSizeAfter = $t06697767209._4
1563- let cumulativeNotionalAfter = $t06697767209._5
1555+ let $t06687966983 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1556+ let oldPositionNotional = $t06687966983._1
1557+ let unrealizedPnl = $t06687966983._2
1558+ let $t06699167223 = swapInput(isAdd, exchangedQuoteAssetAmount)
1559+ let exchangedPositionSize = $t06699167223._1
1560+ let quoteAssetReserveAfter = $t06699167223._2
1561+ let baseAssetReserveAfter = $t06699167223._3
1562+ let totalPositionSizeAfter = $t06699167223._4
1563+ let cumulativeNotionalAfter = $t06699167223._5
15641564 let liquidationRatio = divd(abs(exchangedPositionSize), abs(oldPositionSize))
15651565 let realizedPnl = muld(unrealizedPnl, liquidationRatio)
1566- let $t06749867731 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1567- let remainMargin = $t06749867731._1
1568- let badDebt = $t06749867731._2
1569- let fundingPayment = $t06749867731._3
1566+ let $t06751267745 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1567+ let remainMargin = $t06751267745._1
1568+ let badDebt = $t06751267745._2
1569+ let fundingPayment = $t06751267745._3
15701570 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
15711571 let remainOpenNotional = if ((oldPositionSize > 0))
15721572 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
15731573 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
15741574 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
15751575 let feeToLiquidator = (liquidationPenalty / 2)
15761576 let feeToInsurance = (liquidationPenalty - feeToLiquidator)
15771577 let newPositionMargin = (remainMargin - liquidationPenalty)
15781578 let newPositionSize = (oldPositionSize + exchangedPositionSize)
15791579 let newPositionOpenNotional = abs(remainOpenNotional)
15801580 let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
15811581 let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
15821582 let ammBalance = (cbalance() - liquidationPenalty)
1583- let $t06890469033 = if ((0 > ammBalance))
1583+ let $t06891869047 = if ((0 > ammBalance))
15841584 then $Tuple2(0, abs(ammBalance))
15851585 else $Tuple2(ammBalance, 0)
1586- let newAmmBalance = $t06890469033._1
1587- let x11 = $t06890469033._2
1588- let $t06904169095 = getBorrowedByTrader(_trader)
1589- let borrowed = $t06904169095._1
1590- let assetId = $t06904169095._2
1586+ let newAmmBalance = $t06891869047._1
1587+ let x11 = $t06891869047._2
1588+ let $t06905569109 = getBorrowedByTrader(_trader)
1589+ let borrowed = $t06905569109._1
1590+ let assetId = $t06905569109._2
15911591 let doLiquidateCollateral = if ((borrowed > 0))
15921592 then {
15931593 let collateralToSell = muld(borrowed, liquidationRatio)
15941594 let realizeAndClose = invoke(collateralAddress(), "realizePartially", [_trader, assetId, collateralToSell], nil)
15951595 if ((realizeAndClose == realizeAndClose))
15961596 then nil
15971597 else throw("Strict value is not equal to itself.")
15981598 }
15991599 else nil
16001600 if ((doLiquidateCollateral == doLiquidateCollateral))
16011601 then {
16021602 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
16031603 if ((unstake == unstake))
16041604 then {
16051605 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
16061606 if ((depositInsurance == depositInsurance))
16071607 then {
16081608 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
16091609 if ((notifyNotional == notifyNotional))
16101610 then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
16111611 then abs(exchangedPositionSize)
16121612 else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
16131613 then abs(exchangedPositionSize)
16141614 else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
16151615 else throw("Strict value is not equal to itself.")
16161616 }
16171617 else throw("Strict value is not equal to itself.")
16181618 }
16191619 else throw("Strict value is not equal to itself.")
16201620 }
16211621 else throw("Strict value is not equal to itself.")
16221622 }
16231623 else {
1624- let $t07090071355 = internalClosePosition(_trader, false)
1625- let x1 = $t07090071355._1
1626- let badDebt = $t07090071355._2
1627- let x2 = $t07090071355._3
1628- let x3 = $t07090071355._4
1629- let quoteAssetReserveAfter = $t07090071355._5
1630- let baseAssetReserveAfter = $t07090071355._6
1631- let totalPositionSizeAfter = $t07090071355._7
1632- let cumulativeNotionalAfter = $t07090071355._8
1633- let openInterestNotionalAfter = $t07090071355._9
1634- let exchangedQuoteAssetAmount = $t07090071355._10
1635- let totalLongAfter = $t07090071355._11
1636- let totalShortAfter = $t07090071355._12
1624+ let $t07091471369 = internalClosePosition(_trader, false)
1625+ let x1 = $t07091471369._1
1626+ let badDebt = $t07091471369._2
1627+ let x2 = $t07091471369._3
1628+ let x3 = $t07091471369._4
1629+ let quoteAssetReserveAfter = $t07091471369._5
1630+ let baseAssetReserveAfter = $t07091471369._6
1631+ let totalPositionSizeAfter = $t07091471369._7
1632+ let cumulativeNotionalAfter = $t07091471369._8
1633+ let openInterestNotionalAfter = $t07091471369._9
1634+ let exchangedQuoteAssetAmount = $t07091471369._10
1635+ let totalLongAfter = $t07091471369._11
1636+ let totalShortAfter = $t07091471369._12
16371637 let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
16381638 let feeToLiquidator = (liquidationPenalty / 2)
16391639 let feeToInsurance = (liquidationPenalty - feeToLiquidator)
16401640 let ammBalance = (cbalance() - liquidationPenalty)
1641- let $t07176771896 = if ((0 > ammBalance))
1641+ let $t07178171910 = if ((0 > ammBalance))
16421642 then $Tuple2(0, abs(ammBalance))
16431643 else $Tuple2(ammBalance, 0)
1644- let newAmmBalance = $t07176771896._1
1645- let x11 = $t07176771896._2
1646- let $t07190471958 = getBorrowedByTrader(_trader)
1647- let borrowed = $t07190471958._1
1648- let assetId = $t07190471958._2
1644+ let newAmmBalance = $t07178171910._1
1645+ let x11 = $t07178171910._2
1646+ let $t07191871972 = getBorrowedByTrader(_trader)
1647+ let borrowed = $t07191871972._1
1648+ let assetId = $t07191871972._2
16491649 let doLiquidateCollateral = if ((borrowed > 0))
16501650 then {
16511651 let realizeAndClose = invoke(collateralAddress(), "realizePartiallyAndClose", [_trader, assetId], nil)
16521652 if ((realizeAndClose == realizeAndClose))
16531653 then nil
16541654 else throw("Strict value is not equal to itself.")
16551655 }
16561656 else nil
16571657 if ((doLiquidateCollateral == doLiquidateCollateral))
16581658 then {
16591659 let x = if ((badDebt > 0))
16601660 then {
16611661 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [badDebt], nil)
16621662 if ((lockBadDebt == lockBadDebt))
16631663 then nil
16641664 else throw("Strict value is not equal to itself.")
16651665 }
16661666 else nil
16671667 if ((x == x))
16681668 then {
16691669 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
16701670 if ((unstake == unstake))
16711671 then {
16721672 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
16731673 if ((depositInsurance == depositInsurance))
16741674 then {
16751675 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
16761676 if ((notifyNotional == notifyNotional))
16771677 then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
16781678 else throw("Strict value is not equal to itself.")
16791679 }
16801680 else throw("Strict value is not equal to itself.")
16811681 }
16821682 else throw("Strict value is not equal to itself.")
16831683 }
16841684 else throw("Strict value is not equal to itself.")
16851685 }
16861686 else throw("Strict value is not equal to itself.")
16871687 }
16881688 }
16891689 else throw("Strict value is not equal to itself.")
16901690 }
16911691
16921692
16931693
16941694 @Callable(i)
16951695 func payFunding () = {
16961696 let fundingBlockTimestamp = nextFundingBlockTimestamp()
16971697 if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
16981698 then true
16991699 else !(initialized()))
17001700 then true
17011701 else paused())
17021702 then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
17031703 else {
17041704 let underlyingPrice = getOracleTwapPrice()
1705- let $t07398574047 = getFunding()
1706- let shortPremiumFraction = $t07398574047._1
1707- let longPremiumFraction = $t07398574047._2
1705+ let $t07399974061 = getFunding()
1706+ let shortPremiumFraction = $t07399974061._1
1707+ let longPremiumFraction = $t07399974061._2
17081708 updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
17091709 }
17101710 }
17111711
17121712
17131713
17141714 @Callable(i)
17151715 func syncTerminalPriceToOracle () = {
1716- let $t07442974550 = getSyncTerminalPrice(getOracleTwapPrice())
1717- let newQuoteAssetWeight = $t07442974550._1
1718- let newBaseAssetWeight = $t07442974550._2
1719- let marginToVault = $t07442974550._3
1716+ let $t07444374564 = getSyncTerminalPrice(getOracleTwapPrice())
1717+ let newQuoteAssetWeight = $t07444374564._1
1718+ let newBaseAssetWeight = $t07444374564._2
1719+ let marginToVault = $t07444374564._3
17201720 updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight)
17211721 }
17221722
17231723
17241724
17251725 @Callable(i)
17261726 func v_get (_trader) = {
17271727 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17281728 if ((sync == sync))
17291729 then {
1730- let $t07472874788 = internalClosePosition(_trader, false)
1731- let x1 = $t07472874788._1
1732- let x2 = $t07472874788._2
1733- let x3 = $t07472874788._3
1734- let x4 = $t07472874788._4
1730+ let $t07474274802 = internalClosePosition(_trader, false)
1731+ let x1 = $t07474274802._1
1732+ let x2 = $t07474274802._2
1733+ let x3 = $t07474274802._3
1734+ let x4 = $t07474274802._4
17351735 throw((((s(x2) + s(x3)) + s(x4)) + s(getMarginRatio(_trader))))
17361736 }
17371737 else throw("Strict value is not equal to itself.")
17381738 }
17391739
17401740
17411741
17421742 @Callable(i)
17431743 func view_calcRemainMarginWithFundingPayment (_trader) = {
17441744 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17451745 if ((sync == sync))
17461746 then {
1747- let $t07499975100 = getPosition(_trader)
1748- let positionSize = $t07499975100._1
1749- let positionMargin = $t07499975100._2
1750- let pon = $t07499975100._3
1751- let positionLstUpdCPF = $t07499975100._4
1752- let $t07510375204 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1753- let positionNotional = $t07510375204._1
1754- let unrealizedPnl = $t07510375204._2
1755- let $t07520775379 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1756- let remainMargin = $t07520775379._1
1757- let badDebt = $t07520775379._2
1758- let fundingPayment = $t07520775379._3
1747+ let $t07501375114 = getPosition(_trader)
1748+ let positionSize = $t07501375114._1
1749+ let positionMargin = $t07501375114._2
1750+ let pon = $t07501375114._3
1751+ let positionLstUpdCPF = $t07501375114._4
1752+ let $t07511775218 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1753+ let positionNotional = $t07511775218._1
1754+ let unrealizedPnl = $t07511775218._2
1755+ let $t07522175393 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1756+ let remainMargin = $t07522175393._1
1757+ let badDebt = $t07522175393._2
1758+ let fundingPayment = $t07522175393._3
17591759 throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
17601760 }
17611761 else throw("Strict value is not equal to itself.")
17621762 }
17631763
17641764
17651765
17661766 @Callable(i)
17671767 func view_getPegAdjustCost (_price) = {
17681768 let result = getSyncTerminalPrice(_price)
17691769 throw(toString(result._3))
17701770 }
17711771
17721772
17731773
17741774 @Callable(i)
17751775 func view_getTerminalAmmPrice () = {
1776- let $t07572675807 = getTerminalAmmState()
1777- let terminalQuoteAssetReserve = $t07572675807._1
1778- let terminalBaseAssetReserve = $t07572675807._2
1776+ let $t07574075821 = getTerminalAmmState()
1777+ let terminalQuoteAssetReserve = $t07574075821._1
1778+ let terminalBaseAssetReserve = $t07574075821._2
17791779 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17801780 throw(toString(price))
17811781 }
17821782
17831783
17841784
17851785 @Callable(i)
17861786 func view_getFunding () = {
17871787 let underlyingPrice = getOracleTwapPrice()
1788- let $t07602676088 = getFunding()
1789- let shortPremiumFraction = $t07602676088._1
1790- let longPremiumFraction = $t07602676088._2
1788+ let $t07604076102 = getFunding()
1789+ let shortPremiumFraction = $t07604076102._1
1790+ let longPremiumFraction = $t07604076102._2
17911791 let longFunding = divd(longPremiumFraction, underlyingPrice)
17921792 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17931793 throw((((s(longFunding) + s(shortFunding)) + s(getTwapSpotPrice())) + s(getOracleTwapPrice())))
17941794 }
17951795
17961796
17971797
17981798 @Callable(i)
17991799 func view_getBorrowedByTrader (_trader) = {
1800- let $t07637876432 = getBorrowedByTrader(_trader)
1801- let borrowed = $t07637876432._1
1802- let assetId = $t07637876432._2
1800+ let $t07639276446 = getBorrowedByTrader(_trader)
1801+ let borrowed = $t07639276446._1
1802+ let assetId = $t07639276446._2
18031803 throw((s(borrowed) + assetId))
18041804 }
18051805
18061806
18071807 @Verifier(tx)
18081808 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
18091809

github/deemru/w8io/169f3d6 
460.99 ms