tx · DmKnwLES8MaHUdoGRyHgwWuTMXhjT3sZy1XwdNCeEsdH

3N1xoR4nCRmRL12XHH1koRKLHEwWKcjSiBe:  -0.07500000 Waves

2023.07.12 18:48 [2662878] smart account 3N1xoR4nCRmRL12XHH1koRKLHEwWKcjSiBe > SELF 0.00000000 Waves

{ "type": 13, "id": "DmKnwLES8MaHUdoGRyHgwWuTMXhjT3sZy1XwdNCeEsdH", "fee": 7500000, "feeAssetId": null, "timestamp": 1689176922778, "version": 2, "chainId": 84, "sender": "3N1xoR4nCRmRL12XHH1koRKLHEwWKcjSiBe", "senderPublicKey": "C3GpXwYS87W5JhZE97PdK7icpsZrKMXs7wr22VCJPULq", "proofs": [ "269zAY4Ak3NnPrVvf6CSZki4xVtEX7zjDPf9dae8SSVQ6uwimT2NSYTb6QEV5HnUNtqEgwD7mPSyHLkLVyCHqZ3x" ], "script": "base64:BgKUAQgCEgASABIAEgASAwoBARIVChMBAQEBAQEBAQEBAQEBAQEICAEBEhgKFgEBAQEBAQEICAgBAQEBAQEBAQEBAQESBwoFAQEBCAgSBAoCAQgSBQoDAQEIEgcKBQEBAQQIEgUKAwgBCBIDCgEIEgMKAQgSABIAEgMKAQgSBQoDCAEIEgMKAQESABIDCgEIEgASBAoCCAi/AQAMa19iYXNlT3JhY2xlAgxrX2Jhc2VPcmFjbGUADWtfcXVvdGVPcmFjbGUCDWtfcXVvdGVPcmFjbGUACWtfYmFsYW5jZQIJa19iYWxhbmNlAAprX3NlcXVlbmNlAgprX3NlcXVlbmNlAA5rX3Bvc2l0aW9uU2l6ZQIOa19wb3NpdGlvblNpemUAEGtfcG9zaXRpb25NYXJnaW4CEGtfcG9zaXRpb25NYXJnaW4AFmtfcG9zaXRpb25PcGVuTm90aW9uYWwCFmtfcG9zaXRpb25PcGVuTm90aW9uYWwALmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CEmtfcG9zaXRpb25GcmFjdGlvbgASa19wb3NpdGlvblNlcXVlbmNlAhJrX3Bvc2l0aW9uU2VxdWVuY2UADWtfcG9zaXRpb25GZWUCDWtfcG9zaXRpb25GZWUAHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAITa19wb3NpdGlvblRpbWVzdGFtcAANa19pbml0aWFsaXplZAINa19pbml0aWFsaXplZAAIa19wYXVzZWQCCGtfcGF1c2VkAAtrX2Nsb3NlT25seQILa19jbG9zZU9ubHkABWtfZmVlAgVrX2ZlZQANa19yb2xsb3ZlckZlZQIOa19yb2xsb3Zlcl9mZWUAD2tfZnVuZGluZ1BlcmlvZAIPa19mdW5kaW5nUGVyaW9kABFrX2luaXRNYXJnaW5SYXRpbwIRa19pbml0TWFyZ2luUmF0aW8AFGtfbWluSW5pdE1hcmdpblJhdGlvAhRrX21pbkluaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8AGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8CFmtfcGFydExpcXVpZGF0aW9uUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QAEGtfbWF4UHJpY2VTcHJlYWQCEGtfbWF4UHJpY2VTcHJlYWQAEWtfbWF4T3Blbk5vdGlvbmFsAhFrX21heE9wZW5Ob3Rpb25hbAAVa19mZWVUb1N0YWtlcnNQZXJjZW50AhVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQAEGtfbWF4T3JhY2xlRGVsYXkCEGtfbWF4T3JhY2xlRGVsYXkADWtfZnVuZGluZ01vZGUCDWtfZnVuZGluZ01vZGUADGtfb3JhY2xlTW9kZQIMa19vcmFjbGVNb2RlAA5rX3Bvc2l0aW9uTW9kZQIOa19wb3NpdGlvbk1vZGUAGGtfbWluTGlxdWlkYXRpb25Ob3Rpb25hbAIYa19taW5MaXF1aWRhdGlvbk5vdGlvbmFsACVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhtrX2xhdGVzdExvbmdQcmVtaXVtRnJhY3Rpb24AJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhxrX2xhdGVzdFNob3J0UHJlbWl1bUZyYWN0aW9uABJrX25leHRGdW5kaW5nQmxvY2sCHmtfbmV4dEZ1bmRpbmdCbG9ja01pblRpbWVzdGFtcAARa19sb25nRnVuZGluZ1JhdGUCEWtfbG9uZ0Z1bmRpbmdSYXRlABJrX3Nob3J0RnVuZGluZ1JhdGUCEmtfc2hvcnRGdW5kaW5nUmF0ZQATa19xdW90ZUFzc2V0UmVzZXJ2ZQIIa19xdEFzdFIAEmtfYmFzZUFzc2V0UmVzZXJ2ZQIIa19ic0FzdFIAEmtfcXVvdGVBc3NldFdlaWdodAIIa19xdEFzdFcAEWtfYmFzZUFzc2V0V2VpZ2h0AghrX2JzQXN0VwATa190b3RhbFBvc2l0aW9uU2l6ZQITa190b3RhbFBvc2l0aW9uU2l6ZQAXa190b3RhbExvbmdQb3NpdGlvblNpemUCF2tfdG90YWxMb25nUG9zaXRpb25TaXplABhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAIWa19vcGVuSW50ZXJlc3ROb3Rpb25hbAATa19vcGVuSW50ZXJlc3RTaG9ydAITa19vcGVuSW50ZXJlc3RTaG9ydAASa19vcGVuSW50ZXJlc3RMb25nAhJrX29wZW5JbnRlcmVzdExvbmcACGtfbGFzdFR4AghrX2xhc3RUeAAUa19jb29yZGluYXRvckFkZHJlc3MCFGtfY29vcmRpbmF0b3JBZGRyZXNzAA9rX3ZhdWx0X2FkZHJlc3MCD2tfdmF1bHRfYWRkcmVzcwAPa19hZG1pbl9hZGRyZXNzAg9rX2FkbWluX2FkZHJlc3MADWtfcXVvdGVfYXNzZXQCDWtfcXVvdGVfYXNzZXQAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MAEGtfb3JkZXJzX2FkZHJlc3MCEGtfb3JkZXJzX2FkZHJlc3MAEmtfcmVmZXJyYWxfYWRkcmVzcwISa19yZWZlcnJhbF9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwEOdG9Db21wb3NpdGVLZXkCBF9rZXkIX2FkZHJlc3MJAKwCAgkArAICBQRfa2V5AgFfBQhfYWRkcmVzcwELY29vcmRpbmF0b3IACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MCE0Nvb3JkaW5hdG9yIG5vdCBzZXQBDGFkbWluQWRkcmVzcwAJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19hZG1pbl9hZGRyZXNzAQpxdW90ZUFzc2V0AAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ1rX3F1b3RlX2Fzc2V0AQ5zdGFraW5nQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRFrX3N0YWtpbmdfYWRkcmVzcwIPU3Rha2luZyBub3Qgc2V0AQx2YXVsdEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa192YXVsdF9hZGRyZXNzAg1WYXVsdCBub3Qgc2V0AQxtaW5lckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19taW5lcl9hZGRyZXNzAg1NaW5lciBub3Qgc2V0AQ1vcmRlcnNBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEGtfb3JkZXJzX2FkZHJlc3MCDk9yZGVycyBub3Qgc2V0AQ9yZWZlcnJhbEFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19yZWZlcnJhbF9hZGRyZXNzAhBSZWZlcnJhbCBub3Qgc2V0ARFuZnRNYW5hZ2VyQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCE05GVCBNYW5hZ2VyIG5vdCBzZXQADWtfdG9rZW5fcGFyYW0CDWtfdG9rZW5fcGFyYW0ADGtfdG9rZW5fdHlwZQIMa190b2tlbl90eXBlABhGRUVfUkVEVUNUSU9OX1RPS0VOX1RZUEUCDWZlZV9yZWR1Y3Rpb24ACERJUl9MT05HAAEACURJUl9TSE9SVAACAAdTRUNPTkRTAOgHAA9ERUNJTUFMX05VTUJFUlMABgAMREVDSU1BTF9VTklUCQBoAgABCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoAD01JTlVURVNfSU5fWUVBUgkAaAIAoIogBQxERUNJTUFMX1VOSVQAB09ORV9EQVkJAGgCAICjBQUMREVDSU1BTF9VTklUAA9QTkxfT1BUSU9OX1NQT1QAAQARUE5MX09QVElPTl9PUkFDTEUAAgASRlVORElOR19BU1lNTUVUUklDAAEAEUZVTkRJTkdfU1lNTUVUUklDAAIADE9SQUNMRV9QTEFJTgABAApPUkFDTEVfSklUAAIAD1BPU0lUSU9OX0RJUkVDVAABAA5QT1NJVElPTl9PUkRFUgACAQFzAQJfeAkArAICCQCkAwEFAl94AgEsAQRkaXZkAgJfeAJfeQkAbgQFAl94BQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEEbXVsZAICX3gCX3kJAG4EBQJfeAUCX3kFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBWJkaXZkAgJfeAJfeQkAvQIEBQJfeAkAtgIBBQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEFYm11bGQCAl94Al95CQC9AgQFAl94BQJfeQkAtgIBBQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQNhYnMBAl94AwkAZgIFAl94AAAFAl94CQEBLQEFAl94AQR2bWF4AgJfeAJfeQMJAGcCBQJfeAUCX3kFAl94BQJfeQEDaW50AQFrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUEdGhpcwUBawkArAICAg1ubyB2YWx1ZSBmb3IgBQFrAQVpbnRPcgIBawNkZWYJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBawUDZGVmAQRzdHJBAghfYWRkcmVzcwRfa2V5BAN2YWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQhfYWRkcmVzcwUEX2tleQkArAICAhFObyB2YWx1ZSBmb3Iga2V5IAUEX2tleQUDdmFsAQRpbnRBAghfYWRkcmVzcwRfa2V5BAN2YWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQhfYWRkcmVzcwUEX2tleQkArAICAhFObyB2YWx1ZSBmb3Iga2V5IAUEX2tleQUDdmFsAQhjYmFsYW5jZQAJAQNpbnQBBQlrX2JhbGFuY2UBCWNiYWxhbmNlMAAJAQVpbnRPcgIFCWtfYmFsYW5jZQAAAQNmZWUACQEDaW50AQUFa19mZWUBD3JvbGxvdmVyRmVlUmF0ZQAJAQNpbnQBBQ1rX3JvbGxvdmVyRmVlAQ9pbml0TWFyZ2luUmF0aW8ACQEDaW50AQURa19pbml0TWFyZ2luUmF0aW8BEm1pbkluaXRNYXJnaW5SYXRpbwAJAQVpbnRPcgIFFGtfbWluSW5pdE1hcmdpblJhdGlvBQxERUNJTUFMX1VOSVQBBnF0QXN0UgAJAQNpbnQBBRNrX3F1b3RlQXNzZXRSZXNlcnZlAQdxdEFzdFIwAAkBBWludE9yAgUTa19xdW90ZUFzc2V0UmVzZXJ2ZQAAAQZic0FzdFIACQEDaW50AQUSa19iYXNlQXNzZXRSZXNlcnZlAQdic0FzdFIwAAkBBWludE9yAgUSa19iYXNlQXNzZXRSZXNlcnZlAAABBnF0QXN0VwAJAQVpbnRPcgIFEmtfcXVvdGVBc3NldFdlaWdodAUMREVDSU1BTF9VTklUAQZic0FzdFcACQEFaW50T3ICBRFrX2Jhc2VBc3NldFdlaWdodAUMREVDSU1BTF9VTklUARF0b3RhbFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRNrX3RvdGFsUG9zaXRpb25TaXplARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAJAQNpbnQBBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsARFvcGVuSW50ZXJlc3RTaG9ydAAJAQNpbnQBBRNrX29wZW5JbnRlcmVzdFNob3J0ARBvcGVuSW50ZXJlc3RMb25nAAkBA2ludAEFEmtfb3BlbkludGVyZXN0TG9uZwEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAAJAQNpbnQBBRJrX25leHRGdW5kaW5nQmxvY2sBEGZ1bmRpbmdQZXJpb2RSYXcACQEDaW50AQUPa19mdW5kaW5nUGVyaW9kARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFDERFQ0lNQUxfVU5JVAEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQdTRUNPTkRTARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAkBA2ludAEFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwETbGlxdWlkYXRpb25GZWVSYXRpbwAJAQNpbnQBBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8BF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAkBA2ludAEFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8BC3NwcmVhZExpbWl0AAkBA2ludAEFDWtfc3ByZWFkTGltaXQBDm1heFByaWNlSW1wYWN0AAkBA2ludAEFEGtfbWF4UHJpY2VJbXBhY3QBDm1heFByaWNlU3ByZWFkAAkBA2ludAEFEGtfbWF4UHJpY2VTcHJlYWQBD21heE9wZW5Ob3Rpb25hbAAJAQNpbnQBBRFrX21heE9wZW5Ob3Rpb25hbAEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBA2ludAEFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBA2ludAEFF2tfdG90YWxMb25nUG9zaXRpb25TaXplAQxsYXN0U2VxdWVuY2UACQEFaW50T3ICBQprX3NlcXVlbmNlAAABE2ZlZVRvU3Rha2Vyc1BlcmNlbnQACQEDaW50AQUVa19mZWVUb1N0YWtlcnNQZXJjZW50AQ5tYXhPcmFjbGVEZWxheQAJAQNpbnQBBRBrX21heE9yYWNsZURlbGF5AQtmdW5kaW5nTW9kZQAJAQVpbnRPcgIFDWtfZnVuZGluZ01vZGUFEkZVTkRJTkdfQVNZTU1FVFJJQwEKb3JhY2xlTW9kZQAJAQVpbnRPcgIFDGtfb3JhY2xlTW9kZQUMT1JBQ0xFX1BMQUlOAQxwb3NpdGlvbk1vZGUACQEFaW50T3ICBQ5rX3Bvc2l0aW9uTW9kZQUPUE9TSVRJT05fRElSRUNUAR1taW5QYXJ0aWFsTGlxdWlkYXRpb25Ob3Rpb25hbAAJAQVpbnRPcgIFGGtfbWluTGlxdWlkYXRpb25Ob3Rpb25hbAkAaAIACgUMREVDSU1BTF9VTklUAQ1sYXN0VGltZXN0YW1wAAgFCWxhc3RCbG9jawl0aW1lc3RhbXABD2dldEFjdHVhbENhbGxlcgEBaQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQENb3JkZXJzQWRkcmVzcwACCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcJAAIBCQCsAgIJAKwCAgkArAICAhBJbnZhbGlkIG1hcmdpbjogCQCkAwEFDF9tYXJnaW5SYXRpbwIDIDwgCQCkAwEFEF9iYXNlTWFyZ2luUmF0aW8DAwkBASEBBRRfbGFyZ2VyVGhhbk9yRXF1YWxUbwkAZwIFFHJlbWFpbmluZ01hcmdpblJhdGlvAAAHCQACAQkArAICCQCsAgIJAKwCAgIQSW52YWxpZCBtYXJnaW46IAkApAMBBQxfbWFyZ2luUmF0aW8CAyA+IAkApAMBBRBfYmFzZU1hcmdpblJhdGlvBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgIHX3RyYWRlcgpfZGlyZWN0aW9uBAtwb3NpdGlvbktleQkArAICCQCsAgIFB190cmFkZXICAV8JAKQDAQUKX2RpcmVjdGlvbgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQtwb3NpdGlvbktleQQHJG1hdGNoMAUPcG9zaXRpb25TaXplT3B0AwkAAQIFByRtYXRjaDACA0ludAQMcG9zaXRpb25TaXplBQckbWF0Y2gwCQCXCgUFDHBvc2l0aW9uU2l6ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgULcG9zaXRpb25LZXkJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFC3Bvc2l0aW9uS2V5CQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQtwb3NpdGlvbktleQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQtwb3NpdGlvbktleQkAlwoFAAAAAAAAAAAAAAEMZ2V0RGlyZWN0aW9uAQ1fcG9zaXRpb25TaXplAwkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQUJRElSX1NIT1JUBQhESVJfTE9ORwEOZ2V0UG9zaXRpb25GZWUCB190cmFkZXIKX2RpcmVjdGlvbgQLcG9zaXRpb25LZXkJAKwCAgkArAICBQdfdHJhZGVyAgFfCQCkAwEFCl9kaXJlY3Rpb24EDnBvc2l0aW9uRmVlT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFC3Bvc2l0aW9uS2V5BAckbWF0Y2gwBQ5wb3NpdGlvbkZlZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEC3Bvc2l0aW9uRmVlBQckbWF0Y2gwBQtwb3NpdGlvbkZlZQkBA2ZlZQABE3JlcXVpcmVPcGVuUG9zaXRpb24CB190cmFkZXIKX2RpcmVjdGlvbgMJAAACCAkBC2dldFBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBDWdldE9yYWNsZURhdGEBA2tleQQNb3JhY2xlRGF0YVN0cgkAnQgCBQR0aGlzBQNrZXkDAwkBCWlzRGVmaW5lZAEFDW9yYWNsZURhdGFTdHIJAQIhPQIJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHICAAcECm9yYWNsZURhdGEJALUJAgkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgIBLAQNb3JhY2xlQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUKb3JhY2xlRGF0YQAACQCsAgICG0ludmFsaWQgb3JhY2xlIGFkZHJlc3MgaW46IAkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgQIcHJpY2VLZXkJAJEDAgUKb3JhY2xlRGF0YQABBAhibG9ja0tleQkAkQMCBQpvcmFjbGVEYXRhAAIEB29wZW5LZXkJAJEDAgUKb3JhY2xlRGF0YQADCQCWCgQFDW9yYWNsZUFkZHJlc3MFCHByaWNlS2V5BQhibG9ja0tleQUHb3BlbktleQUEdW5pdAELaW5pdGlhbGl6ZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFDWtfaW5pdGlhbGl6ZWQHAQZwYXVzZWQACQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMFCGtfcGF1c2VkBwEJY2xvc2VPbmx5AAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQtrX2Nsb3NlT25seQcBDXVwZGF0ZVJlc2VydmUDBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudBBfYmFzZUFzc2V0QW1vdW50AwUGX2lzQWRkBAduZXdCYXNlCQBlAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQDCQBnAgAABQduZXdCYXNlCQACAQIqVHggbGVhZCB0byBiYXNlIGFzc2V0IHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCVCgMJAGQCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQFB25ld0Jhc2UJAGQCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50BAhuZXdRdW90ZQkAZQIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAMJAGcCAAAFCG5ld1F1b3RlCQACAQIqVHggbGVhZCB0byBiYXNlIHF1b3RlIHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCVCgMFCG5ld1F1b3RlCQBkAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQJAGUCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50AQ1jYWxjSW52YXJpYW50AgdfcXRBc3RSB19ic0FzdFIEB2JxdEFzdFIJALYCAQUHX3F0QXN0UgQHYmJzQXN0UgkAtgIBBQdfYnNBc3RSCQEFYm11bGQCBQdicXRBc3RSBQdiYnNBc3RSAQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUHX3F0QXN0VwQBawkBDWNhbGNJbnZhcmlhbnQCBQdfcXRBc3RSBQdfYnNBc3RSBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyAwUGX2lzQWRkCQBkAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkCQBlAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBBhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEDSR0MDE2NTg1MTY3NTUJAQ11cGRhdGVSZXNlcnZlAwUGX2lzQWRkBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNjU4NTE2NzU1Al8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTY1ODUxNjc1NQJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxNjU4NTE2NzU1Al8zBAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLbWFya2V0UHJpY2UJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmBBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QAAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg1QcmljZSBpbXBhY3QgCQCkAwEFC3ByaWNlSW1wYWN0AhQgPiBtYXggcHJpY2UgaW1wYWN0IAkApAMBBRNtYXhQcmljZUltcGFjdFZhbHVlAhUgYmVmb3JlIHF1b3RlIGFzc2V0OiAJAKQDAQUHX3F0QXN0UgIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQUHX2JzQXN0UgIhIHF1b3RlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEV9xdW90ZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDiBtYXJrZXRQcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCWCgQFFWFtb3VudEJhc2VBc3NldEJvdWdodAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxAQ9jYWxjUm9sbG92ZXJGZWUCEl9vbGRQb3NpdGlvbk1hcmdpbiBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAQPcG9zaXRpb25NaW51dGVzCQBoAgkAaQIJAGkCCQBlAgkBDWxhc3RUaW1lc3RhbXAABSBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcADoBwA8BQxERUNJTUFMX1VOSVQEC3JvbGxvdmVyRmVlCQEEZGl2ZAIJAQRtdWxkAgkBBG11bGQCBRJfb2xkUG9zaXRpb25NYXJnaW4FD3Bvc2l0aW9uTWludXRlcwkBD3JvbGxvdmVyRmVlUmF0ZQAFD01JTlVURVNfSU5fWUVBUgULcm9sbG92ZXJGZWUBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUQX29sZFBvc2l0aW9uU2l6ZRJfb2xkUG9zaXRpb25NYXJnaW4lX29sZFBvc2l0aW9uQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAxfbWFyZ2luRGVsdGEEDmZ1bmRpbmdQYXltZW50AwkBAiE9AgUQX29sZFBvc2l0aW9uU2l6ZQAABCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBRBfb2xkUG9zaXRpb25TaXplCQEEbXVsZAIJAGUCBSBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUlX29sZFBvc2l0aW9uQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUQX29sZFBvc2l0aW9uU2l6ZQAABAtyb2xsb3ZlckZlZQkBD2NhbGNSb2xsb3ZlckZlZQIFEl9vbGRQb3NpdGlvbk1hcmdpbgUgX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCCQBlAgUMX21hcmdpbkRlbHRhBQtyb2xsb3ZlckZlZQUOZnVuZGluZ1BheW1lbnQFEl9vbGRQb3NpdGlvbk1hcmdpbgQNJHQwMTk0MjIxOTU0OQMJAGYCAAAFDHNpZ25lZE1hcmdpbgkAlAoCAAAJAQNhYnMBBQxzaWduZWRNYXJnaW4JAJQKAgkBA2FicwEFDHNpZ25lZE1hcmdpbgAABAxyZW1haW5NYXJnaW4IBQ0kdDAxOTQyMjE5NTQ5Al8xBAdiYWREZWJ0CAUNJHQwMTk0MjIxOTU0OQJfMgkAlgoEBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFDmZ1bmRpbmdQYXltZW50BQtyb2xsb3ZlckZlZQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQEC3ByaWNlQmVmb3JlCQEEZGl2ZAIJAQRtdWxkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQENY2FsY0ludmFyaWFudAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX2Jhc2VBc3NldFJlc2VydmUEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkAoAMBCQEFYmRpdmQCBQFrCQC2AgEFGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgQPcXVvdGVBc3NldERlbHRhCQEDYWJzAQkAZQIFD3F1b3RlQXNzZXRBZnRlcgUSX3F1b3RlQXNzZXRSZXNlcnZlBA5xdW90ZUFzc2V0U29sZAkBBG11bGQCBQ9xdW90ZUFzc2V0RGVsdGEFEV9xdW90ZUFzc2V0V2VpZ2h0BBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QABA0kdDAyMDgxMTIwOTczCQENdXBkYXRlUmVzZXJ2ZQMJAQEhAQUGX2lzQWRkBQ9xdW90ZUFzc2V0RGVsdGEFEF9iYXNlQXNzZXRBbW91bnQEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMjA4MTEyMDk3MwJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDIwODExMjA5NzMCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMjA4MTEyMDk3MwJfMwQLbWFya2V0UHJpY2UJAQRkaXZkAgUOcXVvdGVBc3NldFNvbGQFEF9iYXNlQXNzZXRBbW91bnQECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgMDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUFFF9jaGVja01heFByaWNlSW1wYWN0BwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFEl9xdW90ZUFzc2V0UmVzZXJ2ZQIUIGJlZm9yZSBiYXNlIGFzc2V0OiAJAKQDAQURX2Jhc2VBc3NldFJlc2VydmUCICBiYXNlIGFzc2V0IGFtb3VudCB0byBleGNoYW5nZTogCQCkAwEFEF9iYXNlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIPIG1hcmtldCBwcmljZTogCQCkAwEFC21hcmtldFByaWNlCQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAQEhAQUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAABQtwcmljZUltcGFjdAEKc3dhcE91dHB1dAMGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwUGX2lzQWRkBRBfYmFzZUFzc2V0QW1vdW50BRRfY2hlY2tNYXhQcmljZUltcGFjdAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwABE2dldE9yYWNsZVByaWNlVmFsdWUDBm9yYWNsZQhwcmljZUtleQhibG9ja0tleQQJbGFzdFZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhwcmljZUtleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIHByaWNlLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIcHJpY2VLZXkDCQECIT0CBQhibG9ja0tleQIABAxjdXJyZW50QmxvY2sFBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmdldE9yYWNsZVByaWNlAAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQPYmFzZU9yYWNsZVByaWNlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMIBQpiYXNlT3JhY2xlAl8xCAUKYmFzZU9yYWNsZQJfMggFCmJhc2VPcmFjbGUCXzMEC3F1b3RlT3JhY2xlCQENZ2V0T3JhY2xlRGF0YQEFDWtfcXVvdGVPcmFjbGUEEHF1b3RlT3JhY2xlUHJpY2UDCQEJaXNEZWZpbmVkAQULcXVvdGVPcmFjbGUEDHF1b3RlT3JhY2xlVgkBBXZhbHVlAQULcXVvdGVPcmFjbGUJARNnZXRPcmFjbGVQcmljZVZhbHVlAwgFDHF1b3RlT3JhY2xlVgJfMQgFDHF1b3RlT3JhY2xlVgJfMggFDHF1b3RlT3JhY2xlVgJfMwUMREVDSU1BTF9VTklUCQEEZGl2ZAIFD2Jhc2VPcmFjbGVQcmljZQUQcXVvdGVPcmFjbGVQcmljZQEOaXNNYXJrZXRDbG9zZWQABApiYXNlT3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQ1nZXRPcmFjbGVEYXRhAQUMa19iYXNlT3JhY2xlAhlObyBiYXNlIGFzc2V0IG9yYWNsZSBkYXRhBAZvcmFjbGUIBQpiYXNlT3JhY2xlAl8xBAdvcGVuS2V5CAUKYmFzZU9yYWNsZQJfNAMJAQIhPQIFB29wZW5LZXkCAAQGaXNPcGVuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJsIAgUGb3JhY2xlBQdvcGVuS2V5CQCsAgIJAKwCAgkArAICAitDYW4gbm90IGdldCBvcmFjbGUgaXMgb3Blbi9jbG9zZWQuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQdvcGVuS2V5CQEBIQEFBmlzT3BlbgcBDGFic1ByaWNlRGlmZgUMX29yYWNsZVByaWNlEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQdfcXRBc3RXB19ic0FzdFcECnByaWNlQWZ0ZXIJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcEDGF2ZXJhZ2VQcmljZQkBBGRpdmQCCQBkAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgUMYXZlcmFnZVByaWNlBQxhYnNQcmljZURpZmYBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQSYWJzUHJpY2VEaWZmQmVmb3JlCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UJAQZxdEFzdFIACQEGYnNBc3RSAAUHX3F0QXN0VwUHX2JzQXN0VwQRYWJzUHJpY2VEaWZmQWZ0ZXIJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwUHX2JzQXN0VwMDCQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIJAQ5tYXhQcmljZVNwcmVhZAAJAGYCBRFhYnNQcmljZURpZmZBZnRlcgUSYWJzUHJpY2VEaWZmQmVmb3JlBwkAAgEJAKwCAgkArAICCQCsAgICDVByaWNlIHNwcmVhZCAJAKQDAQURYWJzUHJpY2VEaWZmQWZ0ZXICFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIRX2xvbmdPcGVuTm90aW9uYWwSX3Nob3J0T3Blbk5vdGlvbmFsBBBfbWF4T3Blbk5vdGlvbmFsCQEPbWF4T3Blbk5vdGlvbmFsAAMJAGYCBRFfbG9uZ09wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICE0xvbmcgb3BlbiBub3Rpb25hbCAJAKQDAQURX2xvbmdPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsAwkAZgIFEl9zaG9ydE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICFFNob3J0IG9wZW4gbm90aW9uYWwgCQCkAwEFEl9zaG9ydE9wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwGASFyZXF1aXJlU2VuZGVyQ2FuV29ya1dpdGhQb3NpdGlvbnMBB19jYWxsZXIDCQAAAgkBDHBvc2l0aW9uTW9kZQAFDlBPU0lUSU9OX09SREVSCQAAAgUHX2NhbGxlcgkBDW9yZGVyc0FkZHJlc3MABgEMZ2V0U3BvdFByaWNlAAQSX3F1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RSAAQRX2Jhc2VBc3NldFJlc2VydmUJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcBFmlzT3ZlckZsdWN0dWF0aW9uTGltaXQABAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYNX3Bvc2l0aW9uU2l6ZQdfb3B0aW9uEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ1fcG9zaXRpb25TaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsAwkAAAIFB19vcHRpb24FD1BOTF9PUFRJT05fU1BPVAQTb3V0UG9zaXRpb25Ob3Rpb25hbAgJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzBwkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAJfMQUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJAQ5nZXRPcmFjbGVQcmljZQAFEHBvc2l0aW9uTm90aW9uYWwBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHDV9wb3NpdGlvblNpemUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0B19vcHRpb24DCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIVSW52YWxpZCBwb3NpdGlvbiBzaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsCQEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAYFDV9wb3NpdGlvblNpemUFB19vcHRpb24FEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0BA11bnJlYWxpemVkUG5sAwUHaXNTaG9ydAkAZQIFFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbAUQcG9zaXRpb25Ob3Rpb25hbAkAZQIFEHBvc2l0aW9uTm90aW9uYWwFFV9wb3NpdGlvbk9wZW5Ob3Rpb25hbAkAlAoCBRBwb3NpdGlvbk5vdGlvbmFsBQ11bnJlYWxpemVkUG5sASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAMHX3RyYWRlcgpfZGlyZWN0aW9uB19vcHRpb24EDSR0MDI5MTE0MjkyNTQJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24EDHBvc2l0aW9uU2l6ZQgFDSR0MDI5MTE0MjkyNTQCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwMjkxMTQyOTI1NAJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAyOTExNDI5MjU0Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDI5MTE0MjkyNTQCXzQJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUMcG9zaXRpb25TaXplBRRwb3NpdGlvbk9wZW5Ob3Rpb25hbAkBBnF0QXN0UgAJAQZxdEFzdFcACQEGYnNBc3RSAAkBBmJzQXN0VwAFB19vcHRpb24BD2NhbGNNYXJnaW5SYXRpbwMNX3JlbWFpbk1hcmdpbghfYmFkRGVidBFfcG9zaXRpb25Ob3Rpb25hbAkBBGRpdmQCCQBlAgUNX3JlbWFpbk1hcmdpbgUIX2JhZERlYnQFEV9wb3NpdGlvbk5vdGlvbmFsARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAwdfdHJhZGVyCl9kaXJlY3Rpb24HX29wdGlvbgQNJHQwMjk3ODYyOTkzOQkBC2dldFBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgQMcG9zaXRpb25TaXplCAUNJHQwMjk3ODYyOTkzOQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyOTc4NjI5OTM5Al8yBANwb24IBQ0kdDAyOTc4NjI5OTM5Al8zBBZwb3NpdGlvbkxhc3RVcGRhdGVkQ1BGCAUNJHQwMjk3ODYyOTkzOQJfNAQRcG9zaXRpb25UaW1lc3RhbXAIBQ0kdDAyOTc4NjI5OTM5Al81BA0kdDAyOTk0NTMwMDUwCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwDBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQdfb3B0aW9uBBBwb3NpdGlvbk5vdGlvbmFsCAUNJHQwMjk5NDUzMDA1MAJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDI5OTQ1MzAwNTACXzIEDSR0MDMwMDU1MzAyNjcJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRZwb3NpdGlvbkxhc3RVcGRhdGVkQ1BGBRFwb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMzAwNTUzMDI2NwJfMQQHYmFkRGVidAgFDSR0MDMwMDU1MzAyNjcCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAgdfdHJhZGVyCl9kaXJlY3Rpb24JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAwUHX3RyYWRlcgUKX2RpcmVjdGlvbgUPUE5MX09QVElPTl9TUE9UARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCB190cmFkZXINX3Bvc2l0aW9uU2l6ZQQMbWF4aW11bVJhdGlvCQEEdm1heAIJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwAJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgkBDmdldE1hcmdpblJhdGlvAgUHX3RyYWRlcgkBDGdldERpcmVjdGlvbgEFDV9wb3NpdGlvblNpemUJARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAQYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplBQxtYXhpbXVtUmF0aW8ECnN3YXBSZXN1bHQJAQpzd2FwT3V0cHV0AwkAZgIFDV9wb3NpdGlvblNpemUAAAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplBwQcbWF4RXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFCnN3YXBSZXN1bHQCXzEEC3ByaWNlSW1wYWN0CAUKc3dhcFJlc3VsdAJfNwMJAGYCCQEObWF4UHJpY2VJbXBhY3QABQtwcmljZUltcGFjdAUYbWF4RXhjaGFuZ2VkUG9zaXRpb25TaXplCQEEbXVsZAIJAQNhYnMBBQ1fcG9zaXRpb25TaXplCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AARVpbnRlcm5hbENsb3NlUG9zaXRpb24IB190cmFkZXIKX2RpcmVjdGlvbgVfc2l6ZQRfZmVlFF9taW5RdW90ZUFzc2V0QW1vdW50DF9hZGRUb01hcmdpbhRfY2hlY2tNYXhQcmljZUltcGFjdApfbGlxdWlkYXRlBA0kdDAzMTQzMDMxNTk4CQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBA9vbGRQb3NpdGlvblNpemUIBQ0kdDAzMTQzMDMxNTk4Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDMxNDMwMzE1OTgCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMzE0MzAzMTU5OAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAzMTQzMDMxNTk4Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDMxNDMwMzE1OTgCXzUEDmlzTG9uZ1Bvc2l0aW9uCQBmAgUPb2xkUG9zaXRpb25TaXplAAAEEmFic09sZFBvc2l0aW9uU2l6ZQkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQMDCQBnAgUSYWJzT2xkUG9zaXRpb25TaXplBQVfc2l6ZQkAZgIFBV9zaXplAAAHBA5pc1BhcnRpYWxDbG9zZQkAZgIFEmFic09sZFBvc2l0aW9uU2l6ZQUFX3NpemUEDSR0MDMxODkwMzIzNDEJAQpzd2FwT3V0cHV0AwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQVfc2l6ZQUUX2NoZWNrTWF4UHJpY2VJbXBhY3QEGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQIBQ0kdDAzMTg5MDMyMzQxAl8xBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzE4OTAzMjM0MQJfMgQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzE4OTAzMjM0MQJfMwQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDMxODkwMzIzNDECXzQEFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMJAGYCBQ9vbGRQb3NpdGlvblNpemUAAAkBAS0BBQVfc2l6ZQUFX3NpemUEDSR0MDMyNTU2MzI3ODAJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAMFB190cmFkZXIFCl9kaXJlY3Rpb24FD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDMyNTU2MzI3ODACXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDAzMjU1NjMyNzgwAl8yBA1yZWFsaXplZFJhdGlvCQEEZGl2ZAIJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUFEmFic09sZFBvc2l0aW9uU2l6ZQQLcmVhbGl6ZWRQbmwJAQRtdWxkAgUNdW5yZWFsaXplZFBubAUNcmVhbGl6ZWRSYXRpbwQNJHQwMzMxMjEzMzM2NwkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQScmVtYWluTWFyZ2luQmVmb3JlCAUNJHQwMzMxMjEzMzM2NwJfMQQCeDEIBQ0kdDAzMzEyMTMzMzY3Al8yBAJ4MggFDSR0MDMzMTIxMzMzNjcCXzMEC3JvbGxvdmVyRmVlCAUNJHQwMzMxMjEzMzM2NwJfNAQPcG9zaXRpb25CYWREZWJ0CAkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAULcmVhbGl6ZWRQbmwCXzIEEHJlYWxpemVkQ2xvc2VGZWUJAQRtdWxkAgkBBG11bGQCBRNvbGRQb3NpdGlvbk5vdGlvbmFsBQ1yZWFsaXplZFJhdGlvBQRfZmVlBBJ1bnJlYWxpemVkUG5sQWZ0ZXIJAGUCBQ11bnJlYWxpemVkUG5sBQtyZWFsaXplZFBubAQScmVtYWluT3Blbk5vdGlvbmFsAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkAZQIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAGQCBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFE29sZFBvc2l0aW9uTm90aW9uYWwFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplBA0kdDAzNDc3MzM1MTU5AwkAAAIFD25ld1Bvc2l0aW9uU2l6ZQAACQCUCgIAAAAACQCUCgIJAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDM0NzczMzUxNTkCXzEEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMzQ3NzMzNTE1OQJfMgQRb3Blbk5vdGlvbmFsRGVsdGEJAGUCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwEC21hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgMFB190cmFkZXIFCl9kaXJlY3Rpb24FD1BOTF9PUFRJT05fU1BPVAQebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQBlAgkBBG11bGQCCQBkAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgULbWFyZ2luUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIJAQRtdWxkAgkAZQIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFC21hcmdpblJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIEEW1hcmdpblRvVHJhZGVyUmF3CQBlAgkAZQIFEnJlbWFpbk1hcmdpbkJlZm9yZQkAZAIFHm5ld1Bvc2l0aW9uTWFyZ2luV2l0aFNhbWVSYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyBRByZWFsaXplZENsb3NlRmVlBA5tYXJnaW5Ub1RyYWRlcgMJAGYCAAAFEW1hcmdpblRvVHJhZGVyUmF3AwUKX2xpcXVpZGF0ZQAACQACAQI3SW52YWxpZCBpbnRlcm5hbENsb3NlUG9zaXRpb24gcGFyYW1zOiB1bmFibGUgdG8gcGF5IGZlZQURbWFyZ2luVG9UcmFkZXJSYXcEEW5ld1Bvc2l0aW9uTWFyZ2luAwUMX2FkZFRvTWFyZ2luCQBkAgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvBQ5tYXJnaW5Ub1RyYWRlcgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvAwMJAQIhPQIFFF9taW5RdW90ZUFzc2V0QW1vdW50AAAJAGYCBRRfbWluUXVvdGVBc3NldEFtb3VudAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQCAyA8IAkApAMBBRRfbWluUXVvdGVBc3NldEFtb3VudAkAowoRBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYFD3Bvc2l0aW9uQmFkRGVidAULcmVhbGl6ZWRQbmwDAwUMX2FkZFRvTWFyZ2luBQ5pc1BhcnRpYWxDbG9zZQcAAAUObWFyZ2luVG9UcmFkZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgkAZQIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFEW9wZW5Ob3Rpb25hbERlbHRhCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQ5pc0xvbmdQb3NpdGlvbgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkBASEBBQ5pc0xvbmdQb3NpdGlvbgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQBlAgkBEG9wZW5JbnRlcmVzdExvbmcAAwUOaXNMb25nUG9zaXRpb24FEW9wZW5Ob3Rpb25hbERlbHRhAAAJAGUCCQERb3BlbkludGVyZXN0U2hvcnQAAwkBASEBBQ5pc0xvbmdQb3NpdGlvbgURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZAIFEHJlYWxpemVkQ2xvc2VGZWUFC3JvbGxvdmVyRmVlBRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgI9SW52YWxpZCBpbnRlcm5hbENsb3NlUG9zaXRpb24gcGFyYW1zOiBpbnZhbGlkIHBvc2l0aW9uIHNpemU6IAkApAMBBQVfc2l6ZQIGIG1heDogCQCkAwEFEmFic09sZFBvc2l0aW9uU2l6ZQETZ2V0VGVybWluYWxBbW1TdGF0ZQAEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQCUCgIJAQZxdEFzdFIACQEGYnNBc3RSAAQJZGlyZWN0aW9uCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABA0kdDAzODQwNjM4NTg1CQEKc3dhcE91dHB1dAMFCWRpcmVjdGlvbgkBA2FicwEFDV9wb3NpdGlvblNpemUHBBVjdXJyZW50TmV0TWFya2V0VmFsdWUIBQ0kdDAzODQwNjM4NTg1Al8xBBl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlCAUNJHQwMzg0MDYzODU4NQJfMgQYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCAUNJHQwMzg0MDYzODU4NQJfMwkAlAoCBRl0ZXJtaW5hbFF1b3RlQXNzZXRSZXNlcnZlBRh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUBE2dldFF1b3RlQXNzZXRXZWlnaHQEEGJhc2VBc3NldFJlc2VydmURdG90YWxQb3NpdGlvblNpemURcXVvdGVBc3NldFJlc2VydmULdGFyZ2V0UHJpY2UEAWIJALYCAQUQYmFzZUFzc2V0UmVzZXJ2ZQQCc3oJALYCAQURdG90YWxQb3NpdGlvblNpemUEAXEJALYCAQURcXVvdGVBc3NldFJlc2VydmUEAXAJALYCAQULdGFyZ2V0UHJpY2UEAWsJAQVibXVsZAIFAXEFAWIEBG5ld0IJALcCAgUBYgUCc3oEBG5ld1EJAQViZGl2ZAIFAWsFBG5ld0IEAXoJAQViZGl2ZAIFBG5ld1EFBG5ld0IEBnJlc3VsdAkBBWJkaXZkAgUBcAUBegkAoAMBBQZyZXN1bHQBFGdldFN5bmNUZXJtaW5hbFByaWNlAw5fdGVybWluYWxQcmljZQdfcXRBc3RSB19ic0FzdFIEDV9wb3NpdGlvblNpemUJARF0b3RhbFBvc2l0aW9uU2l6ZQADCQAAAgUNX3Bvc2l0aW9uU2l6ZQAABAluZXdRdEFzdFcJAQRkaXZkAgkBBG11bGQCBQ5fdGVybWluYWxQcmljZQUHX2JzQXN0UgUHX3F0QXN0UgkAlQoDBQluZXdRdEFzdFcFDERFQ0lNQUxfVU5JVAAABAlkaXJlY3Rpb24JAGYCBQ1fcG9zaXRpb25TaXplAAAEFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQgJAQpzd2FwT3V0cHV0AwUJZGlyZWN0aW9uCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQcCXzEECW5ld1F0QXN0VwkBE2dldFF1b3RlQXNzZXRXZWlnaHQEBQdfYnNBc3RSBQ1fcG9zaXRpb25TaXplBQdfcXRBc3RSBQ5fdGVybWluYWxQcmljZQQJbmV3QnNBc3RXBQxERUNJTUFMX1VOSVQEDW1hcmdpblRvVmF1bHQICQErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcFDV9wb3NpdGlvblNpemUFFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQUHX3F0QXN0UgUJbmV3UXRBc3RXBQdfYnNBc3RSBQluZXdCc0FzdFcFD1BOTF9PUFRJT05fU1BPVAJfMgkAlQoDBQluZXdRdEFzdFcFCW5ld0JzQXN0VwUNbWFyZ2luVG9WYXVsdAEKZ2V0RnVuZGluZwAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQJc3BvdFByaWNlCQEMZ2V0U3BvdFByaWNlAAQHcHJlbWl1bQkAZQIFCXNwb3RQcmljZQUPdW5kZXJseWluZ1ByaWNlAwMJAQ5pc01hcmtldENsb3NlZAAGAwkAAAIJAQtmdW5kaW5nTW9kZQAFEkZVTkRJTkdfQVNZTU1FVFJJQwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAABwkAlQoDAAAAAAAAAwkAZgIAAAUHcHJlbWl1bQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZAwkAAAIJAQtmdW5kaW5nTW9kZQAFEkZVTkRJTkdfQVNZTU1FVFJJQwQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJARV0b3RhbExvbmdQb3NpdGlvblNpemUACQCVCgMFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAAAEGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAEGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUABA5wcmVtaXVtVG9WYXVsdAkAZQIFGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24FGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgkAlQoDBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FDnByZW1pdW1Ub1ZhdWx0BBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQMJAAACCQELZnVuZGluZ01vZGUABRJGVU5ESU5HX0FTWU1NRVRSSUMEFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkAlQoDBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgAABBhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUABBlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAEDnByZW1pdW1Ub1ZhdWx0CQBlAgUYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uBRlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uCQCVCgMFE2xvbmdQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24FDnByZW1pdW1Ub1ZhdWx0AQ5nZXRBZGp1c3RlZEZlZQILX2FydGlmYWN0SWQQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwNDMyNDk0Mzc0NAMJAQIhPQIFC19hcnRpZmFjdElkAgAEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFC19hcnRpZmFjdElkAwkAAAIFDGFydGlmYWN0S2luZAUYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFBAlyZWR1Y3Rpb24JAQRpbnRBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUNa190b2tlbl9wYXJhbQULX2FydGlmYWN0SWQEC2FkanVzdGVkRmVlCQEEbXVsZAIFB2Jhc2VGZWUFCXJlZHVjdGlvbgkAlAoCBQthZGp1c3RlZEZlZQYJAAIBAhlJbnZhbGlkIGF0dGFjaGVkIGFydGlmYWN0CQCUCgIFB2Jhc2VGZWUHBAthZGp1c3RlZEZlZQgFDSR0MDQzMjQ5NDM3NDQCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDQzMjQ5NDM3NDQCXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBBBkb0dldEZlZURpc2NvdW50CQD8BwQJAQxtaW5lckFkZHJlc3MAAhJjb21wdXRlRmVlRGlzY291bnQJAMwIAgUHX3RyYWRlcgUDbmlsBQNuaWwDCQAAAgUQZG9HZXRGZWVEaXNjb3VudAUQZG9HZXRGZWVEaXNjb3VudAQLZmVlRGlzY291bnQEByRtYXRjaDAFEGRvR2V0RmVlRGlzY291bnQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIhSW52YWxpZCBjb21wdXRlRmVlRGlzY291bnQgcmVzdWx0BA0kdDA0NDA5MDQ0MTY0CQEOZ2V0QWRqdXN0ZWRGZWUCBQtfYXJ0aWZhY3RJZAULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwNDQwOTA0NDE2NAJfMQQMYnVybkFydGlmYWN0CAUNJHQwNDQwOTA0NDE2NAJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1nZXRBcnRpZmFjdElkAQFpBAphcnRpZmFjdElkAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkA2AQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAISSW52YWxpZCBhcnRpZmFjdElkAgAFCmFydGlmYWN0SWQBDWRpc3RyaWJ1dGVGZWUBCl9mZWVBbW91bnQEDGZlZVRvU3Rha2VycwkBBG11bGQCBQpfZmVlQW1vdW50CQETZmVlVG9TdGFrZXJzUGVyY2VudAAECmZlZVRvVmF1bHQJAGUCBQpfZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMJAJQKAgUMZmVlVG9TdGFrZXJzBQpmZWVUb1ZhdWx0AQ51cGRhdGVTZXR0aW5ncxEQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5DF9yb2xsb3ZlckZlZQxfZnVuZGluZ01vZGULX29yYWNsZU1vZGUTX21pbkluaXRNYXJnaW5SYXRpbw1fcG9zaXRpb25Nb2RlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrX2luaXRNYXJnaW5SYXRpbwUQX2luaXRNYXJnaW5SYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUUa19taW5Jbml0TWFyZ2luUmF0aW8FE19taW5Jbml0TWFyZ2luUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwUEX21tcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19saXF1aWRhdGlvbkZlZVJhdGlvBRRfbGlxdWlkYXRpb25GZWVSYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa19mdW5kaW5nUGVyaW9kBQ5fZnVuZGluZ1BlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUFa19mZWUFBF9mZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfc3ByZWFkTGltaXQFDF9zcHJlYWRMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZUltcGFjdAUPX21heFByaWNlSW1wYWN0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRlrX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VTcHJlYWQFD19tYXhQcmljZVNwcmVhZAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19tYXhPcGVuTm90aW9uYWwFEF9tYXhPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfZmVlVG9TdGFrZXJzUGVyY2VudAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4T3JhY2xlRGVsYXkFD19tYXhPcmFjbGVEZWxheQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19yb2xsb3ZlckZlZQUMX3JvbGxvdmVyRmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX2Z1bmRpbmdNb2RlBQxfZnVuZGluZ01vZGUJAMwIAgkBDEludGVnZXJFbnRyeQIFDGtfb3JhY2xlTW9kZQULX29yYWNsZU1vZGUJAMwIAgkBDEludGVnZXJFbnRyeQIFDmtfcG9zaXRpb25Nb2RlBQ1fcG9zaXRpb25Nb2RlBQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXIDDl9pc05ld1Bvc2l0aW9uB190cmFkZXIKX2RpcmVjdGlvbgQLcG9zaXRpb25LZXkJAKwCAgkArAICBQdfdHJhZGVyAgFfCQCkAwEFCl9kaXJlY3Rpb24DBQ5faXNOZXdQb3NpdGlvbgQPY3VycmVudFNlcXVlbmNlCQEMbGFzdFNlcXVlbmNlAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUSa19wb3NpdGlvblNlcXVlbmNlBQtwb3NpdGlvbktleQkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQprX3NlcXVlbmNlCQBkAgUPY3VycmVudFNlcXVlbmNlAAEFA25pbAUDbmlsARF1cGRhdGVQb3NpdGlvbkZlZQQOX2lzTmV3UG9zaXRpb24HX3RyYWRlcgpfZGlyZWN0aW9uBF9mZWUEC3Bvc2l0aW9uS2V5CQCsAgIJAKwCAgUHX3RyYWRlcgIBXwkApAMBBQpfZGlyZWN0aW9uAwUOX2lzTmV3UG9zaXRpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFC3Bvc2l0aW9uS2V5BQRfZmVlBQNuaWwFA25pbAEOdXBkYXRlUG9zaXRpb24GB190cmFkZXIFX3NpemUHX21hcmdpbg1fb3Blbk5vdGlvbmFsIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sYXRlc3RUaW1lc3RhbXAECWRpcmVjdGlvbgkBDGdldERpcmVjdGlvbgEFBV9zaXplBAtwb3NpdGlvbktleQkArAICCQCsAgIFB190cmFkZXICAV8JAKQDAQUJZGlyZWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQULcG9zaXRpb25LZXkFBV9zaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQtwb3NpdGlvbktleQUHX21hcmdpbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAULcG9zaXRpb25LZXkFDV9vcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FC3Bvc2l0aW9uS2V5BSBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQtwb3NpdGlvbktleQUQX2xhdGVzdFRpbWVzdGFtcAUDbmlsARF1cGRhdGVBbW1SZXNlcnZlcwIHX3F0QXN0UgdfYnNBc3RSAwMJAGYCAAAFB19xdEFzdFIGCQBmAgAABQdfYnNBc3RSCQACAQIhSW52YWxpZCBhbW91bnQgdG8gdXBkYXRlIHJlc2VydmVzAwMJAQIhPQIFB19xdEFzdFIJAQdxdEFzdFIwAAYJAQIhPQIFB19ic0FzdFIJAQdic0FzdFIwAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa19xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUSa19iYXNlQXNzZXRSZXNlcnZlBQdfYnNBc3RSBQNuaWwFA25pbAEQdXBkYXRlQW1tV2VpZ2h0cwIHX3F0QXN0VwdfYnNBc3RXAwMJAQIhPQIFB19xdEFzdFcJAQZxdEFzdFcABgkBAiE9AgUHX2JzQXN0VwkBBmJzQXN0VwAJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfcXVvdGVBc3NldFdlaWdodAUHX3F0QXN0VwkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19iYXNlQXNzZXRXZWlnaHQFB19ic0FzdFcFA25pbAUDbmlsAQl1cGRhdGVBbW0IB19xdEFzdFIHX2JzQXN0UhdfdG90YWxQb3NpdGlvblNpemVBZnRlchVfb3BlbkludGVyZXN0Tm90aW9uYWwWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZRZfdG90YWxMb25nT3Blbk5vdGlvbmFsF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwADCQECIT0CCQBlAgUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGEludmFsaWQgQU1NIHN0YXRlIGRhdGE6IAkApAMBBRZfdG90YWxMb25nUG9zaXRpb25TaXplAgQgLSAgCQCkAwEFF190b3RhbFNob3J0UG9zaXRpb25TaXplAgQgIT0gCQCkAwEFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX29wZW5JbnRlcmVzdExvbmcFFl90b3RhbExvbmdPcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfb3BlbkludGVyZXN0U2hvcnQFF190b3RhbFNob3J0T3Blbk5vdGlvbmFsBQNuaWwBDmRlbGV0ZVBvc2l0aW9uAgdfdHJhZGVyCl9kaXJlY3Rpb24EC3Bvc2l0aW9uS2V5CQCsAgIJAKwCAgUHX3RyYWRlcgIBXwkApAMBBQpfZGlyZWN0aW9uCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQtwb3NpdGlvbktleQkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQtwb3NpdGlvbktleQkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQtwb3NpdGlvbktleQkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQtwb3NpdGlvbktleQkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQtwb3NpdGlvbktleQkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFC3Bvc2l0aW9uS2V5BQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEIX2JhbGFuY2UDCQBmAgAABQhfYmFsYW5jZQkAAgECB0JhbGFuY2UDAwkAAAIJAQljYmFsYW5jZTAAAAAGCQECIT0CCQEJY2JhbGFuY2UwAAUIX2JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUIX2JhbGFuY2UFA25pbAUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbBcBaQEFcGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFEludmFsaWQgcGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAYFA25pbAFpAQd1bnBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIHVucGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAcFA25pbAFpAQxzZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECG0ludmFsaWQgc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkGBQNuaWwBaQEOdW5zZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgdW5zZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQcFA25pbAFpAQ9jaGFuZ2VMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQAAAgURX3F1b3RlQXNzZXRBbW91bnQAAAkAAgECHkludmFsaWQgY2hhbmdlTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBRiYXNlQXNzZXRBbW91bnRUb0FkZAkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBkAgUHX2JzQXN0UgUUYmFzZUFzc2V0QW1vdW50VG9BZGQEDSR0MDUzMDQ5NTMyMDAJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDUzMDQ5NTMyMDACXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDUzMDQ5NTMyMDACXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA1MzA0OTUzMjAwAl8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmNoYW5nZVNldHRpbmdzExBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQtfb3JhY2xlTW9kZQ9fYmFzZU9yYWNsZURhdGEQX3F1b3RlT3JhY2xlRGF0YRNfbWluSW5pdE1hcmdpblJhdGlvDV9wb3NpdGlvbk1vZGUDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBmAgUQX2luaXRNYXJnaW5SYXRpbwUMREVDSU1BTF9VTklUBgkAZwIAAAUTX21pbkluaXRNYXJnaW5SYXRpbwYJAGYCBRBfaW5pdE1hcmdpblJhdGlvBRNfbWluSW5pdE1hcmdpblJhdGlvBgkAZwIAAAUEX21tcgYJAGcCAAAFFF9saXF1aWRhdGlvbkZlZVJhdGlvBgkAZwIAAAUEX2ZlZQYJAGcCAAAFDF9zcHJlYWRMaW1pdAYJAGcCAAAFD19tYXhQcmljZUltcGFjdAYJAGcCAAAFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwYJAGcCAAAFD19tYXhQcmljZVNwcmVhZAYJAGcCAAAFEF9tYXhPcGVuTm90aW9uYWwGCQBnAgAABRRfZmVlVG9TdGFrZXJzUGVyY2VudAYJAGYCBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUMREVDSU1BTF9VTklUBgkAZgIAAAUPX21heE9yYWNsZURlbGF5BgkAZwIAAAUMX3JvbGxvdmVyRmVlBgMJAQIhPQIFDF9mdW5kaW5nTW9kZQURRlVORElOR19TWU1NRVRSSUMJAQIhPQIFDF9mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDBwYDCQECIT0CBQtfb3JhY2xlTW9kZQUMT1JBQ0xFX1BMQUlOCQECIT0CBQtfb3JhY2xlTW9kZQUKT1JBQ0xFX0pJVAcGAwkBAiE9AgUNX3Bvc2l0aW9uTW9kZQUPUE9TSVRJT05fRElSRUNUCQECIT0CBQ1fcG9zaXRpb25Nb2RlBQ5QT1NJVElPTl9PUkRFUgcGCQEBIQEJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIdSW52YWxpZCBjaGFuZ2VTZXR0aW5ncyBwYXJhbXMJAM4IAgkBDnVwZGF0ZVNldHRpbmdzEQUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQFEF9tYXhPcGVuTm90aW9uYWwFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQ9fbWF4T3JhY2xlRGVsYXkFDF9yb2xsb3ZlckZlZQUMX2Z1bmRpbmdNb2RlBQtfb3JhY2xlTW9kZQUTX21pbkluaXRNYXJnaW5SYXRpbwUNX3Bvc2l0aW9uTW9kZQkAzAgCCQELU3RyaW5nRW50cnkCBQxrX2Jhc2VPcmFjbGUFD19iYXNlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX3F1b3RlT3JhY2xlBRBfcXVvdGVPcmFjbGVEYXRhBQNuaWwBaQEKaW5pdGlhbGl6ZRYHX3F0QXN0UgdfYnNBc3RSDl9mdW5kaW5nUGVyaW9kEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbwRfZmVlD19iYXNlT3JhY2xlRGF0YRBfcXVvdGVPcmFjbGVEYXRhDF9jb29yZGluYXRvcgxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQtfb3JhY2xlTW9kZRNfbWluSW5pdE1hcmdpblJhdGlvDV9wb3NpdGlvbk1vZGUDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMJAGcCAAAFB19xdEFzdFIGCQBnAgAABQdfYnNBc3RSBgkAZwIAAAUOX2Z1bmRpbmdQZXJpb2QGCQBnAgAABRBfaW5pdE1hcmdpblJhdGlvBgkAZgIFEF9pbml0TWFyZ2luUmF0aW8FDERFQ0lNQUxfVU5JVAYJAGcCAAAFE19taW5Jbml0TWFyZ2luUmF0aW8GCQBmAgUQX2luaXRNYXJnaW5SYXRpbwUTX21pbkluaXRNYXJnaW5SYXRpbwYJAGcCAAAFBF9tbXIGCQBnAgAABRRfbGlxdWlkYXRpb25GZWVSYXRpbwYJAGcCAAAFBF9mZWUGCQBnAgAABQxfc3ByZWFkTGltaXQGCQBnAgAABQ9fbWF4UHJpY2VJbXBhY3QGCQBnAgAABRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8GCQBnAgAABQ9fbWF4UHJpY2VTcHJlYWQGCQBnAgAABRBfbWF4T3Blbk5vdGlvbmFsBgkAZwIAAAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQGCQBmAgUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFDERFQ0lNQUxfVU5JVAYJAGYCAAAFD19tYXhPcmFjbGVEZWxheQYJAGcCAAAFDF9yb2xsb3ZlckZlZQYDCQECIT0CBQxfZnVuZGluZ01vZGUFEUZVTkRJTkdfU1lNTUVUUklDCQECIT0CBQxfZnVuZGluZ01vZGUFEkZVTkRJTkdfQVNZTU1FVFJJQwcGAwkBAiE9AgULX29yYWNsZU1vZGUFDE9SQUNMRV9QTEFJTgkBAiE9AgULX29yYWNsZU1vZGUFCk9SQUNMRV9KSVQHBgMJAQIhPQIFDV9wb3NpdGlvbk1vZGUFD1BPU0lUSU9OX0RJUkVDVAkBAiE9AgUNX3Bvc2l0aW9uTW9kZQUOUE9TSVRJT05fT1JERVIHBgkBC2luaXRpYWxpemVkAAYJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECHUludmFsaWQgaW5pdGlhbGl6ZSBwYXJhbWV0ZXJzCQDOCAIJAM4IAgkAzggCCQDOCAIJAQl1cGRhdGVBbW0IBQdfcXRBc3RSBQdfYnNBc3RSAAAAAAAAAAAAAAAACQEOdXBkYXRlU2V0dGluZ3MRBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQUMX3JvbGxvdmVyRmVlBQxfZnVuZGluZ01vZGUFC19vcmFjbGVNb2RlBRNfbWluSW5pdE1hcmdpblJhdGlvBQ1fcG9zaXRpb25Nb2RlCQENdXBkYXRlRnVuZGluZwUJAGQCCQENbGFzdFRpbWVzdGFtcAAFDl9mdW5kaW5nUGVyaW9kAAAAAAAAAAAJAQ11cGRhdGVCYWxhbmNlAQAACQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rX2luaXRpYWxpemVkBgkAzAgCCQELU3RyaW5nRW50cnkCBQxrX2Jhc2VPcmFjbGUFD19iYXNlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX3F1b3RlT3JhY2xlBRBfcXVvdGVPcmFjbGVEYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDF9jb29yZGluYXRvcgUDbmlsAWkBEGluY3JlYXNlUG9zaXRpb24FCl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsMX3ByaWNlVXBkYXRlBAx1cGRhdGVPcmFjbGUJAPwHBAUEdGhpcwIMdXBkYXRlT3JhY2xlCQDMCAIFDF9wcmljZVVwZGF0ZQUDbmlsBQNuaWwDCQAAAgUMdXBkYXRlT3JhY2xlBQx1cGRhdGVPcmFjbGUEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwMDAwMJAQIhPQIFCl9kaXJlY3Rpb24FCERJUl9MT05HCQECIT0CBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQHBgkAZwIAAAUKX3Jhd0Ftb3VudAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQUMaXNRdW90ZUFzc2V0BgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQESbWluSW5pdE1hcmdpblJhdGlvAAcGCQEBIQEJASFyZXF1aXJlU2VuZGVyQ2FuV29ya1dpdGhQb3NpdGlvbnMBCAUBaQZjYWxsZXIGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgaW5jcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA2MDQ2MzYwNjEyCQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgkBDWdldEFydGlmYWN0SWQBBQFpBAthZGp1c3RlZEZlZQgFDSR0MDYwNDYzNjA2MTICXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDYwNDYzNjA2MTICXzIEB19hbW91bnQJAQRkaXZkAgUKX3Jhd0Ftb3VudAkAZAIJAQRtdWxkAgULYWRqdXN0ZWRGZWUFCV9sZXZlcmFnZQUMREVDSU1BTF9VTklUBBNkaXN0cmlidXRlRmVlQW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUHX2Ftb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACFWFjY2VwdFBheW1lbnRXaXRoTGluawkAzAgCBQdfdHJhZGVyCQDMCAIFCF9yZWZMaW5rBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA2MTEwODYxMjg4CQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2MTEwODYxMjg4Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDYxMTA4NjEyODgCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjExMDg2MTI4OAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2MTEwODYxMjg4Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDYxMTA4NjEyODgCXzUEDWlzTmV3UG9zaXRpb24JAAACBQ9vbGRQb3NpdGlvblNpemUAAAQPaXNTYW1lRGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAAACBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQEDmV4cGFuZEV4aXN0aW5nAwkBASEBBQ1pc05ld1Bvc2l0aW9uBQ9pc1NhbWVEaXJlY3Rpb24HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA2MTU3NzY0NzEwAwMFDWlzTmV3UG9zaXRpb24GBQ5leHBhbmRFeGlzdGluZwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNjIwODY2MjI1OQkBCXN3YXBJbnB1dAIFBWlzQWRkBQxvcGVuTm90aW9uYWwEFWFtb3VudEJhc2VBc3NldEJvdWdodAgFDSR0MDYyMDg2NjIyNTkCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2MjA4NjYyMjU5Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2MjA4NjYyMjU5Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjIwODY2MjI1OQJfNAMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50CQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAIDIDwgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUMb3Blbk5vdGlvbmFsAAAEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAABA0kdDA2MjgwNTYzMDgwCQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA2MjgwNTYzMDgwAl8xBAJ4MQgFDSR0MDYyODA1NjMwODACXzIEAngyCAUNJHQwNjI4MDU2MzA4MAJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA2MjgwNTYzMDgwAl80AwkBASEBCQEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAAgECFU92ZXIgbWF4IHNwcmVhZCBsaW1pdAMJAQEhAQkBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECFk92ZXIgbWF4IG9wZW4gbm90aW9uYWwJAKAKDgUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAGQCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQkBDWxhc3RUaW1lc3RhbXAABRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIFC3JvbGxvdmVyRmVlBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA2NDM5ODY0NTI2CQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwDCQClCAEIBQFpBmNhbGxlcgUKX2RpcmVjdGlvbgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNjQzOTg2NDUyNgJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDY0Mzk4NjQ1MjYCXzIDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQACAQIuVXNlIGRlY3JlYXNlUG9zaXRpb24gdG8gZGVjcmVhc2UgcG9zaXRpb24gc2l6ZQkAAgECFENsb3NlIHBvc2l0aW9uIGZpcnN0BA9uZXdQb3NpdGlvblNpemUIBQ0kdDA2MTU3NzY0NzEwAl8xBBduZXdQb3NpdGlvblJlbWFpbk1hcmdpbggFDSR0MDYxNTc3NjQ3MTACXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjE1Nzc2NDcxMAJfMwQUbmV3UG9zaXRpb25MYXRlc3RDUEYIBQ0kdDA2MTU3NzY0NzEwAl80BBRuZXdQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDYxNTc3NjQ3MTACXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDYxNTc3NjQ3MTACXzYEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2MTU3NzY0NzEwAl83BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjE1Nzc2NDcxMAJfOAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDYxNTc3NjQ3MTACXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNjE1Nzc2NDcxMANfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDYxNTc3NjQ3MTADXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDYxNTc3NjQ3MTADXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA2MTU3NzY0NzEwA18xMwQLcm9sbG92ZXJGZWUIBQ0kdDA2MTU3NzY0NzEwA18xNAQNJHQwNjQ3MTY2NDc4NwkBDWRpc3RyaWJ1dGVGZWUBCQBkAgUJZmVlQW1vdW50BQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjQ3MTY2NDc4NwJfMQQKZmVlVG9WYXVsdAgFDSR0MDY0NzE2NjQ3ODcCXzIEBXN0YWtlAwkAZwIFB19hbW91bnQFC3JvbGxvdmVyRmVlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQBlAgUHX2Ftb3VudAULcm9sbG92ZXJGZWUFA25pbAkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgkAZQIFC3JvbGxvdmVyRmVlBQdfYW1vdW50BQNuaWwFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGBRRuZXdQb3NpdGlvblRpbWVzdGFtcAkBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXIDBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyBQpfZGlyZWN0aW9uCQERdXBkYXRlUG9zaXRpb25GZWUEBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQthZGp1c3RlZEZlZQkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQENdXBkYXRlQmFsYW5jZQEJAGUCCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRNYXJnaW4CCl9kaXJlY3Rpb24MX3ByaWNlVXBkYXRlBAx1cGRhdGVPcmFjbGUJAPwHBAUEdGhpcwIMdXBkYXRlT3JhY2xlCQDMCAIFDF9wcmljZVVwZGF0ZQUDbmlsBQNuaWwDCQAAAgUMdXBkYXRlT3JhY2xlBQx1cGRhdGVPcmFjbGUEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgQHX2Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgIJAKUIAQgFAWkGY2FsbGVyBQpfZGlyZWN0aW9uBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjcxMjk2NzMwOQkBC2dldFBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjcxMjk2NzMwOQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2NzEyOTY3MzA5Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY3MTI5NjczMDkCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjcxMjk2NzMwOQJfNAQUb2xkUG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA2NzEyOTY3MzA5Al81BAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQNJHQwNjc0NDk2NzY3NQkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAUHX2Ftb3VudAQMcmVtYWluTWFyZ2luCAUNJHQwNjc0NDk2NzY3NQJfMQQHYmFkRGVidAgFDSR0MDY3NDQ5Njc2NzUCXzIEC3JvbGxvdmVyRmVlCAUNJHQwNjc0NDk2NzY3NQJfMwQLbWFyZ2luUmF0aW8JAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBA5jaGVja01pbk1hcmdpbgkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBEm1pbkluaXRNYXJnaW5SYXRpbwAHAwkAAAIFDmNoZWNrTWluTWFyZ2luBQ5jaGVja01pbk1hcmdpbgQWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwMJAGYCBQtyb2xsb3ZlckZlZQAABA0kdDA2NzkzMTY3OTkwCQENZGlzdHJpYnV0ZUZlZQEFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2NzkzMTY3OTkwAl8xBApmZWVUb1ZhdWx0CAUNJHQwNjc5MzE2Nzk5MAJfMgQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUMZmVlVG9TdGFrZXJzBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUKZmVlVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0CQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPb2xkUG9zaXRpb25TaXplCQBkAgkAZQIFEW9sZFBvc2l0aW9uTWFyZ2luBQtyb2xsb3ZlckZlZQUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAGQCCQEIY2JhbGFuY2UABQdfYW1vdW50BQtyb2xsb3ZlckZlZQUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxyZW1vdmVNYXJnaW4DB19hbW91bnQKX2RpcmVjdGlvbgxfcHJpY2VVcGRhdGUEDHVwZGF0ZU9yYWNsZQkA/AcEBQR0aGlzAgx1cGRhdGVPcmFjbGUJAMwIAgUMX3ByaWNlVXBkYXRlBQNuaWwFA25pbAMJAAACBQx1cGRhdGVPcmFjbGUFDHVwZGF0ZU9yYWNsZQQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBBBlbnN1cmVDYWxsZWRPbmNlCQD8BwQFBHRoaXMCEGVuc3VyZUNhbGxlZE9uY2UFA25pbAUDbmlsAwkAAAIFEGVuc3VyZUNhbGxlZE9uY2UFEGVuc3VyZUNhbGxlZE9uY2UEB190cmFkZXIJAKUIAQgFAWkGY2FsbGVyAwMDAwMJAGcCAAAFB19hbW91bnQGCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECH0ludmFsaWQgcmVtb3ZlTWFyZ2luIHBhcmFtZXRlcnMEDSR0MDY5NDkxNjk2NzEJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24ED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDY5NDkxNjk2NzECXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwNjk0OTE2OTY3MQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA2OTQ5MTY5NjcxAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDY5NDkxNjk2NzECXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwNjk0OTE2OTY3MQJfNQQNJHQwNjk2Nzc2OTkyNgkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFD29sZFBvc2l0aW9uU2l6ZQURb2xkUG9zaXRpb25NYXJnaW4FFG9sZFBvc2l0aW9uTHN0VXBkQ1BGBRRvbGRQb3NpdGlvblRpbWVzdGFtcAkBAS0BBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA2OTY3NzY5OTI2Al8xBAdiYWREZWJ0CAUNJHQwNjk2Nzc2OTkyNgJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA2OTY3NzY5OTI2Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDY5Njc3Njk5MjYCXzQDCQECIT0CBQdiYWREZWJ0AAAJAAIBAh1JbnZhbGlkIHJlbW92ZWQgbWFyZ2luIGFtb3VudAQLbWFyZ2luUmF0aW8JAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEPaW5pdE1hcmdpblJhdGlvAAYJAAIBCQCsAgIJAKwCAgkArAICAhlUb28gbXVjaCBtYXJnaW4gcmVtb3ZlZDogCQCkAwEFC21hcmdpblJhdGlvAgMgPCAJAKQDAQkBD2luaXRNYXJnaW5SYXRpbwAEDSR0MDcwMzEyNzAzNzEJAQ1kaXN0cmlidXRlRmVlAQULcm9sbG92ZXJGZWUEDGZlZVRvU3Rha2VycwgFDSR0MDcwMzEyNzAzNzECXzEECmZlZVRvVmF1bHQIBQ0kdDA3MDMxMjcwMzcxAl8yBBZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzAwkAZgIFC3JvbGxvdmVyRmVlAAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQpmZWVUb1ZhdWx0BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQJAQt0cmFuc2ZlckZlZQEFDGZlZVRvU3Rha2VycwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIJAGQCBQdfYW1vdW50BQxmZWVUb1N0YWtlcnMFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9vbGRQb3NpdGlvblNpemUJAQ1sYXN0VGltZXN0YW1wAAkBCHdpdGhkcmF3AggFAWkGY2FsbGVyBQdfYW1vdW50CQENdXBkYXRlQmFsYW5jZQEJAGUCCQBlAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY2xvc2VQb3NpdGlvbgUFX3NpemUKX2RpcmVjdGlvbhRfbWluUXVvdGVBc3NldEFtb3VudAxfYWRkVG9NYXJnaW4MX3ByaWNlVXBkYXRlBAx1cGRhdGVPcmFjbGUJAPwHBAUEdGhpcwIMdXBkYXRlT3JhY2xlCQDMCAIFDF9wcmljZVVwZGF0ZQUDbmlsBQNuaWwDCQAAAgUMdXBkYXRlT3JhY2xlBQx1cGRhdGVPcmFjbGUEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQOX3RyYWRlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQdfdHJhZGVyAg5JbnZhbGlkIGNhbGxlcgQLcG9zaXRpb25GZWUJAQ5nZXRQb3NpdGlvbkZlZQIFB190cmFkZXIFCl9kaXJlY3Rpb24DAwMDAwMJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQBnAgAABQVfc2l6ZQYJAGYCAAAFFF9taW5RdW90ZUFzc2V0QW1vdW50BgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECIEludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBBRvbGRQb3NpdGlvblRpbWVzdGFtcAgJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24CXzUEDSR0MDcyNzA2NzMzMDkJARVpbnRlcm5hbENsb3NlUG9zaXRpb24IBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQVfc2l6ZQULcG9zaXRpb25GZWUFFF9taW5RdW90ZUFzc2V0QW1vdW50BQxfYWRkVG9NYXJnaW4GBgQPbmV3UG9zaXRpb25TaXplCAUNJHQwNzI3MDY3MzMwOQJfMQQRbmV3UG9zaXRpb25NYXJnaW4IBQ0kdDA3MjcwNjczMzA5Al8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDcyNzA2NzMzMDkCXzMEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNzI3MDY3MzMwOQJfNAQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNzI3MDY3MzMwOQJfNQQLcmVhbGl6ZWRQbmwIBQ0kdDA3MjcwNjczMzA5Al82BA5tYXJnaW5Ub1RyYWRlcggFDSR0MDcyNzA2NzMzMDkCXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MjcwNjczMzA5Al84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3MjcwNjczMzA5Al85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzI3MDY3MzMwOQNfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3MjcwNjczMzA5A18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA3MjcwNjczMzA5A18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNzI3MDY3MzMwOQNfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzI3MDY3MzMwOQNfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDcyNzA2NzMzMDkDXzE1BAtyZWFsaXplZEZlZQgFDSR0MDcyNzA2NzMzMDkDXzE2AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAACQACAQIqSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnM6IGJhZCBkZWJ0AwkAZwIFFG9sZFBvc2l0aW9uVGltZXN0YW1wCQENbGFzdFRpbWVzdGFtcAAJAAIBAlNJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVyczogd2FpdCBhdCBsZWFzdCAxIGJsb2NrIGJlZm9yZSBjbG9zaW5nIHRoZSBwb3NpdGlvbgQOaXNQYXJ0aWFsQ2xvc2UJAQIhPQIFD25ld1Bvc2l0aW9uU2l6ZQAABA53aXRoZHJhd0Ftb3VudAkAZAIFDm1hcmdpblRvVHJhZGVyBQtyZWFsaXplZEZlZQQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFDndpdGhkcmF3QW1vdW50BA1hbW1OZXdCYWxhbmNlAwkAZgIAAAUKYW1tQmFsYW5jZQAABQphbW1CYWxhbmNlBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCBQ53aXRoZHJhd0Ftb3VudAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACDWFjY2VwdFBheW1lbnQJAMwIAgUHX3RyYWRlcgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFC3JlYWxpemVkRmVlBQNuaWwDCQAAAgUOcmVmZXJyZXJGZWVBbnkFDnJlZmVycmVyRmVlQW55BAtyZWZlcnJlckZlZQQHJG1hdGNoMAUOcmVmZXJyZXJGZWVBbnkDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQITSW52YWxpZCByZWZlcnJlckZlZQQNJHQwNzQyODE3NDM1NAkBDWRpc3RyaWJ1dGVGZWUBCQBlAgULcmVhbGl6ZWRGZWUFC3JlZmVycmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA3NDI4MTc0MzU0Al8xBApmZWVUb1ZhdWx0CAUNJHQwNzQyODE3NDM1NAJfMgQMZGVwb3NpdFZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFDGRlcG9zaXRWYXVsdAUMZGVwb3NpdFZhdWx0BAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgUHX3RyYWRlcgkAzAgCBQtyZWFsaXplZEZlZQUDbmlsBQNuaWwDCQAAAgUJbm90aWZ5RmVlBQlub3RpZnlGZWUEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAM4IAgMFDmlzUGFydGlhbENsb3NlCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9uZXdQb3NpdGlvblNpemUFEW5ld1Bvc2l0aW9uTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25Mc3RVcGRDUEYJAQ1sYXN0VGltZXN0YW1wAAkBDmRlbGV0ZVBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgMJAGYCBQ5tYXJnaW5Ub1RyYWRlcgAACQEId2l0aGRyYXcCBQ5fdHJhZGVyQWRkcmVzcwUObWFyZ2luVG9UcmFkZXIFA25pbAkBDXVwZGF0ZUJhbGFuY2UBBQ1hbW1OZXdCYWxhbmNlCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJbGlxdWlkYXRlAwdfdHJhZGVyCl9kaXJlY3Rpb24MX3ByaWNlVXBkYXRlBAx1cGRhdGVPcmFjbGUJAPwHBAUEdGhpcwIMdXBkYXRlT3JhY2xlCQDMCAIFDF9wcmljZVVwZGF0ZQUDbmlsBQNuaWwDCQAAAgUMdXBkYXRlT3JhY2xlBQx1cGRhdGVPcmFjbGUEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQPc3BvdE1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgMFB190cmFkZXIFCl9kaXJlY3Rpb24FD1BOTF9PUFRJT05fU1BPVAQWbGlxdWlkYXRpb25NYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAwUHX3RyYWRlcgUKX2RpcmVjdGlvbgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBRZsaXF1aWRhdGlvbk1hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24GCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAhNVbmFibGUgdG8gbGlxdWlkYXRlBA9vbGRQb3NpdGlvblNpemUICQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uAl8xBA9wb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEFGlzUGFydGlhbExpcXVpZGF0aW9uAwMDCQBmAgUPc3BvdE1hcmdpblJhdGlvCQETbGlxdWlkYXRpb25GZWVSYXRpbwAJAGYCCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8AAAAHCQBmAgUMREVDSU1BTF9VTklUCQEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8ABwkAZgIJAQRtdWxkAgUPcG9zaXRpb25TaXplQWJzCQEMZ2V0U3BvdFByaWNlAAkBHW1pblBhcnRpYWxMaXF1aWRhdGlvbk5vdGlvbmFsAAcEDSR0MDc3MDI4Nzc0MTUDBRRpc1BhcnRpYWxMaXF1aWRhdGlvbgQPbGlxdWlkYXRpb25TaXplCQEDYWJzAQkBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQQQbGlxdWlkYXRpb25SYXRpbwkBBGRpdmQCBQ9saXF1aWRhdGlvblNpemUFD3Bvc2l0aW9uU2l6ZUFicwQTbGlxdWlkYXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9saXF1aWRhdGlvblNpemUJAQxnZXRTcG90UHJpY2UACQCUCgIFEGxpcXVpZGF0aW9uUmF0aW8FD2xpcXVpZGF0aW9uU2l6ZQkAlAoCAAAFD3Bvc2l0aW9uU2l6ZUFicwQQbGlxdWlkYXRpb25SYXRpbwgFDSR0MDc3MDI4Nzc0MTUCXzEED2xpcXVpZGF0aW9uU2l6ZQgFDSR0MDc3MDI4Nzc0MTUCXzIEDSR0MDc3NDIxNzgwNzcJARVpbnRlcm5hbENsb3NlUG9zaXRpb24IBQdfdHJhZGVyBQpfZGlyZWN0aW9uAwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24FD2xpcXVpZGF0aW9uU2l6ZQUPcG9zaXRpb25TaXplQWJzCQETbGlxdWlkYXRpb25GZWVSYXRpbwAAAAYHBgQPbmV3UG9zaXRpb25TaXplCAUNJHQwNzc0MjE3ODA3NwJfMQQRbmV3UG9zaXRpb25NYXJnaW4IBQ0kdDA3NzQyMTc4MDc3Al8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDc3NDIxNzgwNzcCXzMEFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNzc0MjE3ODA3NwJfNAQPcG9zaXRpb25CYWREZWJ0CAUNJHQwNzc0MjE3ODA3NwJfNQQLcmVhbGl6ZWRQbmwIBQ0kdDA3NzQyMTc4MDc3Al82BA5tYXJnaW5Ub1RyYWRlcggFDSR0MDc3NDIxNzgwNzcCXzcEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3NzQyMTc4MDc3Al84BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA3NzQyMTc4MDc3Al85BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNzc0MjE3ODA3NwNfMTAEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA3NzQyMTc4MDc3A18xMQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA3NzQyMTc4MDc3A18xMgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNzc0MjE3ODA3NwNfMTMEGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyCAUNJHQwNzc0MjE3ODA3NwNfMTQEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDc3NDIxNzgwNzcDXzE1BBJsaXF1aWRhdGlvblBlbmFsdHkIBQ0kdDA3NzQyMTc4MDc3A18xNgQPZmVlVG9MaXF1aWRhdG9yCQBpAgUSbGlxdWlkYXRpb25QZW5hbHR5AAIECmZlZVRvVmF1bHQJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNbmV3QW1tQmFsYW5jZQMJAGYCAAAFCmFtbUJhbGFuY2UAAAUKYW1tQmFsYW5jZQQLbG9ja0JhZERlYnQDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAEC2xvY2tCYWREZWJ0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkAZAIFD3Bvc2l0aW9uQmFkRGVidAUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUSbGlxdWlkYXRpb25QZW5hbHR5BQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAgdhZGRGcmVlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUKZmVlVG9WYXVsdAUDbmlsAwkAAAIFEGRlcG9zaXRJbnN1cmFuY2UFEGRlcG9zaXRJbnN1cmFuY2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCBQdfdHJhZGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIDBRRpc1BhcnRpYWxMaXF1aWRhdGlvbgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ5kZWxldGVQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24JAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUPZmVlVG9MaXF1aWRhdG9yCQENdXBkYXRlQmFsYW5jZQEFDW5ld0FtbUJhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKcGF5RnVuZGluZwEMX3ByaWNlVXBkYXRlBAx1cGRhdGVPcmFjbGUJAPwHBAUEdGhpcwIMdXBkYXRlT3JhY2xlCQDMCAIFDF9wcmljZVVwZGF0ZQUDbmlsBQNuaWwDCQAAAgUMdXBkYXRlT3JhY2xlBQx1cGRhdGVPcmFjbGUEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAADAwMJAGYCBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJAQ1sYXN0VGltZXN0YW1wAAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQkArAICCQCsAgIJAKwCAgIhSW52YWxpZCBmdW5kaW5nIGJsb2NrIHRpbWVzdGFtcDogCQCkAwEJAQ1sYXN0VGltZXN0YW1wAAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABA0kdDA4MDI5NTgwMzczCQEKZ2V0RnVuZGluZwAEFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwODAyOTU4MDM3MwJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDgwMjk1ODAzNzMCXzIEDnByZW1pdW1Ub1ZhdWx0CAUNJHQwODAyOTU4MDM3MwJfMwQTZG9QYXlGdW5kaW5nVG9WYXVsdAMJAGYCBQ5wcmVtaXVtVG9WYXVsdAAABBNkb1BheUZ1bmRpbmdUb1ZhdWx0CQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgkBAS0BBQ5wcmVtaXVtVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUTZG9QYXlGdW5kaW5nVG9WYXVsdAUTZG9QYXlGdW5kaW5nVG9WYXVsdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUTZG9QYXlGdW5kaW5nVG9WYXVsdAUTZG9QYXlGdW5kaW5nVG9WYXVsdAkBDXVwZGF0ZUZ1bmRpbmcFCQBkAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBkAgkBI2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkAZAIJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ABRRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAQRkaXZkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FD3VuZGVybHlpbmdQcmljZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQx1cGRhdGVPcmFjbGUBDF9wcmljZVVwZGF0ZQMJAAACCQEKb3JhY2xlTW9kZQAFDE9SQUNMRV9QTEFJTgUDbmlsBAxwcmljZVVwZGF0ZXMJALwJAgUMX3ByaWNlVXBkYXRlAgI6OgQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQRYmFzZU9yYWNsZUFkZHJlc3MIBQpiYXNlT3JhY2xlAl8xBBJkb1VwZGF0ZUJhc2VPcmFjbGUJAPwHBAURYmFzZU9yYWNsZUFkZHJlc3MCCnVwZGF0ZURhdGEJAMwIAgkAkQMCBQxwcmljZVVwZGF0ZXMAAAUDbmlsBQNuaWwDCQAAAgUSZG9VcGRhdGVCYXNlT3JhY2xlBRJkb1VwZGF0ZUJhc2VPcmFjbGUEC3F1b3RlT3JhY2xlCQENZ2V0T3JhY2xlRGF0YQEFDWtfcXVvdGVPcmFjbGUEE2RvVXBkYXRlUXVvdGVPcmFjbGUDCQEJaXNEZWZpbmVkAQULcXVvdGVPcmFjbGUEDHF1b3RlT3JhY2xlVgkBBXZhbHVlAQULcXVvdGVPcmFjbGUEEnF1b3RlT3JhY2xlQWRkcmVzcwgFDHF1b3RlT3JhY2xlVgJfMQQTZG9VcGRhdGVRdW90ZU9yYWNsZQkA/AcEBRJxdW90ZU9yYWNsZUFkZHJlc3MCCnVwZGF0ZURhdGEJAMwIAgkAkQMCBQxwcmljZVVwZGF0ZXMAAQUDbmlsBQNuaWwDCQAAAgUTZG9VcGRhdGVRdW90ZU9yYWNsZQUTZG9VcGRhdGVRdW90ZU9yYWNsZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUTZG9VcGRhdGVRdW90ZU9yYWNsZQUTZG9VcGRhdGVRdW90ZU9yYWNsZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUABAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEDSR0MDgyMTkwODI1NTYJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFB19xdEFzdFIFB19ic0FzdFIEE25ld1F1b3RlQXNzZXRXZWlnaHQIBQ0kdDA4MjE5MDgyNTU2Al8xBBJuZXdCYXNlQXNzZXRXZWlnaHQIBQ0kdDA4MjE5MDgyNTU2Al8yBA1tYXJnaW5Ub1ZhdWx0CAUNJHQwODIxOTA4MjU1NgJfMwQQbWFyZ2luVG9WYXVsdEFkagMDCQBmAgAABQ1tYXJnaW5Ub1ZhdWx0CQBmAgkBA2FicwEFDW1hcmdpblRvVmF1bHQJAQhjYmFsYW5jZQAHCQEBLQEJAQhjYmFsYW5jZQAFDW1hcmdpblRvVmF1bHQEDWRvRXhjaGFuZ2VQbkwDCQECIT0CBRBtYXJnaW5Ub1ZhdWx0QWRqAAAEDWRvRXhjaGFuZ2VQbkwJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCBRBtYXJnaW5Ub1ZhdWx0QWRqBQNuaWwFA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQ1kb0V4Y2hhbmdlUG5MBQ1kb0V4Y2hhbmdlUG5MCQDOCAIJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFEG1hcmdpblRvVmF1bHRBZGoJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGVuc3VyZUNhbGxlZE9uY2UAAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIiSW52YWxpZCBzYXZlQ3VycmVudFR4SWQgcGFyYW1ldGVycwQEdHhJZAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBAZsYXN0VHgJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUIa19sYXN0VHgCAAMJAQIhPQIFBmxhc3RUeAUEdHhJZAkAzAgCCQELU3RyaW5nRW50cnkCBQhrX2xhc3RUeAUEdHhJZAUDbmlsCQACAQIpQ2FuIG5vdCBjYWxsIHZBTU0gbWV0aG9kcyB0d2ljZSBpbiBvbmUgdHgBaQEPbWlncmF0ZVBvc2l0aW9uAQdfdHJhZGVyBA9wb3NpdGlvblNpemVPcHQJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFB190cmFkZXIDAwkBCWlzRGVmaW5lZAEFD3Bvc2l0aW9uU2l6ZU9wdAkBCWlzRGVmaW5lZAEJAKYIAQUHX3RyYWRlcgcEBXBTaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgQHcE1hcmdpbgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUHX3RyYWRlcgQJcE5vdGlvbmFsCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyBAlwRnJhY3Rpb24JARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FB190cmFkZXIECnBUaW1lc3RhbXAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQdfdHJhZGVyCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQEcEZlZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQdfdHJhZGVyCQEDZmVlAAQJcFNlcXVlbmNlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRJrX3Bvc2l0aW9uU2VxdWVuY2UFB190cmFkZXIECnBEaXJlY3Rpb24JAQxnZXREaXJlY3Rpb24BBQVwU2l6ZQQLcG9zaXRpb25LZXkJAKwCAgkArAICBQdfdHJhZGVyAgFfCQCkAwEFCnBEaXJlY3Rpb24JAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFB190cmFkZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUQa19wb3NpdGlvbk1hcmdpbgUHX3RyYWRlcgkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FB190cmFkZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQdfdHJhZGVyCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFB190cmFkZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUSa19wb3NpdGlvblNlcXVlbmNlBQdfdHJhZGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQULcG9zaXRpb25LZXkFBXBTaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQtwb3NpdGlvbktleQUHcE1hcmdpbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAULcG9zaXRpb25LZXkFCXBOb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgULcG9zaXRpb25LZXkFCXBGcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQtwb3NpdGlvbktleQUKcFRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQULcG9zaXRpb25LZXkFBHBGZWUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEmtfcG9zaXRpb25TZXF1ZW5jZQULcG9zaXRpb25LZXkFCXBTZXF1ZW5jZQUDbmlsCQACAQkArAICAhdOb3RoaW5nIHRvIG1pZ3JhdGUgZm9yIAUHX3RyYWRlcgFpASd2aWV3X2NhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQDB190cmFkZXIKX2RpcmVjdGlvbgxfcHJpY2VVcGRhdGUEDHVwZGF0ZU9yYWNsZQkA/AcEBQR0aGlzAgx1cGRhdGVPcmFjbGUJAMwIAgUMX3ByaWNlVXBkYXRlBQNuaWwFA25pbAMJAAACBQx1cGRhdGVPcmFjbGUFDHVwZGF0ZU9yYWNsZQQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA0kdDA4NjM1MDg2NDg2CQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBAxwb3NpdGlvblNpemUIBQ0kdDA4NjM1MDg2NDg2Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDg2MzUwODY0ODYCXzIEA3BvbggFDSR0MDg2MzUwODY0ODYCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwODYzNTA4NjQ4NgJfNAQRcG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA4NjM1MDg2NDg2Al81BA0kdDA4NjQ4OTg2NjAyCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwDBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDA4NjQ4OTg2NjAyAl8xBA11bnJlYWxpemVkUG5sCAUNJHQwODY0ODk4NjYwMgJfMgQNJHQwODY2MDU4NjgyOQkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FEXBvc2l0aW9uTHN0VXBkQ1BGBRFwb3NpdGlvblRpbWVzdGFtcAUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwODY2MDU4NjgyOQJfMQQHYmFkRGVidAgFDSR0MDg2NjA1ODY4MjkCXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwODY2MDU4NjgyOQJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA4NjYwNTg2ODI5Al80BA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAECXNwb3RQcmljZQkBDGdldFNwb3RQcmljZQAJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkBAXMBBQxyZW1haW5NYXJnaW4JAQFzAQUOZnVuZGluZ1BheW1lbnQJAQFzAQkBDmdldE1hcmdpblJhdGlvAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgkBAXMBBQ11bnJlYWxpemVkUG5sCQEBcwEFB2JhZERlYnQJAQFzAQUQcG9zaXRpb25Ob3Rpb25hbAkBAXMBBQtyb2xsb3ZlckZlZQkBAXMBBQ91bmRlcmx5aW5nUHJpY2UJAQFzAQUJc3BvdFByaWNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFXZpZXdfZ2V0UGVnQWRqdXN0Q29zdAEGX3ByaWNlBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwUGX3ByaWNlBQdfcXRBc3RSBQdfYnNBc3RSCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDg3NjgyODc3NjMJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDg3NjgyODc3NjMCXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDg3NjgyODc3NjMCXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAQxfcHJpY2VVcGRhdGUEDHVwZGF0ZU9yYWNsZQkA/AcEBQR0aGlzAgx1cGRhdGVPcmFjbGUJAMwIAgUMX3ByaWNlVXBkYXRlBQNuaWwFA25pbAMJAAACBQx1cGRhdGVPcmFjbGUFDHVwZGF0ZU9yYWNsZQQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDg4NDE1ODg0OTMJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4ODQxNTg4NDkzAl8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODg0MTU4ODQ5MwJfMgQOcHJlbWl1bVRvVmF1bHQIBQ0kdDA4ODQxNTg4NDkzAl8zBAtsb25nRnVuZGluZwkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UEDHNob3J0RnVuZGluZwkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFC2xvbmdGdW5kaW5nCQEBcwEFDHNob3J0RnVuZGluZwkBAXMBCQEMZ2V0U3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UACQEBcwEFDnByZW1pdW1Ub1ZhdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGNvbXB1dGVTcG90UHJpY2UABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEBnJlc3VsdAkBDGdldFNwb3RQcmljZQAJAJQKAgUDbmlsBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfY29tcHV0ZUZlZUZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQGcmVzdWx0CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgULX2FydGlmYWN0SWQJAJQKAgUDbmlsBQZyZXN1bHQBAnR4AQZ2ZXJpZnkABA5jb29yZGluYXRvclN0cgkAnQgCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwMJAQlpc0RlZmluZWQBBQ5jb29yZGluYXRvclN0cgQFYWRtaW4JAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUOY29vcmRpbmF0b3JTdHIFD2tfYWRtaW5fYWRkcmVzcwMJAQlpc0RlZmluZWQBBQVhZG1pbgkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBCQEFdmFsdWUBBQVhZG1pbgkArAICCQCsAgIJAKwCAgIHc3RhdHVzXwkApQgBBQR0aGlzAgFfCQDYBAEIBQJ0eAJpZAcJAAIBAi51bmFibGUgdG8gdmVyaWZ5OiBhZG1pbiBub3Qgc2V0IGluIGNvb3JkaW5hdG9yCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5YECwJg==", "height": 2662878, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 4pBUFC8VqGgqR2GVXx1gRgS5z9xgXH6RLMp4eaTSAa2A Next: CoLkahdeVJR7czbkJ5px2bb3t3M3jPiqSKDzUJRrkWEZ Diff:
OldNewDifferences
10801080
10811081
10821082 @Callable(i)
1083-func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_baseOracleData,_quoteOracleData,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _fundingPeriod))
1083+func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_baseOracleData,_quoteOracleData,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _fundingPeriod))
10841084 then true
10851085 else (0 >= _initMarginRatio))
10861086 then true
10881088 then true
10891089 else (0 >= _minInitMarginRatio))
10901090 then true
1091- else (_minInitMarginRatio > DECIMAL_UNIT))
1092- then true
1093- else (_initMarginRatio >= _minInitMarginRatio))
1091+ else (_initMarginRatio > _minInitMarginRatio))
10941092 then true
10951093 else (0 >= _mmr))
10961094 then true
11371135
11381136
11391137 @Callable(i)
1140-func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
1138+func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
11411139 then true
11421140 else (0 >= _bsAstR))
11431141 then true
11481146 else (_initMarginRatio > DECIMAL_UNIT))
11491147 then true
11501148 else (0 >= _minInitMarginRatio))
1151- then true
1152- else (_minInitMarginRatio > DECIMAL_UNIT))
11531149 then true
11541150 else (_initMarginRatio > _minInitMarginRatio))
11551151 then true
12361232 else isMarketClosed())
12371233 then throw("Invalid increasePosition parameters")
12381234 else {
1239- let $t06054060689 = getForTraderWithArtifact(_trader, getArtifactId(i))
1240- let adjustedFee = $t06054060689._1
1241- let burnArtifact = $t06054060689._2
1235+ let $t06046360612 = getForTraderWithArtifact(_trader, getArtifactId(i))
1236+ let adjustedFee = $t06046360612._1
1237+ let burnArtifact = $t06046360612._2
12421238 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12431239 let distributeFeeAmount = (_rawAmount - _amount)
12441240 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12511247 throw("Invalid referrerFee")
12521248 }
12531249 let feeAmount = (distributeFeeAmount - referrerFee)
1254- let $t06118561365 = getPosition(_trader, _direction)
1255- let oldPositionSize = $t06118561365._1
1256- let oldPositionMargin = $t06118561365._2
1257- let oldPositionOpenNotional = $t06118561365._3
1258- let oldPositionLstUpdCPF = $t06118561365._4
1259- let oldPositionTimestamp = $t06118561365._5
1250+ let $t06110861288 = getPosition(_trader, _direction)
1251+ let oldPositionSize = $t06110861288._1
1252+ let oldPositionMargin = $t06110861288._2
1253+ let oldPositionOpenNotional = $t06110861288._3
1254+ let oldPositionLstUpdCPF = $t06110861288._4
1255+ let oldPositionTimestamp = $t06110861288._5
12601256 let isNewPosition = (oldPositionSize == 0)
12611257 let isSameDirection = if ((oldPositionSize > 0))
12621258 then (_direction == DIR_LONG)
12651261 then isSameDirection
12661262 else false
12671263 let isAdd = (_direction == DIR_LONG)
1268- let $t06165464787 = if (if (isNewPosition)
1264+ let $t06157764710 = if (if (isNewPosition)
12691265 then true
12701266 else expandExisting)
12711267 then {
12721268 let openNotional = muld(_amount, _leverage)
1273- let $t06216362336 = swapInput(isAdd, openNotional)
1274- let amountBaseAssetBought = $t06216362336._1
1275- let quoteAssetReserveAfter = $t06216362336._2
1276- let baseAssetReserveAfter = $t06216362336._3
1277- let totalPositionSizeAfter = $t06216362336._4
1269+ let $t06208662259 = swapInput(isAdd, openNotional)
1270+ let amountBaseAssetBought = $t06208662259._1
1271+ let quoteAssetReserveAfter = $t06208662259._2
1272+ let baseAssetReserveAfter = $t06208662259._3
1273+ let totalPositionSizeAfter = $t06208662259._4
12781274 if (if ((_minBaseAssetAmount != 0))
12791275 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12801276 else false)
12871283 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12881284 then openNotional
12891285 else 0))
1290- let $t06288263157 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1291- let remainMargin = $t06288263157._1
1292- let x1 = $t06288263157._2
1293- let x2 = $t06288263157._3
1294- let rolloverFee = $t06288263157._4
1286+ let $t06280563080 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1287+ let remainMargin = $t06280563080._1
1288+ let x1 = $t06280563080._2
1289+ let x2 = $t06280563080._3
1290+ let rolloverFee = $t06280563080._4
12951291 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12961292 then throw("Over max spread limit")
12971293 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
13051301 }
13061302 else {
13071303 let openNotional = muld(_amount, _leverage)
1308- let $t06447564603 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1309- let oldPositionNotional = $t06447564603._1
1310- let unrealizedPnl = $t06447564603._2
1304+ let $t06439864526 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1305+ let oldPositionNotional = $t06439864526._1
1306+ let unrealizedPnl = $t06439864526._2
13111307 if ((oldPositionNotional > openNotional))
13121308 then throw("Use decreasePosition to decrease position size")
13131309 else throw("Close position first")
13141310 }
1315- let newPositionSize = $t06165464787._1
1316- let newPositionRemainMargin = $t06165464787._2
1317- let newPositionOpenNotional = $t06165464787._3
1318- let newPositionLatestCPF = $t06165464787._4
1319- let newPositionTimestamp = $t06165464787._5
1320- let baseAssetReserveAfter = $t06165464787._6
1321- let quoteAssetReserveAfter = $t06165464787._7
1322- let totalPositionSizeAfter = $t06165464787._8
1323- let openInterestNotionalAfter = $t06165464787._9
1324- let totalLongAfter = $t06165464787._10
1325- let totalShortAfter = $t06165464787._11
1326- let totalLongOpenInterestAfter = $t06165464787._12
1327- let totalShortOpenInterestAfter = $t06165464787._13
1328- let rolloverFee = $t06165464787._14
1329- let $t06479364864 = distributeFee((feeAmount + rolloverFee))
1330- let feeToStakers = $t06479364864._1
1331- let feeToVault = $t06479364864._2
1311+ let newPositionSize = $t06157764710._1
1312+ let newPositionRemainMargin = $t06157764710._2
1313+ let newPositionOpenNotional = $t06157764710._3
1314+ let newPositionLatestCPF = $t06157764710._4
1315+ let newPositionTimestamp = $t06157764710._5
1316+ let baseAssetReserveAfter = $t06157764710._6
1317+ let quoteAssetReserveAfter = $t06157764710._7
1318+ let totalPositionSizeAfter = $t06157764710._8
1319+ let openInterestNotionalAfter = $t06157764710._9
1320+ let totalLongAfter = $t06157764710._10
1321+ let totalShortAfter = $t06157764710._11
1322+ let totalLongOpenInterestAfter = $t06157764710._12
1323+ let totalShortOpenInterestAfter = $t06157764710._13
1324+ let rolloverFee = $t06157764710._14
1325+ let $t06471664787 = distributeFee((feeAmount + rolloverFee))
1326+ let feeToStakers = $t06471664787._1
1327+ let feeToVault = $t06471664787._2
13321328 let stake = if ((_amount >= rolloverFee))
13331329 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13341330 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13901386 else isMarketClosed())
13911387 then throw("Invalid addMargin parameters")
13921388 else {
1393- let $t06720667386 = getPosition(_trader, _direction)
1394- let oldPositionSize = $t06720667386._1
1395- let oldPositionMargin = $t06720667386._2
1396- let oldPositionOpenNotional = $t06720667386._3
1397- let oldPositionLstUpdCPF = $t06720667386._4
1398- let oldPositionTimestamp = $t06720667386._5
1389+ let $t06712967309 = getPosition(_trader, _direction)
1390+ let oldPositionSize = $t06712967309._1
1391+ let oldPositionMargin = $t06712967309._2
1392+ let oldPositionOpenNotional = $t06712967309._3
1393+ let oldPositionLstUpdCPF = $t06712967309._4
1394+ let oldPositionTimestamp = $t06712967309._5
13991395 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
14001396 if ((stake == stake))
14011397 then {
1402- let $t06752667752 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1403- let remainMargin = $t06752667752._1
1404- let badDebt = $t06752667752._2
1405- let rolloverFee = $t06752667752._3
1398+ let $t06744967675 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1399+ let remainMargin = $t06744967675._1
1400+ let badDebt = $t06744967675._2
1401+ let rolloverFee = $t06744967675._3
14061402 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
14071403 let checkMinMargin = requireMoreMarginRatio(marginRatio, minInitMarginRatio(), false)
14081404 if ((checkMinMargin == checkMinMargin))
14091405 then {
14101406 let doTransferFeeToStakers = if ((rolloverFee > 0))
14111407 then {
1412- let $t06800868067 = distributeFee(rolloverFee)
1413- let feeToStakers = $t06800868067._1
1414- let feeToVault = $t06800868067._2
1408+ let $t06793167990 = distributeFee(rolloverFee)
1409+ let feeToStakers = $t06793167990._1
1410+ let feeToVault = $t06793167990._2
14151411 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
14161412 if ((unstake == unstake))
14171413 then {
14641460 else isMarketClosed())
14651461 then throw("Invalid removeMargin parameters")
14661462 else {
1467- let $t06956869748 = getPosition(_trader, _direction)
1468- let oldPositionSize = $t06956869748._1
1469- let oldPositionMargin = $t06956869748._2
1470- let oldPositionOpenNotional = $t06956869748._3
1471- let oldPositionLstUpdCPF = $t06956869748._4
1472- let oldPositionTimestamp = $t06956869748._5
1473- let $t06975470003 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1474- let remainMargin = $t06975470003._1
1475- let badDebt = $t06975470003._2
1476- let fundingPayment = $t06975470003._3
1477- let rolloverFee = $t06975470003._4
1463+ let $t06949169671 = getPosition(_trader, _direction)
1464+ let oldPositionSize = $t06949169671._1
1465+ let oldPositionMargin = $t06949169671._2
1466+ let oldPositionOpenNotional = $t06949169671._3
1467+ let oldPositionLstUpdCPF = $t06949169671._4
1468+ let oldPositionTimestamp = $t06949169671._5
1469+ let $t06967769926 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1470+ let remainMargin = $t06967769926._1
1471+ let badDebt = $t06967769926._2
1472+ let fundingPayment = $t06967769926._3
1473+ let rolloverFee = $t06967769926._4
14781474 if ((badDebt != 0))
14791475 then throw("Invalid removed margin amount")
14801476 else {
14821478 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14831479 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14841480 else {
1485- let $t07038970448 = distributeFee(rolloverFee)
1486- let feeToStakers = $t07038970448._1
1487- let feeToVault = $t07038970448._2
1481+ let $t07031270371 = distributeFee(rolloverFee)
1482+ let feeToStakers = $t07031270371._1
1483+ let feeToVault = $t07031270371._2
14881484 let doTransferFeeToStakers = if ((rolloverFee > 0))
14891485 then {
14901486 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
15421538 then throw("Invalid closePosition parameters")
15431539 else {
15441540 let oldPositionTimestamp = getPosition(_trader, _direction)._5
1545- let $t07278373386 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1546- let newPositionSize = $t07278373386._1
1547- let newPositionMargin = $t07278373386._2
1548- let newPositionOpenNotional = $t07278373386._3
1549- let newPositionLstUpdCPF = $t07278373386._4
1550- let positionBadDebt = $t07278373386._5
1551- let realizedPnl = $t07278373386._6
1552- let marginToTrader = $t07278373386._7
1553- let quoteAssetReserveAfter = $t07278373386._8
1554- let baseAssetReserveAfter = $t07278373386._9
1555- let totalPositionSizeAfter = $t07278373386._10
1556- let openInterestNotionalAfter = $t07278373386._11
1557- let totalLongAfter = $t07278373386._12
1558- let totalShortAfter = $t07278373386._13
1559- let totalLongOpenInterestAfter = $t07278373386._14
1560- let totalShortOpenInterestAfter = $t07278373386._15
1561- let realizedFee = $t07278373386._16
1541+ let $t07270673309 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1542+ let newPositionSize = $t07270673309._1
1543+ let newPositionMargin = $t07270673309._2
1544+ let newPositionOpenNotional = $t07270673309._3
1545+ let newPositionLstUpdCPF = $t07270673309._4
1546+ let positionBadDebt = $t07270673309._5
1547+ let realizedPnl = $t07270673309._6
1548+ let marginToTrader = $t07270673309._7
1549+ let quoteAssetReserveAfter = $t07270673309._8
1550+ let baseAssetReserveAfter = $t07270673309._9
1551+ let totalPositionSizeAfter = $t07270673309._10
1552+ let openInterestNotionalAfter = $t07270673309._11
1553+ let totalLongAfter = $t07270673309._12
1554+ let totalShortAfter = $t07270673309._13
1555+ let totalLongOpenInterestAfter = $t07270673309._14
1556+ let totalShortOpenInterestAfter = $t07270673309._15
1557+ let realizedFee = $t07270673309._16
15621558 if ((positionBadDebt > 0))
15631559 then throw("Invalid closePosition parameters: bad debt")
15641560 else if ((oldPositionTimestamp >= lastTimestamp()))
15821578 case _ =>
15831579 throw("Invalid referrerFee")
15841580 }
1585- let $t07435874431 = distributeFee((realizedFee - referrerFee))
1586- let feeToStakers = $t07435874431._1
1587- let feeToVault = $t07435874431._2
1581+ let $t07428174354 = distributeFee((realizedFee - referrerFee))
1582+ let feeToStakers = $t07428174354._1
1583+ let feeToVault = $t07428174354._2
15881584 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15891585 if ((depositVault == depositVault))
15901586 then {
16541650 else false)
16551651 then (muld(positionSizeAbs, getSpotPrice()) > minPartialLiquidationNotional())
16561652 else false
1657- let $t07710577492 = if (isPartialLiquidation)
1653+ let $t07702877415 = if (isPartialLiquidation)
16581654 then {
16591655 let liquidationSize = abs(getPartialLiquidationAmount(_trader, oldPositionSize))
16601656 let liquidationRatio = divd(liquidationSize, positionSizeAbs)
16621658 $Tuple2(liquidationRatio, liquidationSize)
16631659 }
16641660 else $Tuple2(0, positionSizeAbs)
1665- let liquidationRatio = $t07710577492._1
1666- let liquidationSize = $t07710577492._2
1667- let $t07749878154 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
1661+ let liquidationRatio = $t07702877415._1
1662+ let liquidationSize = $t07702877415._2
1663+ let $t07742178077 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
16681664 then liquidationSize
16691665 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1670- let newPositionSize = $t07749878154._1
1671- let newPositionMargin = $t07749878154._2
1672- let newPositionOpenNotional = $t07749878154._3
1673- let newPositionLstUpdCPF = $t07749878154._4
1674- let positionBadDebt = $t07749878154._5
1675- let realizedPnl = $t07749878154._6
1676- let marginToTrader = $t07749878154._7
1677- let quoteAssetReserveAfter = $t07749878154._8
1678- let baseAssetReserveAfter = $t07749878154._9
1679- let totalPositionSizeAfter = $t07749878154._10
1680- let openInterestNotionalAfter = $t07749878154._11
1681- let totalLongAfter = $t07749878154._12
1682- let totalShortAfter = $t07749878154._13
1683- let totalLongOpenInterestAfter = $t07749878154._14
1684- let totalShortOpenInterestAfter = $t07749878154._15
1685- let liquidationPenalty = $t07749878154._16
1666+ let newPositionSize = $t07742178077._1
1667+ let newPositionMargin = $t07742178077._2
1668+ let newPositionOpenNotional = $t07742178077._3
1669+ let newPositionLstUpdCPF = $t07742178077._4
1670+ let positionBadDebt = $t07742178077._5
1671+ let realizedPnl = $t07742178077._6
1672+ let marginToTrader = $t07742178077._7
1673+ let quoteAssetReserveAfter = $t07742178077._8
1674+ let baseAssetReserveAfter = $t07742178077._9
1675+ let totalPositionSizeAfter = $t07742178077._10
1676+ let openInterestNotionalAfter = $t07742178077._11
1677+ let totalLongAfter = $t07742178077._12
1678+ let totalShortAfter = $t07742178077._13
1679+ let totalLongOpenInterestAfter = $t07742178077._14
1680+ let totalShortOpenInterestAfter = $t07742178077._15
1681+ let liquidationPenalty = $t07742178077._16
16861682 let feeToLiquidator = (liquidationPenalty / 2)
16871683 let feeToVault = (liquidationPenalty - feeToLiquidator)
16881684 let ammBalance = (cbalance() - liquidationPenalty)
17431739 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
17441740 else {
17451741 let underlyingPrice = getOraclePrice()
1746- let $t08037280450 = getFunding()
1747- let shortPremiumFraction = $t08037280450._1
1748- let longPremiumFraction = $t08037280450._2
1749- let premiumToVault = $t08037280450._3
1742+ let $t08029580373 = getFunding()
1743+ let shortPremiumFraction = $t08029580373._1
1744+ let longPremiumFraction = $t08029580373._2
1745+ let premiumToVault = $t08029580373._3
17501746 let doPayFundingToVault = if ((premiumToVault > 0))
17511747 then {
17521748 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
18011797 func syncTerminalPriceToOracle () = {
18021798 let _qtAstR = qtAstR()
18031799 let _bsAstR = bsAstR()
1804- let $t08226782633 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1805- let newQuoteAssetWeight = $t08226782633._1
1806- let newBaseAssetWeight = $t08226782633._2
1807- let marginToVault = $t08226782633._3
1800+ let $t08219082556 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1801+ let newQuoteAssetWeight = $t08219082556._1
1802+ let newBaseAssetWeight = $t08219082556._2
1803+ let marginToVault = $t08219082556._3
18081804 let marginToVaultAdj = if (if ((0 > marginToVault))
18091805 then (abs(marginToVault) > cbalance())
18101806 else false)
18691865 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
18701866 if ((sync == sync))
18711867 then {
1872- let $t08642786563 = getPosition(_trader, _direction)
1873- let positionSize = $t08642786563._1
1874- let positionMargin = $t08642786563._2
1875- let pon = $t08642786563._3
1876- let positionLstUpdCPF = $t08642786563._4
1877- let positionTimestamp = $t08642786563._5
1878- let $t08656686679 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1879- let positionNotional = $t08656686679._1
1880- let unrealizedPnl = $t08656686679._2
1881- let $t08668286906 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1882- let remainMargin = $t08668286906._1
1883- let badDebt = $t08668286906._2
1884- let fundingPayment = $t08668286906._3
1885- let rolloverFee = $t08668286906._4
1868+ let $t08635086486 = getPosition(_trader, _direction)
1869+ let positionSize = $t08635086486._1
1870+ let positionMargin = $t08635086486._2
1871+ let pon = $t08635086486._3
1872+ let positionLstUpdCPF = $t08635086486._4
1873+ let positionTimestamp = $t08635086486._5
1874+ let $t08648986602 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1875+ let positionNotional = $t08648986602._1
1876+ let unrealizedPnl = $t08648986602._2
1877+ let $t08660586829 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1878+ let remainMargin = $t08660586829._1
1879+ let badDebt = $t08660586829._2
1880+ let fundingPayment = $t08660586829._3
1881+ let rolloverFee = $t08660586829._4
18861882 let underlyingPrice = getOraclePrice()
18871883 let spotPrice = getSpotPrice()
18881884 throw(((((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader, _direction))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)) + s(underlyingPrice)) + s(spotPrice)))
19061902
19071903 @Callable(i)
19081904 func view_getTerminalAmmPrice () = {
1909- let $t08775987840 = getTerminalAmmState()
1910- let terminalQuoteAssetReserve = $t08775987840._1
1911- let terminalBaseAssetReserve = $t08775987840._2
1905+ let $t08768287763 = getTerminalAmmState()
1906+ let terminalQuoteAssetReserve = $t08768287763._1
1907+ let terminalBaseAssetReserve = $t08768287763._2
19121908 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
19131909 throw(toString(price))
19141910 }
19241920 if ((sync == sync))
19251921 then {
19261922 let underlyingPrice = getOraclePrice()
1927- let $t08849288570 = getFunding()
1928- let shortPremiumFraction = $t08849288570._1
1929- let longPremiumFraction = $t08849288570._2
1930- let premiumToVault = $t08849288570._3
1923+ let $t08841588493 = getFunding()
1924+ let shortPremiumFraction = $t08841588493._1
1925+ let longPremiumFraction = $t08841588493._2
1926+ let premiumToVault = $t08841588493._3
19311927 let longFunding = divd(longPremiumFraction, underlyingPrice)
19321928 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
19331929 throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_baseOracle = "k_baseOracle"
55
66 let k_quoteOracle = "k_quoteOracle"
77
88 let k_balance = "k_balance"
99
1010 let k_sequence = "k_sequence"
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_positionSequence = "k_positionSequence"
2121
2222 let k_positionFee = "k_positionFee"
2323
2424 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2525
2626 let k_initialized = "k_initialized"
2727
2828 let k_paused = "k_paused"
2929
3030 let k_closeOnly = "k_closeOnly"
3131
3232 let k_fee = "k_fee"
3333
3434 let k_rolloverFee = "k_rollover_fee"
3535
3636 let k_fundingPeriod = "k_fundingPeriod"
3737
3838 let k_initMarginRatio = "k_initMarginRatio"
3939
4040 let k_minInitMarginRatio = "k_minInitMarginRatio"
4141
4242 let k_maintenanceMarginRatio = "k_mmr"
4343
4444 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4545
4646 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4747
4848 let k_spreadLimit = "k_spreadLimit"
4949
5050 let k_maxPriceImpact = "k_maxPriceImpact"
5151
5252 let k_maxPriceSpread = "k_maxPriceSpread"
5353
5454 let k_maxOpenNotional = "k_maxOpenNotional"
5555
5656 let k_feeToStakersPercent = "k_feeToStakersPercent"
5757
5858 let k_maxOracleDelay = "k_maxOracleDelay"
5959
6060 let k_fundingMode = "k_fundingMode"
6161
6262 let k_oracleMode = "k_oracleMode"
6363
6464 let k_positionMode = "k_positionMode"
6565
6666 let k_minLiquidationNotional = "k_minLiquidationNotional"
6767
6868 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6969
7070 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7171
7272 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7373
7474 let k_longFundingRate = "k_longFundingRate"
7575
7676 let k_shortFundingRate = "k_shortFundingRate"
7777
7878 let k_quoteAssetReserve = "k_qtAstR"
7979
8080 let k_baseAssetReserve = "k_bsAstR"
8181
8282 let k_quoteAssetWeight = "k_qtAstW"
8383
8484 let k_baseAssetWeight = "k_bsAstW"
8585
8686 let k_totalPositionSize = "k_totalPositionSize"
8787
8888 let k_totalLongPositionSize = "k_totalLongPositionSize"
8989
9090 let k_totalShortPositionSize = "k_totalShortPositionSize"
9191
9292 let k_openInterestNotional = "k_openInterestNotional"
9393
9494 let k_openInterestShort = "k_openInterestShort"
9595
9696 let k_openInterestLong = "k_openInterestLong"
9797
9898 let k_lastTx = "k_lastTx"
9999
100100 let k_coordinatorAddress = "k_coordinatorAddress"
101101
102102 let k_vault_address = "k_vault_address"
103103
104104 let k_admin_address = "k_admin_address"
105105
106106 let k_quote_asset = "k_quote_asset"
107107
108108 let k_staking_address = "k_staking_address"
109109
110110 let k_miner_address = "k_miner_address"
111111
112112 let k_orders_address = "k_orders_address"
113113
114114 let k_referral_address = "k_referral_address"
115115
116116 let k_nft_manager_address = "k_nft_manager_address"
117117
118118 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
119119
120120
121121 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
122122
123123
124124 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
125125
126126
127127 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
128128
129129
130130 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
131131
132132
133133 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
134134
135135
136136 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
137137
138138
139139 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
140140
141141
142142 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
143143
144144
145145 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
146146
147147
148148 let k_token_param = "k_token_param"
149149
150150 let k_token_type = "k_token_type"
151151
152152 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
153153
154154 let DIR_LONG = 1
155155
156156 let DIR_SHORT = 2
157157
158158 let SECONDS = 1000
159159
160160 let DECIMAL_NUMBERS = 6
161161
162162 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
163163
164164 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
165165
166166 let ONE_DAY = (86400 * DECIMAL_UNIT)
167167
168168 let PNL_OPTION_SPOT = 1
169169
170170 let PNL_OPTION_ORACLE = 2
171171
172172 let FUNDING_ASYMMETRIC = 1
173173
174174 let FUNDING_SYMMETRIC = 2
175175
176176 let ORACLE_PLAIN = 1
177177
178178 let ORACLE_JIT = 2
179179
180180 let POSITION_DIRECT = 1
181181
182182 let POSITION_ORDER = 2
183183
184184 func s (_x) = (toString(_x) + ",")
185185
186186
187187 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
188188
189189
190190 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
191191
192192
193193 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
194194
195195
196196 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
197197
198198
199199 func abs (_x) = if ((_x > 0))
200200 then _x
201201 else -(_x)
202202
203203
204204 func vmax (_x,_y) = if ((_x >= _y))
205205 then _x
206206 else _y
207207
208208
209209 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
210210
211211
212212 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
213213
214214
215215 func strA (_address,_key) = {
216216 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
217217 val
218218 }
219219
220220
221221 func intA (_address,_key) = {
222222 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
223223 val
224224 }
225225
226226
227227 func cbalance () = int(k_balance)
228228
229229
230230 func cbalance0 () = intOr(k_balance, 0)
231231
232232
233233 func fee () = int(k_fee)
234234
235235
236236 func rolloverFeeRate () = int(k_rolloverFee)
237237
238238
239239 func initMarginRatio () = int(k_initMarginRatio)
240240
241241
242242 func minInitMarginRatio () = intOr(k_minInitMarginRatio, DECIMAL_UNIT)
243243
244244
245245 func qtAstR () = int(k_quoteAssetReserve)
246246
247247
248248 func qtAstR0 () = intOr(k_quoteAssetReserve, 0)
249249
250250
251251 func bsAstR () = int(k_baseAssetReserve)
252252
253253
254254 func bsAstR0 () = intOr(k_baseAssetReserve, 0)
255255
256256
257257 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
258258
259259
260260 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
261261
262262
263263 func totalPositionSize () = int(k_totalPositionSize)
264264
265265
266266 func openInterestNotional () = int(k_openInterestNotional)
267267
268268
269269 func openInterestShort () = int(k_openInterestShort)
270270
271271
272272 func openInterestLong () = int(k_openInterestLong)
273273
274274
275275 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
276276
277277
278278 func fundingPeriodRaw () = int(k_fundingPeriod)
279279
280280
281281 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
282282
283283
284284 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
285285
286286
287287 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
288288
289289
290290 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
291291
292292
293293 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
294294
295295
296296 func spreadLimit () = int(k_spreadLimit)
297297
298298
299299 func maxPriceImpact () = int(k_maxPriceImpact)
300300
301301
302302 func maxPriceSpread () = int(k_maxPriceSpread)
303303
304304
305305 func maxOpenNotional () = int(k_maxOpenNotional)
306306
307307
308308 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
309309
310310
311311 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
312312
313313
314314 func totalShortPositionSize () = int(k_totalShortPositionSize)
315315
316316
317317 func totalLongPositionSize () = int(k_totalLongPositionSize)
318318
319319
320320 func lastSequence () = intOr(k_sequence, 0)
321321
322322
323323 func feeToStakersPercent () = int(k_feeToStakersPercent)
324324
325325
326326 func maxOracleDelay () = int(k_maxOracleDelay)
327327
328328
329329 func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
330330
331331
332332 func oracleMode () = intOr(k_oracleMode, ORACLE_PLAIN)
333333
334334
335335 func positionMode () = intOr(k_positionMode, POSITION_DIRECT)
336336
337337
338338 func minPartialLiquidationNotional () = intOr(k_minLiquidationNotional, (10 * DECIMAL_UNIT))
339339
340340
341341 func lastTimestamp () = lastBlock.timestamp
342342
343343
344344 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
345345
346346
347347 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
348348 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
349349 if (if (_largerThanOrEqualTo)
350350 then (0 > remainingMarginRatio)
351351 else false)
352352 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
353353 else if (if (!(_largerThanOrEqualTo))
354354 then (remainingMarginRatio >= 0)
355355 else false)
356356 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
357357 else true
358358 }
359359
360360
361361 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
362362 then throw("Should not be called with _positionSize == 0")
363363 else if ((_positionSize > 0))
364364 then latestLongCumulativePremiumFraction()
365365 else latestShortCumulativePremiumFraction()
366366
367367
368368 func getPosition (_trader,_direction) = {
369369 let positionKey = ((_trader + "_") + toString(_direction))
370370 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, positionKey))
371371 match positionSizeOpt {
372372 case positionSize: Int =>
373373 $Tuple5(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, positionKey)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, positionKey)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedTimestamp, positionKey)))
374374 case _ =>
375375 $Tuple5(0, 0, 0, 0, 0)
376376 }
377377 }
378378
379379
380380 func getDirection (_positionSize) = if ((0 > _positionSize))
381381 then DIR_SHORT
382382 else DIR_LONG
383383
384384
385385 func getPositionFee (_trader,_direction) = {
386386 let positionKey = ((_trader + "_") + toString(_direction))
387387 let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, positionKey))
388388 match positionFeeOpt {
389389 case positionFee: Int =>
390390 positionFee
391391 case _ =>
392392 fee()
393393 }
394394 }
395395
396396
397397 func requireOpenPosition (_trader,_direction) = if ((getPosition(_trader, _direction)._1 == 0))
398398 then throw("No open position")
399399 else true
400400
401401
402402 func getOracleData (key) = {
403403 let oracleDataStr = getString(this, key)
404404 if (if (isDefined(oracleDataStr))
405405 then (value(oracleDataStr) != "")
406406 else false)
407407 then {
408408 let oracleData = split(value(oracleDataStr), ",")
409409 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
410410 let priceKey = oracleData[1]
411411 let blockKey = oracleData[2]
412412 let openKey = oracleData[3]
413413 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
414414 }
415415 else unit
416416 }
417417
418418
419419 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
420420
421421
422422 func paused () = valueOrElse(getBoolean(this, k_paused), false)
423423
424424
425425 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
426426
427427
428428 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
429429 then {
430430 let newBase = (bsAstR() - _baseAssetAmount)
431431 if ((0 >= newBase))
432432 then throw("Tx lead to base asset reserve <= 0, revert")
433433 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
434434 }
435435 else {
436436 let newQuote = (qtAstR() - _quoteAssetAmount)
437437 if ((0 >= newQuote))
438438 then throw("Tx lead to base quote reserve <= 0, revert")
439439 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
440440 }
441441
442442
443443 func calcInvariant (_qtAstR,_bsAstR) = {
444444 let bqtAstR = toBigInt(_qtAstR)
445445 let bbsAstR = toBigInt(_bsAstR)
446446 bmuld(bqtAstR, bbsAstR)
447447 }
448448
449449
450450 func swapInput (_isAdd,_quoteAssetAmount) = {
451451 let _qtAstR = qtAstR()
452452 let _bsAstR = bsAstR()
453453 let _qtAstW = qtAstW()
454454 let _bsAstW = bsAstW()
455455 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
456456 let k = calcInvariant(_qtAstR, _bsAstR)
457457 let quoteAssetReserveAfter = if (_isAdd)
458458 then (_qtAstR + quoteAssetAmountAdjusted)
459459 else (_qtAstR - quoteAssetAmountAdjusted)
460460 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
461461 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
462462 let amountBaseAssetBought = if (_isAdd)
463463 then amountBaseAssetBoughtAbs
464464 else -(amountBaseAssetBoughtAbs)
465465 let $t01658516755 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
466466 let quoteAssetReserveAfter1 = $t01658516755._1
467467 let baseAssetReserveAfter1 = $t01658516755._2
468468 let totalPositionSizeAfter1 = $t01658516755._3
469469 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
470470 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
471471 let priceDiff = abs((priceBefore - marketPrice))
472472 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
473473 let maxPriceImpactValue = maxPriceImpact()
474474 if ((priceImpact > maxPriceImpactValue))
475475 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)))
476476 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
477477 }
478478
479479
480480 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
481481 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
482482 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
483483 rolloverFee
484484 }
485485
486486
487487 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
488488 let fundingPayment = if ((_oldPositionSize != 0))
489489 then {
490490 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
491491 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
492492 }
493493 else 0
494494 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
495495 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
496496 let $t01942219549 = if ((0 > signedMargin))
497497 then $Tuple2(0, abs(signedMargin))
498498 else $Tuple2(abs(signedMargin), 0)
499499 let remainMargin = $t01942219549._1
500500 let badDebt = $t01942219549._2
501501 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
502502 }
503503
504504
505505 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
506506 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
507507 if ((_baseAssetAmount == 0))
508508 then throw("Invalid base asset amount")
509509 else {
510510 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
511511 let baseAssetPoolAmountAfter = if (_isAdd)
512512 then (_baseAssetReserve + _baseAssetAmount)
513513 else (_baseAssetReserve - _baseAssetAmount)
514514 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
515515 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
516516 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
517517 let maxPriceImpactValue = maxPriceImpact()
518518 let $t02081120973 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
519519 let quoteAssetReserveAfter1 = $t02081120973._1
520520 let baseAssetReserveAfter1 = $t02081120973._2
521521 let totalPositionSizeAfter1 = $t02081120973._3
522522 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
523523 let priceDiff = abs((priceBefore - marketPrice))
524524 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
525525 if (if ((priceImpact > maxPriceImpactValue))
526526 then _checkMaxPriceImpact
527527 else false)
528528 then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_quoteAssetReserve)) + " before base asset: ") + toString(_baseAssetReserve)) + " base asset amount to exchange: ") + toString(_baseAssetAmount)) + " price before: ") + toString(priceBefore)) + " market price: ") + toString(marketPrice)))
529529 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
530530 then abs(_baseAssetAmount)
531531 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
532532 then abs(_baseAssetAmount)
533533 else 0)), priceImpact)
534534 }
535535 }
536536
537537
538538 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
539539
540540
541541 func getOraclePriceValue (oracle,priceKey,blockKey) = {
542542 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
543543 if ((blockKey != ""))
544544 then {
545545 let currentBlock = height
546546 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
547547 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
548548 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
549549 else lastValue
550550 }
551551 else lastValue
552552 }
553553
554554
555555 func getOraclePrice () = {
556556 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
557557 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
558558 let quoteOracle = getOracleData(k_quoteOracle)
559559 let quoteOraclePrice = if (isDefined(quoteOracle))
560560 then {
561561 let quoteOracleV = value(quoteOracle)
562562 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
563563 }
564564 else DECIMAL_UNIT
565565 divd(baseOraclePrice, quoteOraclePrice)
566566 }
567567
568568
569569 func isMarketClosed () = {
570570 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
571571 let oracle = baseOracle._1
572572 let openKey = baseOracle._4
573573 if ((openKey != ""))
574574 then {
575575 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
576576 !(isOpen)
577577 }
578578 else false
579579 }
580580
581581
582582 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
583583 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
584584 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
585585 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
586586 absPriceDiff
587587 }
588588
589589
590590 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
591591 let oraclePrice = getOraclePrice()
592592 let _qtAstW = qtAstW()
593593 let _bsAstW = bsAstW()
594594 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
595595 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
596596 if (if ((absPriceDiffAfter > maxPriceSpread()))
597597 then (absPriceDiffAfter > absPriceDiffBefore)
598598 else false)
599599 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
600600 else true
601601 }
602602
603603
604604 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
605605 let _maxOpenNotional = maxOpenNotional()
606606 if ((_longOpenNotional > _maxOpenNotional))
607607 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
608608 else if ((_shortOpenNotional > _maxOpenNotional))
609609 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
610610 else true
611611 }
612612
613613
614614 func requireSenderCanWorkWithPositions (_caller) = if ((positionMode() == POSITION_ORDER))
615615 then (_caller == ordersAddress())
616616 else true
617617
618618
619619 func getSpotPrice () = {
620620 let _quoteAssetReserve = qtAstR()
621621 let _baseAssetReserve = bsAstR()
622622 let _qtAstW = qtAstW()
623623 let _bsAstW = bsAstW()
624624 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
625625 }
626626
627627
628628 func isOverFluctuationLimit () = {
629629 let oraclePrice = getOraclePrice()
630630 let currentPrice = getSpotPrice()
631631 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
632632 }
633633
634634
635635 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
636636 let positionSizeAbs = abs(_positionSize)
637637 let isShort = (0 > _positionSize)
638638 let positionNotional = if ((_option == PNL_OPTION_SPOT))
639639 then {
640640 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
641641 outPositionNotional
642642 }
643643 else muld(positionSizeAbs, getOraclePrice())
644644 positionNotional
645645 }
646646
647647
648648 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
649649 then throw("Invalid position size")
650650 else {
651651 let isShort = (0 > _positionSize)
652652 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
653653 let unrealizedPnl = if (isShort)
654654 then (_positionOpenNotional - positionNotional)
655655 else (positionNotional - _positionOpenNotional)
656656 $Tuple2(positionNotional, unrealizedPnl)
657657 }
658658
659659
660660 func getPositionNotionalAndUnrealizedPnl (_trader,_direction,_option) = {
661661 let $t02911429254 = getPosition(_trader, _direction)
662662 let positionSize = $t02911429254._1
663663 let positionMargin = $t02911429254._2
664664 let positionOpenNotional = $t02911429254._3
665665 let positionLstUpdCPF = $t02911429254._4
666666 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
667667 }
668668
669669
670670 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
671671
672672
673673 func getMarginRatioByOption (_trader,_direction,_option) = {
674674 let $t02978629939 = getPosition(_trader, _direction)
675675 let positionSize = $t02978629939._1
676676 let positionMargin = $t02978629939._2
677677 let pon = $t02978629939._3
678678 let positionLastUpdatedCPF = $t02978629939._4
679679 let positionTimestamp = $t02978629939._5
680680 let $t02994530050 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, _option)
681681 let positionNotional = $t02994530050._1
682682 let unrealizedPnl = $t02994530050._2
683683 let $t03005530267 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
684684 let remainMargin = $t03005530267._1
685685 let badDebt = $t03005530267._2
686686 calcMarginRatio(remainMargin, badDebt, positionNotional)
687687 }
688688
689689
690690 func getMarginRatio (_trader,_direction) = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
691691
692692
693693 func getPartialLiquidationAmount (_trader,_positionSize) = {
694694 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader, getDirection(_positionSize)), maintenanceMarginRatio())))
695695 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
696696 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
697697 let maxExchangedQuoteAssetAmount = swapResult._1
698698 let priceImpact = swapResult._7
699699 if ((maxPriceImpact() > priceImpact))
700700 then maxExchangedPositionSize
701701 else muld(abs(_positionSize), partialLiquidationRatio())
702702 }
703703
704704
705705 func internalClosePosition (_trader,_direction,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
706706 let $t03143031598 = getPosition(_trader, _direction)
707707 let oldPositionSize = $t03143031598._1
708708 let oldPositionMargin = $t03143031598._2
709709 let oldPositionOpenNotional = $t03143031598._3
710710 let oldPositionLstUpdCPF = $t03143031598._4
711711 let oldPositionTimestamp = $t03143031598._5
712712 let isLongPosition = (oldPositionSize > 0)
713713 let absOldPositionSize = abs(oldPositionSize)
714714 if (if ((absOldPositionSize >= _size))
715715 then (_size > 0)
716716 else false)
717717 then {
718718 let isPartialClose = (absOldPositionSize > _size)
719719 let $t03189032341 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
720720 let exchangedQuoteAssetAmount = $t03189032341._1
721721 let quoteAssetReserveAfter = $t03189032341._2
722722 let baseAssetReserveAfter = $t03189032341._3
723723 let totalPositionSizeAfter = $t03189032341._4
724724 let exchangedPositionSize = if ((oldPositionSize > 0))
725725 then -(_size)
726726 else _size
727727 let $t03255632780 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
728728 let oldPositionNotional = $t03255632780._1
729729 let unrealizedPnl = $t03255632780._2
730730 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
731731 let realizedPnl = muld(unrealizedPnl, realizedRatio)
732732 let $t03312133367 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
733733 let remainMarginBefore = $t03312133367._1
734734 let x1 = $t03312133367._2
735735 let x2 = $t03312133367._3
736736 let rolloverFee = $t03312133367._4
737737 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
738738 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
739739 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
740740 let remainOpenNotional = if ((oldPositionSize > 0))
741741 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
742742 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
743743 let newPositionSize = (oldPositionSize + exchangedPositionSize)
744744 let $t03477335159 = if ((newPositionSize == 0))
745745 then $Tuple2(0, 0)
746746 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
747747 let newPositionOpenNotional = $t03477335159._1
748748 let newPositionLstUpdCPF = $t03477335159._2
749749 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
750750 let marginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
751751 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
752752 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
753753 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
754754 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
755755 let marginToTrader = if ((0 > marginToTraderRaw))
756756 then if (_liquidate)
757757 then 0
758758 else throw("Invalid internalClosePosition params: unable to pay fee")
759759 else marginToTraderRaw
760760 let newPositionMargin = if (_addToMargin)
761761 then (newPositionMarginWithSameRatio + marginToTrader)
762762 else newPositionMarginWithSameRatio
763763 if (if ((_minQuoteAssetAmount != 0))
764764 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
765765 else false)
766766 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
767767 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
768768 then isPartialClose
769769 else false)
770770 then 0
771771 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
772772 then abs(exchangedPositionSize)
773773 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
774774 then abs(exchangedPositionSize)
775775 else 0)), (openInterestLong() - (if (isLongPosition)
776776 then openNotionalDelta
777777 else 0)), (openInterestShort() - (if (!(isLongPosition))
778778 then openNotionalDelta
779779 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
780780 }
781781 else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
782782 }
783783
784784
785785 func getTerminalAmmState () = {
786786 let _positionSize = totalPositionSize()
787787 if ((_positionSize == 0))
788788 then $Tuple2(qtAstR(), bsAstR())
789789 else {
790790 let direction = (_positionSize > 0)
791791 let $t03840638585 = swapOutput(direction, abs(_positionSize), false)
792792 let currentNetMarketValue = $t03840638585._1
793793 let terminalQuoteAssetReserve = $t03840638585._2
794794 let terminalBaseAssetReserve = $t03840638585._3
795795 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
796796 }
797797 }
798798
799799
800800 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
801801 let b = toBigInt(baseAssetReserve)
802802 let sz = toBigInt(totalPositionSize)
803803 let q = toBigInt(quoteAssetReserve)
804804 let p = toBigInt(targetPrice)
805805 let k = bmuld(q, b)
806806 let newB = (b + sz)
807807 let newQ = bdivd(k, newB)
808808 let z = bdivd(newQ, newB)
809809 let result = bdivd(p, z)
810810 toInt(result)
811811 }
812812
813813
814814 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
815815 let _positionSize = totalPositionSize()
816816 if ((_positionSize == 0))
817817 then {
818818 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
819819 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
820820 }
821821 else {
822822 let direction = (_positionSize > 0)
823823 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
824824 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
825825 let newBsAstW = DECIMAL_UNIT
826826 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
827827 $Tuple3(newQtAstW, newBsAstW, marginToVault)
828828 }
829829 }
830830
831831
832832 func getFunding () = {
833833 let underlyingPrice = getOraclePrice()
834834 let spotPrice = getSpotPrice()
835835 let premium = (spotPrice - underlyingPrice)
836836 if (if (isMarketClosed())
837837 then true
838838 else if ((fundingMode() == FUNDING_ASYMMETRIC))
839839 then if ((totalShortPositionSize() == 0))
840840 then true
841841 else (totalLongPositionSize() == 0)
842842 else false)
843843 then $Tuple3(0, 0, 0)
844844 else if ((0 > premium))
845845 then {
846846 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
847847 if ((fundingMode() == FUNDING_ASYMMETRIC))
848848 then {
849849 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
850850 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
851851 }
852852 else {
853853 let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
854854 let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
855855 let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
856856 $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
857857 }
858858 }
859859 else {
860860 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
861861 if ((fundingMode() == FUNDING_ASYMMETRIC))
862862 then {
863863 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
864864 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
865865 }
866866 else {
867867 let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
868868 let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
869869 let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
870870 $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
871871 }
872872 }
873873 }
874874
875875
876876 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
877877 let baseFeeRaw = fee()
878878 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
879879 let $t04324943744 = if ((_artifactId != ""))
880880 then {
881881 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
882882 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
883883 then {
884884 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
885885 let adjustedFee = muld(baseFee, reduction)
886886 $Tuple2(adjustedFee, true)
887887 }
888888 else throw("Invalid attached artifact")
889889 }
890890 else $Tuple2(baseFee, false)
891891 let adjustedFee = $t04324943744._1
892892 let burnArtifact = $t04324943744._2
893893 $Tuple2(adjustedFee, burnArtifact)
894894 }
895895
896896
897897 func getForTraderWithArtifact (_trader,_artifactId) = {
898898 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
899899 if ((doGetFeeDiscount == doGetFeeDiscount))
900900 then {
901901 let feeDiscount = match doGetFeeDiscount {
902902 case x: Int =>
903903 x
904904 case _ =>
905905 throw("Invalid computeFeeDiscount result")
906906 }
907907 let $t04409044164 = getAdjustedFee(_artifactId, feeDiscount)
908908 let adjustedFee = $t04409044164._1
909909 let burnArtifact = $t04409044164._2
910910 $Tuple2(adjustedFee, burnArtifact)
911911 }
912912 else throw("Strict value is not equal to itself.")
913913 }
914914
915915
916916 func getArtifactId (i) = {
917917 let artifactId = if ((size(i.payments) > 1))
918918 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
919919 else ""
920920 artifactId
921921 }
922922
923923
924924 func distributeFee (_feeAmount) = {
925925 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
926926 let feeToVault = (_feeAmount - feeToStakers)
927927 $Tuple2(feeToStakers, feeToVault)
928928 }
929929
930930
931931 func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_minInitMarginRatio,_positionMode) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_minInitMarginRatio, _minInitMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread), IntegerEntry(k_maxOpenNotional, _maxOpenNotional), IntegerEntry(k_feeToStakersPercent, _feeToStakersPercent), IntegerEntry(k_maxOracleDelay, _maxOracleDelay), IntegerEntry(k_rolloverFee, _rolloverFee), IntegerEntry(k_fundingMode, _fundingMode), IntegerEntry(k_oracleMode, _oracleMode), IntegerEntry(k_positionMode, _positionMode)]
932932
933933
934934 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)]
935935
936936
937937 func incrementPositionSequenceNumber (_isNewPosition,_trader,_direction) = {
938938 let positionKey = ((_trader + "_") + toString(_direction))
939939 if (_isNewPosition)
940940 then {
941941 let currentSequence = lastSequence()
942942 [IntegerEntry(toCompositeKey(k_positionSequence, positionKey), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
943943 }
944944 else nil
945945 }
946946
947947
948948 func updatePositionFee (_isNewPosition,_trader,_direction,_fee) = {
949949 let positionKey = ((_trader + "_") + toString(_direction))
950950 if (_isNewPosition)
951951 then [IntegerEntry(toCompositeKey(k_positionFee, positionKey), _fee)]
952952 else nil
953953 }
954954
955955
956956 func updatePosition (_trader,_size,_margin,_openNotional,_latestCumulativePremiumFraction,_latestTimestamp) = {
957957 let direction = getDirection(_size)
958958 let positionKey = ((_trader + "_") + toString(direction))
959959 [IntegerEntry(toCompositeKey(k_positionSize, positionKey), _size), IntegerEntry(toCompositeKey(k_positionMargin, positionKey), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, positionKey), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey), _latestCumulativePremiumFraction), IntegerEntry(toCompositeKey(k_positionLastUpdatedTimestamp, positionKey), _latestTimestamp)]
960960 }
961961
962962
963963 func updateAmmReserves (_qtAstR,_bsAstR) = if (if ((0 > _qtAstR))
964964 then true
965965 else (0 > _bsAstR))
966966 then throw("Invalid amount to update reserves")
967967 else if (if ((_qtAstR != qtAstR0()))
968968 then true
969969 else (_bsAstR != bsAstR0()))
970970 then [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
971971 else nil
972972
973973
974974 func updateAmmWeights (_qtAstW,_bsAstW) = if (if ((_qtAstW != qtAstW()))
975975 then true
976976 else (_bsAstW != bsAstW()))
977977 then [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
978978 else nil
979979
980980
981981 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
982982 let _qtAstW = qtAstW()
983983 let _bsAstW = bsAstW()
984984 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
985985 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " - ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
986986 else (updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize), IntegerEntry(k_openInterestLong, _totalLongOpenNotional), IntegerEntry(k_openInterestShort, _totalShortOpenNotional)])
987987 }
988988
989989
990990 func deletePosition (_trader,_direction) = {
991991 let positionKey = ((_trader + "_") + toString(_direction))
992992 [DeleteEntry(toCompositeKey(k_positionSize, positionKey)), DeleteEntry(toCompositeKey(k_positionMargin, positionKey)), DeleteEntry(toCompositeKey(k_positionOpenNotional, positionKey)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey)), DeleteEntry(toCompositeKey(k_positionFee, positionKey)), DeleteEntry(toCompositeKey(k_positionLastUpdatedTimestamp, positionKey))]
993993 }
994994
995995
996996 func withdraw (_address,_amount) = {
997997 let balance = assetBalance(this, quoteAsset())
998998 if ((_amount > balance))
999999 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
10001000 else [ScriptTransfer(_address, _amount, quoteAsset())]
10011001 }
10021002
10031003
10041004 func updateBalance (_balance) = if ((0 > _balance))
10051005 then throw("Balance")
10061006 else if (if ((cbalance0() == 0))
10071007 then true
10081008 else (cbalance0() != _balance))
10091009 then [IntegerEntry(k_balance, _balance)]
10101010 else nil
10111011
10121012
10131013 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
10141014
10151015
10161016 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
10171017 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
10181018 else nil
10191019
10201020
10211021 @Callable(i)
10221022 func pause () = if ((i.caller != adminAddress()))
10231023 then throw("Invalid pause params")
10241024 else [BooleanEntry(k_paused, true)]
10251025
10261026
10271027
10281028 @Callable(i)
10291029 func unpause () = if ((i.caller != adminAddress()))
10301030 then throw("Invalid unpause params")
10311031 else [BooleanEntry(k_paused, false)]
10321032
10331033
10341034
10351035 @Callable(i)
10361036 func setCloseOnly () = if ((i.caller != adminAddress()))
10371037 then throw("Invalid setCloseOnly params")
10381038 else [BooleanEntry(k_closeOnly, true)]
10391039
10401040
10411041
10421042 @Callable(i)
10431043 func unsetCloseOnly () = if ((i.caller != adminAddress()))
10441044 then throw("Invalid unsetCloseOnly params")
10451045 else [BooleanEntry(k_closeOnly, false)]
10461046
10471047
10481048
10491049 @Callable(i)
10501050 func changeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10511051 then true
10521052 else (_quoteAssetAmount == 0))
10531053 then throw("Invalid changeLiquidity params")
10541054 else {
10551055 let _qtAstR = qtAstR()
10561056 let _bsAstR = bsAstR()
10571057 let _qtAstW = qtAstW()
10581058 let _bsAstW = bsAstW()
10591059 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10601060 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10611061 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10621062 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
10631063 let $t05304953200 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
10641064 let newQuoteAssetWeight = $t05304953200._1
10651065 let newBaseAssetWeight = $t05304953200._2
10661066 let marginToVault = $t05304953200._3
10671067 let doExchangePnL = if ((marginToVault != 0))
10681068 then {
10691069 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10701070 if ((doExchangePnL == doExchangePnL))
10711071 then nil
10721072 else throw("Strict value is not equal to itself.")
10731073 }
10741074 else nil
10751075 if ((doExchangePnL == doExchangePnL))
10761076 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10771077 else throw("Strict value is not equal to itself.")
10781078 }
10791079
10801080
10811081
10821082 @Callable(i)
1083-func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_baseOracleData,_quoteOracleData,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _fundingPeriod))
1083+func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_baseOracleData,_quoteOracleData,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _fundingPeriod))
10841084 then true
10851085 else (0 >= _initMarginRatio))
10861086 then true
10871087 else (_initMarginRatio > DECIMAL_UNIT))
10881088 then true
10891089 else (0 >= _minInitMarginRatio))
10901090 then true
1091- else (_minInitMarginRatio > DECIMAL_UNIT))
1092- then true
1093- else (_initMarginRatio >= _minInitMarginRatio))
1091+ else (_initMarginRatio > _minInitMarginRatio))
10941092 then true
10951093 else (0 >= _mmr))
10961094 then true
10971095 else (0 >= _liquidationFeeRatio))
10981096 then true
10991097 else (0 >= _fee))
11001098 then true
11011099 else (0 >= _spreadLimit))
11021100 then true
11031101 else (0 >= _maxPriceImpact))
11041102 then true
11051103 else (0 >= _partialLiquidationRatio))
11061104 then true
11071105 else (0 >= _maxPriceSpread))
11081106 then true
11091107 else (0 >= _maxOpenNotional))
11101108 then true
11111109 else (0 >= _feeToStakersPercent))
11121110 then true
11131111 else (_feeToStakersPercent > DECIMAL_UNIT))
11141112 then true
11151113 else (0 > _maxOracleDelay))
11161114 then true
11171115 else (0 >= _rolloverFee))
11181116 then true
11191117 else if ((_fundingMode != FUNDING_SYMMETRIC))
11201118 then (_fundingMode != FUNDING_ASYMMETRIC)
11211119 else false)
11221120 then true
11231121 else if ((_oracleMode != ORACLE_PLAIN))
11241122 then (_oracleMode != ORACLE_JIT)
11251123 else false)
11261124 then true
11271125 else if ((_positionMode != POSITION_DIRECT))
11281126 then (_positionMode != POSITION_ORDER)
11291127 else false)
11301128 then true
11311129 else !(initialized()))
11321130 then true
11331131 else (i.caller != adminAddress()))
11341132 then throw("Invalid changeSettings params")
11351133 else (updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode, _oracleMode, _minInitMarginRatio, _positionMode) ++ [StringEntry(k_baseOracle, _baseOracleData), StringEntry(k_quoteOracle, _quoteOracleData)])
11361134
11371135
11381136
11391137 @Callable(i)
1140-func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
1138+func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode,_oracleMode,_minInitMarginRatio,_positionMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
11411139 then true
11421140 else (0 >= _bsAstR))
11431141 then true
11441142 else (0 >= _fundingPeriod))
11451143 then true
11461144 else (0 >= _initMarginRatio))
11471145 then true
11481146 else (_initMarginRatio > DECIMAL_UNIT))
11491147 then true
11501148 else (0 >= _minInitMarginRatio))
1151- then true
1152- else (_minInitMarginRatio > DECIMAL_UNIT))
11531149 then true
11541150 else (_initMarginRatio > _minInitMarginRatio))
11551151 then true
11561152 else (0 >= _mmr))
11571153 then true
11581154 else (0 >= _liquidationFeeRatio))
11591155 then true
11601156 else (0 >= _fee))
11611157 then true
11621158 else (0 >= _spreadLimit))
11631159 then true
11641160 else (0 >= _maxPriceImpact))
11651161 then true
11661162 else (0 >= _partialLiquidationRatio))
11671163 then true
11681164 else (0 >= _maxPriceSpread))
11691165 then true
11701166 else (0 >= _maxOpenNotional))
11711167 then true
11721168 else (0 >= _feeToStakersPercent))
11731169 then true
11741170 else (_feeToStakersPercent > DECIMAL_UNIT))
11751171 then true
11761172 else (0 > _maxOracleDelay))
11771173 then true
11781174 else (0 >= _rolloverFee))
11791175 then true
11801176 else if ((_fundingMode != FUNDING_SYMMETRIC))
11811177 then (_fundingMode != FUNDING_ASYMMETRIC)
11821178 else false)
11831179 then true
11841180 else if ((_oracleMode != ORACLE_PLAIN))
11851181 then (_oracleMode != ORACLE_JIT)
11861182 else false)
11871183 then true
11881184 else if ((_positionMode != POSITION_DIRECT))
11891185 then (_positionMode != POSITION_ORDER)
11901186 else false)
11911187 then true
11921188 else initialized())
11931189 then true
11941190 else (i.caller != this))
11951191 then throw("Invalid initialize parameters")
11961192 else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode, _oracleMode, _minInitMarginRatio, _positionMode)) ++ updateFunding((lastTimestamp() + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_baseOracle, _baseOracleData), StringEntry(k_quoteOracle, _quoteOracleData), StringEntry(k_coordinatorAddress, toString(addressFromStringValue(_coordinator)))])
11971193
11981194
11991195
12001196 @Callable(i)
12011197 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink,_priceUpdate) = {
12021198 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
12031199 if ((updateOracle == updateOracle))
12041200 then {
12051201 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
12061202 if ((sync == sync))
12071203 then {
12081204 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
12091205 if ((ensureCalledOnce == ensureCalledOnce))
12101206 then {
12111207 let _trader = getActualCaller(i)
12121208 let _rawAmount = i.payments[0].amount
12131209 let _assetId = i.payments[0].assetId
12141210 let _assetIdStr = toBase58String(value(_assetId))
12151211 let isQuoteAsset = (_assetId == quoteAsset())
12161212 if (if (if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
12171213 then (_direction != DIR_SHORT)
12181214 else false)
12191215 then true
12201216 else (0 >= _rawAmount))
12211217 then true
12221218 else !(initialized()))
12231219 then true
12241220 else !(isQuoteAsset))
12251221 then true
12261222 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
12271223 then true
12281224 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), minInitMarginRatio(), false)))
12291225 then true
12301226 else !(requireSenderCanWorkWithPositions(i.caller)))
12311227 then true
12321228 else paused())
12331229 then true
12341230 else closeOnly())
12351231 then true
12361232 else isMarketClosed())
12371233 then throw("Invalid increasePosition parameters")
12381234 else {
1239- let $t06054060689 = getForTraderWithArtifact(_trader, getArtifactId(i))
1240- let adjustedFee = $t06054060689._1
1241- let burnArtifact = $t06054060689._2
1235+ let $t06046360612 = getForTraderWithArtifact(_trader, getArtifactId(i))
1236+ let adjustedFee = $t06046360612._1
1237+ let burnArtifact = $t06046360612._2
12421238 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
12431239 let distributeFeeAmount = (_rawAmount - _amount)
12441240 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
12451241 if ((referrerFeeAny == referrerFeeAny))
12461242 then {
12471243 let referrerFee = match referrerFeeAny {
12481244 case x: Int =>
12491245 x
12501246 case _ =>
12511247 throw("Invalid referrerFee")
12521248 }
12531249 let feeAmount = (distributeFeeAmount - referrerFee)
1254- let $t06118561365 = getPosition(_trader, _direction)
1255- let oldPositionSize = $t06118561365._1
1256- let oldPositionMargin = $t06118561365._2
1257- let oldPositionOpenNotional = $t06118561365._3
1258- let oldPositionLstUpdCPF = $t06118561365._4
1259- let oldPositionTimestamp = $t06118561365._5
1250+ let $t06110861288 = getPosition(_trader, _direction)
1251+ let oldPositionSize = $t06110861288._1
1252+ let oldPositionMargin = $t06110861288._2
1253+ let oldPositionOpenNotional = $t06110861288._3
1254+ let oldPositionLstUpdCPF = $t06110861288._4
1255+ let oldPositionTimestamp = $t06110861288._5
12601256 let isNewPosition = (oldPositionSize == 0)
12611257 let isSameDirection = if ((oldPositionSize > 0))
12621258 then (_direction == DIR_LONG)
12631259 else (_direction == DIR_SHORT)
12641260 let expandExisting = if (!(isNewPosition))
12651261 then isSameDirection
12661262 else false
12671263 let isAdd = (_direction == DIR_LONG)
1268- let $t06165464787 = if (if (isNewPosition)
1264+ let $t06157764710 = if (if (isNewPosition)
12691265 then true
12701266 else expandExisting)
12711267 then {
12721268 let openNotional = muld(_amount, _leverage)
1273- let $t06216362336 = swapInput(isAdd, openNotional)
1274- let amountBaseAssetBought = $t06216362336._1
1275- let quoteAssetReserveAfter = $t06216362336._2
1276- let baseAssetReserveAfter = $t06216362336._3
1277- let totalPositionSizeAfter = $t06216362336._4
1269+ let $t06208662259 = swapInput(isAdd, openNotional)
1270+ let amountBaseAssetBought = $t06208662259._1
1271+ let quoteAssetReserveAfter = $t06208662259._2
1272+ let baseAssetReserveAfter = $t06208662259._3
1273+ let totalPositionSizeAfter = $t06208662259._4
12781274 if (if ((_minBaseAssetAmount != 0))
12791275 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12801276 else false)
12811277 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12821278 else {
12831279 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12841280 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12851281 then openNotional
12861282 else 0))
12871283 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12881284 then openNotional
12891285 else 0))
1290- let $t06288263157 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1291- let remainMargin = $t06288263157._1
1292- let x1 = $t06288263157._2
1293- let x2 = $t06288263157._3
1294- let rolloverFee = $t06288263157._4
1286+ let $t06280563080 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1287+ let remainMargin = $t06280563080._1
1288+ let x1 = $t06280563080._2
1289+ let x2 = $t06280563080._3
1290+ let rolloverFee = $t06280563080._4
12951291 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12961292 then throw("Over max spread limit")
12971293 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12981294 then throw("Over max open notional")
12991295 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
13001296 then abs(amountBaseAssetBought)
13011297 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
13021298 then abs(amountBaseAssetBought)
13031299 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
13041300 }
13051301 }
13061302 else {
13071303 let openNotional = muld(_amount, _leverage)
1308- let $t06447564603 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1309- let oldPositionNotional = $t06447564603._1
1310- let unrealizedPnl = $t06447564603._2
1304+ let $t06439864526 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1305+ let oldPositionNotional = $t06439864526._1
1306+ let unrealizedPnl = $t06439864526._2
13111307 if ((oldPositionNotional > openNotional))
13121308 then throw("Use decreasePosition to decrease position size")
13131309 else throw("Close position first")
13141310 }
1315- let newPositionSize = $t06165464787._1
1316- let newPositionRemainMargin = $t06165464787._2
1317- let newPositionOpenNotional = $t06165464787._3
1318- let newPositionLatestCPF = $t06165464787._4
1319- let newPositionTimestamp = $t06165464787._5
1320- let baseAssetReserveAfter = $t06165464787._6
1321- let quoteAssetReserveAfter = $t06165464787._7
1322- let totalPositionSizeAfter = $t06165464787._8
1323- let openInterestNotionalAfter = $t06165464787._9
1324- let totalLongAfter = $t06165464787._10
1325- let totalShortAfter = $t06165464787._11
1326- let totalLongOpenInterestAfter = $t06165464787._12
1327- let totalShortOpenInterestAfter = $t06165464787._13
1328- let rolloverFee = $t06165464787._14
1329- let $t06479364864 = distributeFee((feeAmount + rolloverFee))
1330- let feeToStakers = $t06479364864._1
1331- let feeToVault = $t06479364864._2
1311+ let newPositionSize = $t06157764710._1
1312+ let newPositionRemainMargin = $t06157764710._2
1313+ let newPositionOpenNotional = $t06157764710._3
1314+ let newPositionLatestCPF = $t06157764710._4
1315+ let newPositionTimestamp = $t06157764710._5
1316+ let baseAssetReserveAfter = $t06157764710._6
1317+ let quoteAssetReserveAfter = $t06157764710._7
1318+ let totalPositionSizeAfter = $t06157764710._8
1319+ let openInterestNotionalAfter = $t06157764710._9
1320+ let totalLongAfter = $t06157764710._10
1321+ let totalShortAfter = $t06157764710._11
1322+ let totalLongOpenInterestAfter = $t06157764710._12
1323+ let totalShortOpenInterestAfter = $t06157764710._13
1324+ let rolloverFee = $t06157764710._14
1325+ let $t06471664787 = distributeFee((feeAmount + rolloverFee))
1326+ let feeToStakers = $t06471664787._1
1327+ let feeToVault = $t06471664787._2
13321328 let stake = if ((_amount >= rolloverFee))
13331329 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
13341330 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13351331 if ((stake == stake))
13361332 then {
13371333 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
13381334 if ((depositVault == depositVault))
13391335 then {
13401336 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
13411337 if ((notifyFee == notifyFee))
13421338 then {
13431339 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
13441340 if ((notifyNotional == notifyNotional))
13451341 then ((((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF, newPositionTimestamp) ++ incrementPositionSequenceNumber(isNewPosition, _trader, _direction)) ++ updatePositionFee(isNewPosition, _trader, _direction, adjustedFee)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doBurnArtifact(burnArtifact, i))
13461342 else throw("Strict value is not equal to itself.")
13471343 }
13481344 else throw("Strict value is not equal to itself.")
13491345 }
13501346 else throw("Strict value is not equal to itself.")
13511347 }
13521348 else throw("Strict value is not equal to itself.")
13531349 }
13541350 else throw("Strict value is not equal to itself.")
13551351 }
13561352 }
13571353 else throw("Strict value is not equal to itself.")
13581354 }
13591355 else throw("Strict value is not equal to itself.")
13601356 }
13611357 else throw("Strict value is not equal to itself.")
13621358 }
13631359
13641360
13651361
13661362 @Callable(i)
13671363 func addMargin (_direction,_priceUpdate) = {
13681364 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
13691365 if ((updateOracle == updateOracle))
13701366 then {
13711367 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13721368 if ((sync == sync))
13731369 then {
13741370 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13751371 if ((ensureCalledOnce == ensureCalledOnce))
13761372 then {
13771373 let _trader = toString(i.caller)
13781374 let _amount = i.payments[0].amount
13791375 let _assetId = i.payments[0].assetId
13801376 let _assetIdStr = toBase58String(value(_assetId))
13811377 let isQuoteAsset = (_assetId == quoteAsset())
13821378 if (if (if (if (if (!(isQuoteAsset))
13831379 then true
13841380 else !(requireOpenPosition(toString(i.caller), _direction)))
13851381 then true
13861382 else !(initialized()))
13871383 then true
13881384 else paused())
13891385 then true
13901386 else isMarketClosed())
13911387 then throw("Invalid addMargin parameters")
13921388 else {
1393- let $t06720667386 = getPosition(_trader, _direction)
1394- let oldPositionSize = $t06720667386._1
1395- let oldPositionMargin = $t06720667386._2
1396- let oldPositionOpenNotional = $t06720667386._3
1397- let oldPositionLstUpdCPF = $t06720667386._4
1398- let oldPositionTimestamp = $t06720667386._5
1389+ let $t06712967309 = getPosition(_trader, _direction)
1390+ let oldPositionSize = $t06712967309._1
1391+ let oldPositionMargin = $t06712967309._2
1392+ let oldPositionOpenNotional = $t06712967309._3
1393+ let oldPositionLstUpdCPF = $t06712967309._4
1394+ let oldPositionTimestamp = $t06712967309._5
13991395 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
14001396 if ((stake == stake))
14011397 then {
1402- let $t06752667752 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1403- let remainMargin = $t06752667752._1
1404- let badDebt = $t06752667752._2
1405- let rolloverFee = $t06752667752._3
1398+ let $t06744967675 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1399+ let remainMargin = $t06744967675._1
1400+ let badDebt = $t06744967675._2
1401+ let rolloverFee = $t06744967675._3
14061402 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
14071403 let checkMinMargin = requireMoreMarginRatio(marginRatio, minInitMarginRatio(), false)
14081404 if ((checkMinMargin == checkMinMargin))
14091405 then {
14101406 let doTransferFeeToStakers = if ((rolloverFee > 0))
14111407 then {
1412- let $t06800868067 = distributeFee(rolloverFee)
1413- let feeToStakers = $t06800868067._1
1414- let feeToVault = $t06800868067._2
1408+ let $t06793167990 = distributeFee(rolloverFee)
1409+ let feeToStakers = $t06793167990._1
1410+ let feeToVault = $t06793167990._2
14151411 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
14161412 if ((unstake == unstake))
14171413 then {
14181414 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14191415 if ((lockBadDebt == lockBadDebt))
14201416 then transferFee(feeToStakers)
14211417 else throw("Strict value is not equal to itself.")
14221418 }
14231419 else throw("Strict value is not equal to itself.")
14241420 }
14251421 else nil
14261422 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14271423 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14281424 else throw("Strict value is not equal to itself.")
14291425 }
14301426 else throw("Strict value is not equal to itself.")
14311427 }
14321428 else throw("Strict value is not equal to itself.")
14331429 }
14341430 }
14351431 else throw("Strict value is not equal to itself.")
14361432 }
14371433 else throw("Strict value is not equal to itself.")
14381434 }
14391435 else throw("Strict value is not equal to itself.")
14401436 }
14411437
14421438
14431439
14441440 @Callable(i)
14451441 func removeMargin (_amount,_direction,_priceUpdate) = {
14461442 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
14471443 if ((updateOracle == updateOracle))
14481444 then {
14491445 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14501446 if ((sync == sync))
14511447 then {
14521448 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14531449 if ((ensureCalledOnce == ensureCalledOnce))
14541450 then {
14551451 let _trader = toString(i.caller)
14561452 if (if (if (if (if ((0 >= _amount))
14571453 then true
14581454 else !(requireOpenPosition(_trader, _direction)))
14591455 then true
14601456 else !(initialized()))
14611457 then true
14621458 else paused())
14631459 then true
14641460 else isMarketClosed())
14651461 then throw("Invalid removeMargin parameters")
14661462 else {
1467- let $t06956869748 = getPosition(_trader, _direction)
1468- let oldPositionSize = $t06956869748._1
1469- let oldPositionMargin = $t06956869748._2
1470- let oldPositionOpenNotional = $t06956869748._3
1471- let oldPositionLstUpdCPF = $t06956869748._4
1472- let oldPositionTimestamp = $t06956869748._5
1473- let $t06975470003 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1474- let remainMargin = $t06975470003._1
1475- let badDebt = $t06975470003._2
1476- let fundingPayment = $t06975470003._3
1477- let rolloverFee = $t06975470003._4
1463+ let $t06949169671 = getPosition(_trader, _direction)
1464+ let oldPositionSize = $t06949169671._1
1465+ let oldPositionMargin = $t06949169671._2
1466+ let oldPositionOpenNotional = $t06949169671._3
1467+ let oldPositionLstUpdCPF = $t06949169671._4
1468+ let oldPositionTimestamp = $t06949169671._5
1469+ let $t06967769926 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1470+ let remainMargin = $t06967769926._1
1471+ let badDebt = $t06967769926._2
1472+ let fundingPayment = $t06967769926._3
1473+ let rolloverFee = $t06967769926._4
14781474 if ((badDebt != 0))
14791475 then throw("Invalid removed margin amount")
14801476 else {
14811477 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
14821478 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
14831479 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
14841480 else {
1485- let $t07038970448 = distributeFee(rolloverFee)
1486- let feeToStakers = $t07038970448._1
1487- let feeToVault = $t07038970448._2
1481+ let $t07031270371 = distributeFee(rolloverFee)
1482+ let feeToStakers = $t07031270371._1
1483+ let feeToVault = $t07031270371._2
14881484 let doTransferFeeToStakers = if ((rolloverFee > 0))
14891485 then {
14901486 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14911487 if ((lockBadDebt == lockBadDebt))
14921488 then transferFee(feeToStakers)
14931489 else throw("Strict value is not equal to itself.")
14941490 }
14951491 else nil
14961492 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14971493 then {
14981494 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
14991495 if ((unstake == unstake))
15001496 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
15011497 else throw("Strict value is not equal to itself.")
15021498 }
15031499 else throw("Strict value is not equal to itself.")
15041500 }
15051501 }
15061502 }
15071503 }
15081504 else throw("Strict value is not equal to itself.")
15091505 }
15101506 else throw("Strict value is not equal to itself.")
15111507 }
15121508 else throw("Strict value is not equal to itself.")
15131509 }
15141510
15151511
15161512
15171513 @Callable(i)
15181514 func closePosition (_size,_direction,_minQuoteAssetAmount,_addToMargin,_priceUpdate) = {
15191515 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
15201516 if ((updateOracle == updateOracle))
15211517 then {
15221518 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15231519 if ((sync == sync))
15241520 then {
15251521 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
15261522 if ((ensureCalledOnce == ensureCalledOnce))
15271523 then {
15281524 let _trader = getActualCaller(i)
15291525 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
15301526 let positionFee = getPositionFee(_trader, _direction)
15311527 if (if (if (if (if (if (!(requireOpenPosition(_trader, _direction)))
15321528 then true
15331529 else !(initialized()))
15341530 then true
15351531 else paused())
15361532 then true
15371533 else (0 >= _size))
15381534 then true
15391535 else (0 > _minQuoteAssetAmount))
15401536 then true
15411537 else isMarketClosed())
15421538 then throw("Invalid closePosition parameters")
15431539 else {
15441540 let oldPositionTimestamp = getPosition(_trader, _direction)._5
1545- let $t07278373386 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1546- let newPositionSize = $t07278373386._1
1547- let newPositionMargin = $t07278373386._2
1548- let newPositionOpenNotional = $t07278373386._3
1549- let newPositionLstUpdCPF = $t07278373386._4
1550- let positionBadDebt = $t07278373386._5
1551- let realizedPnl = $t07278373386._6
1552- let marginToTrader = $t07278373386._7
1553- let quoteAssetReserveAfter = $t07278373386._8
1554- let baseAssetReserveAfter = $t07278373386._9
1555- let totalPositionSizeAfter = $t07278373386._10
1556- let openInterestNotionalAfter = $t07278373386._11
1557- let totalLongAfter = $t07278373386._12
1558- let totalShortAfter = $t07278373386._13
1559- let totalLongOpenInterestAfter = $t07278373386._14
1560- let totalShortOpenInterestAfter = $t07278373386._15
1561- let realizedFee = $t07278373386._16
1541+ let $t07270673309 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1542+ let newPositionSize = $t07270673309._1
1543+ let newPositionMargin = $t07270673309._2
1544+ let newPositionOpenNotional = $t07270673309._3
1545+ let newPositionLstUpdCPF = $t07270673309._4
1546+ let positionBadDebt = $t07270673309._5
1547+ let realizedPnl = $t07270673309._6
1548+ let marginToTrader = $t07270673309._7
1549+ let quoteAssetReserveAfter = $t07270673309._8
1550+ let baseAssetReserveAfter = $t07270673309._9
1551+ let totalPositionSizeAfter = $t07270673309._10
1552+ let openInterestNotionalAfter = $t07270673309._11
1553+ let totalLongAfter = $t07270673309._12
1554+ let totalShortAfter = $t07270673309._13
1555+ let totalLongOpenInterestAfter = $t07270673309._14
1556+ let totalShortOpenInterestAfter = $t07270673309._15
1557+ let realizedFee = $t07270673309._16
15621558 if ((positionBadDebt > 0))
15631559 then throw("Invalid closePosition parameters: bad debt")
15641560 else if ((oldPositionTimestamp >= lastTimestamp()))
15651561 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
15661562 else {
15671563 let isPartialClose = (newPositionSize != 0)
15681564 let withdrawAmount = (marginToTrader + realizedFee)
15691565 let ammBalance = (cbalance() - withdrawAmount)
15701566 let ammNewBalance = if ((0 > ammBalance))
15711567 then 0
15721568 else ammBalance
15731569 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
15741570 if ((unstake == unstake))
15751571 then {
15761572 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), realizedFee)])
15771573 if ((referrerFeeAny == referrerFeeAny))
15781574 then {
15791575 let referrerFee = match referrerFeeAny {
15801576 case x: Int =>
15811577 x
15821578 case _ =>
15831579 throw("Invalid referrerFee")
15841580 }
1585- let $t07435874431 = distributeFee((realizedFee - referrerFee))
1586- let feeToStakers = $t07435874431._1
1587- let feeToVault = $t07435874431._2
1581+ let $t07428174354 = distributeFee((realizedFee - referrerFee))
1582+ let feeToStakers = $t07428174354._1
1583+ let feeToVault = $t07428174354._2
15881584 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
15891585 if ((depositVault == depositVault))
15901586 then {
15911587 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
15921588 if ((notifyFee == notifyFee))
15931589 then {
15941590 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
15951591 if ((notifyNotional == notifyNotional))
15961592 then (((((if (isPartialClose)
15971593 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
15981594 else deletePosition(_trader, _direction)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
15991595 then withdraw(_traderAddress, marginToTrader)
16001596 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
16011597 else throw("Strict value is not equal to itself.")
16021598 }
16031599 else throw("Strict value is not equal to itself.")
16041600 }
16051601 else throw("Strict value is not equal to itself.")
16061602 }
16071603 else throw("Strict value is not equal to itself.")
16081604 }
16091605 else throw("Strict value is not equal to itself.")
16101606 }
16111607 }
16121608 }
16131609 else throw("Strict value is not equal to itself.")
16141610 }
16151611 else throw("Strict value is not equal to itself.")
16161612 }
16171613 else throw("Strict value is not equal to itself.")
16181614 }
16191615
16201616
16211617
16221618 @Callable(i)
16231619 func liquidate (_trader,_direction,_priceUpdate) = {
16241620 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
16251621 if ((updateOracle == updateOracle))
16261622 then {
16271623 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16281624 if ((sync == sync))
16291625 then {
16301626 let spotMarginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
16311627 let liquidationMarginRatio = if (isOverFluctuationLimit())
16321628 then {
16331629 let oracleMarginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_ORACLE)
16341630 vmax(spotMarginRatio, oracleMarginRatio)
16351631 }
16361632 else spotMarginRatio
16371633 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
16381634 then true
16391635 else !(requireOpenPosition(_trader, _direction)))
16401636 then true
16411637 else !(initialized()))
16421638 then true
16431639 else paused())
16441640 then true
16451641 else isMarketClosed())
16461642 then throw("Unable to liquidate")
16471643 else {
16481644 let oldPositionSize = getPosition(_trader, _direction)._1
16491645 let positionSizeAbs = abs(oldPositionSize)
16501646 let isPartialLiquidation = if (if (if ((spotMarginRatio > liquidationFeeRatio()))
16511647 then (partialLiquidationRatio() > 0)
16521648 else false)
16531649 then (DECIMAL_UNIT > partialLiquidationRatio())
16541650 else false)
16551651 then (muld(positionSizeAbs, getSpotPrice()) > minPartialLiquidationNotional())
16561652 else false
1657- let $t07710577492 = if (isPartialLiquidation)
1653+ let $t07702877415 = if (isPartialLiquidation)
16581654 then {
16591655 let liquidationSize = abs(getPartialLiquidationAmount(_trader, oldPositionSize))
16601656 let liquidationRatio = divd(liquidationSize, positionSizeAbs)
16611657 let liquidationNotional = muld(liquidationSize, getSpotPrice())
16621658 $Tuple2(liquidationRatio, liquidationSize)
16631659 }
16641660 else $Tuple2(0, positionSizeAbs)
1665- let liquidationRatio = $t07710577492._1
1666- let liquidationSize = $t07710577492._2
1667- let $t07749878154 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
1661+ let liquidationRatio = $t07702877415._1
1662+ let liquidationSize = $t07702877415._2
1663+ let $t07742178077 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
16681664 then liquidationSize
16691665 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1670- let newPositionSize = $t07749878154._1
1671- let newPositionMargin = $t07749878154._2
1672- let newPositionOpenNotional = $t07749878154._3
1673- let newPositionLstUpdCPF = $t07749878154._4
1674- let positionBadDebt = $t07749878154._5
1675- let realizedPnl = $t07749878154._6
1676- let marginToTrader = $t07749878154._7
1677- let quoteAssetReserveAfter = $t07749878154._8
1678- let baseAssetReserveAfter = $t07749878154._9
1679- let totalPositionSizeAfter = $t07749878154._10
1680- let openInterestNotionalAfter = $t07749878154._11
1681- let totalLongAfter = $t07749878154._12
1682- let totalShortAfter = $t07749878154._13
1683- let totalLongOpenInterestAfter = $t07749878154._14
1684- let totalShortOpenInterestAfter = $t07749878154._15
1685- let liquidationPenalty = $t07749878154._16
1666+ let newPositionSize = $t07742178077._1
1667+ let newPositionMargin = $t07742178077._2
1668+ let newPositionOpenNotional = $t07742178077._3
1669+ let newPositionLstUpdCPF = $t07742178077._4
1670+ let positionBadDebt = $t07742178077._5
1671+ let realizedPnl = $t07742178077._6
1672+ let marginToTrader = $t07742178077._7
1673+ let quoteAssetReserveAfter = $t07742178077._8
1674+ let baseAssetReserveAfter = $t07742178077._9
1675+ let totalPositionSizeAfter = $t07742178077._10
1676+ let openInterestNotionalAfter = $t07742178077._11
1677+ let totalLongAfter = $t07742178077._12
1678+ let totalShortAfter = $t07742178077._13
1679+ let totalLongOpenInterestAfter = $t07742178077._14
1680+ let totalShortOpenInterestAfter = $t07742178077._15
1681+ let liquidationPenalty = $t07742178077._16
16861682 let feeToLiquidator = (liquidationPenalty / 2)
16871683 let feeToVault = (liquidationPenalty - feeToLiquidator)
16881684 let ammBalance = (cbalance() - liquidationPenalty)
16891685 let newAmmBalance = if ((0 > ammBalance))
16901686 then 0
16911687 else ammBalance
16921688 let lockBadDebt = if ((positionBadDebt > 0))
16931689 then {
16941690 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
16951691 if ((lockBadDebt == lockBadDebt))
16961692 then nil
16971693 else throw("Strict value is not equal to itself.")
16981694 }
16991695 else nil
17001696 if ((lockBadDebt == lockBadDebt))
17011697 then {
17021698 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
17031699 if ((unstake == unstake))
17041700 then {
17051701 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
17061702 if ((depositInsurance == depositInsurance))
17071703 then {
17081704 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
17091705 if ((notifyNotional == notifyNotional))
17101706 then ((((if (isPartialLiquidation)
17111707 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
17121708 else deletePosition(_trader, _direction)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
17131709 else throw("Strict value is not equal to itself.")
17141710 }
17151711 else throw("Strict value is not equal to itself.")
17161712 }
17171713 else throw("Strict value is not equal to itself.")
17181714 }
17191715 else throw("Strict value is not equal to itself.")
17201716 }
17211717 }
17221718 else throw("Strict value is not equal to itself.")
17231719 }
17241720 else throw("Strict value is not equal to itself.")
17251721 }
17261722
17271723
17281724
17291725 @Callable(i)
17301726 func payFunding (_priceUpdate) = {
17311727 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
17321728 if ((updateOracle == updateOracle))
17331729 then {
17341730 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17351731 if ((sync == sync))
17361732 then {
17371733 let fundingBlockTimestamp = nextFundingBlockTimestamp()
17381734 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
17391735 then true
17401736 else !(initialized()))
17411737 then true
17421738 else paused())
17431739 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
17441740 else {
17451741 let underlyingPrice = getOraclePrice()
1746- let $t08037280450 = getFunding()
1747- let shortPremiumFraction = $t08037280450._1
1748- let longPremiumFraction = $t08037280450._2
1749- let premiumToVault = $t08037280450._3
1742+ let $t08029580373 = getFunding()
1743+ let shortPremiumFraction = $t08029580373._1
1744+ let longPremiumFraction = $t08029580373._2
1745+ let premiumToVault = $t08029580373._3
17501746 let doPayFundingToVault = if ((premiumToVault > 0))
17511747 then {
17521748 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
17531749 if ((doPayFundingToVault == doPayFundingToVault))
17541750 then nil
17551751 else throw("Strict value is not equal to itself.")
17561752 }
17571753 else nil
17581754 if ((doPayFundingToVault == doPayFundingToVault))
17591755 then updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
17601756 else throw("Strict value is not equal to itself.")
17611757 }
17621758 }
17631759 else throw("Strict value is not equal to itself.")
17641760 }
17651761 else throw("Strict value is not equal to itself.")
17661762 }
17671763
17681764
17691765
17701766 @Callable(i)
17711767 func updateOracle (_priceUpdate) = if ((oracleMode() == ORACLE_PLAIN))
17721768 then nil
17731769 else {
17741770 let priceUpdates = split_4C(_priceUpdate, "::")
17751771 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
17761772 let baseOracleAddress = baseOracle._1
17771773 let doUpdateBaseOracle = invoke(baseOracleAddress, "updateData", [priceUpdates[0]], nil)
17781774 if ((doUpdateBaseOracle == doUpdateBaseOracle))
17791775 then {
17801776 let quoteOracle = getOracleData(k_quoteOracle)
17811777 let doUpdateQuoteOracle = if (isDefined(quoteOracle))
17821778 then {
17831779 let quoteOracleV = value(quoteOracle)
17841780 let quoteOracleAddress = quoteOracleV._1
17851781 let doUpdateQuoteOracle = invoke(quoteOracleAddress, "updateData", [priceUpdates[1]], nil)
17861782 if ((doUpdateQuoteOracle == doUpdateQuoteOracle))
17871783 then nil
17881784 else throw("Strict value is not equal to itself.")
17891785 }
17901786 else nil
17911787 if ((doUpdateQuoteOracle == doUpdateQuoteOracle))
17921788 then nil
17931789 else throw("Strict value is not equal to itself.")
17941790 }
17951791 else throw("Strict value is not equal to itself.")
17961792 }
17971793
17981794
17991795
18001796 @Callable(i)
18011797 func syncTerminalPriceToOracle () = {
18021798 let _qtAstR = qtAstR()
18031799 let _bsAstR = bsAstR()
1804- let $t08226782633 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1805- let newQuoteAssetWeight = $t08226782633._1
1806- let newBaseAssetWeight = $t08226782633._2
1807- let marginToVault = $t08226782633._3
1800+ let $t08219082556 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1801+ let newQuoteAssetWeight = $t08219082556._1
1802+ let newBaseAssetWeight = $t08219082556._2
1803+ let marginToVault = $t08219082556._3
18081804 let marginToVaultAdj = if (if ((0 > marginToVault))
18091805 then (abs(marginToVault) > cbalance())
18101806 else false)
18111807 then -(cbalance())
18121808 else marginToVault
18131809 let doExchangePnL = if ((marginToVaultAdj != 0))
18141810 then {
18151811 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
18161812 if ((doExchangePnL == doExchangePnL))
18171813 then nil
18181814 else throw("Strict value is not equal to itself.")
18191815 }
18201816 else nil
18211817 if ((doExchangePnL == doExchangePnL))
18221818 then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
18231819 else throw("Strict value is not equal to itself.")
18241820 }
18251821
18261822
18271823
18281824 @Callable(i)
18291825 func ensureCalledOnce () = if ((i.caller != this))
18301826 then throw("Invalid saveCurrentTxId parameters")
18311827 else {
18321828 let txId = toBase58String(i.transactionId)
18331829 let lastTx = valueOrElse(getString(this, k_lastTx), "")
18341830 if ((lastTx != txId))
18351831 then [StringEntry(k_lastTx, txId)]
18361832 else throw("Can not call vAMM methods twice in one tx")
18371833 }
18381834
18391835
18401836
18411837 @Callable(i)
18421838 func migratePosition (_trader) = {
18431839 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
18441840 if (if (isDefined(positionSizeOpt))
18451841 then isDefined(addressFromString(_trader))
18461842 else false)
18471843 then {
18481844 let pSize = getIntegerValue(this, toCompositeKey(k_positionSize, _trader))
18491845 let pMargin = getIntegerValue(this, toCompositeKey(k_positionMargin, _trader))
18501846 let pNotional = getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader))
18511847 let pFraction = getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader))
18521848 let pTimestamp = valueOrElse(getInteger(this, toCompositeKey(k_positionLastUpdatedTimestamp, _trader)), lastBlock.timestamp)
18531849 let pFee = valueOrElse(getInteger(this, toCompositeKey(k_positionFee, _trader)), fee())
18541850 let pSequence = getIntegerValue(this, toCompositeKey(k_positionSequence, _trader))
18551851 let pDirection = getDirection(pSize)
18561852 let positionKey = ((_trader + "_") + toString(pDirection))
18571853 [DeleteEntry(toCompositeKey(k_positionSize, _trader)), DeleteEntry(toCompositeKey(k_positionMargin, _trader)), DeleteEntry(toCompositeKey(k_positionOpenNotional, _trader)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)), DeleteEntry(toCompositeKey(k_positionLastUpdatedTimestamp, _trader)), DeleteEntry(toCompositeKey(k_positionFee, _trader)), DeleteEntry(toCompositeKey(k_positionSequence, _trader)), IntegerEntry(toCompositeKey(k_positionSize, positionKey), pSize), IntegerEntry(toCompositeKey(k_positionMargin, positionKey), pMargin), IntegerEntry(toCompositeKey(k_positionOpenNotional, positionKey), pNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey), pFraction), IntegerEntry(toCompositeKey(k_positionLastUpdatedTimestamp, positionKey), pTimestamp), IntegerEntry(toCompositeKey(k_positionFee, positionKey), pFee), IntegerEntry(toCompositeKey(k_positionSequence, positionKey), pSequence)]
18581854 }
18591855 else throw(("Nothing to migrate for " + _trader))
18601856 }
18611857
18621858
18631859
18641860 @Callable(i)
18651861 func view_calcRemainMarginWithFundingPayment (_trader,_direction,_priceUpdate) = {
18661862 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
18671863 if ((updateOracle == updateOracle))
18681864 then {
18691865 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
18701866 if ((sync == sync))
18711867 then {
1872- let $t08642786563 = getPosition(_trader, _direction)
1873- let positionSize = $t08642786563._1
1874- let positionMargin = $t08642786563._2
1875- let pon = $t08642786563._3
1876- let positionLstUpdCPF = $t08642786563._4
1877- let positionTimestamp = $t08642786563._5
1878- let $t08656686679 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1879- let positionNotional = $t08656686679._1
1880- let unrealizedPnl = $t08656686679._2
1881- let $t08668286906 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1882- let remainMargin = $t08668286906._1
1883- let badDebt = $t08668286906._2
1884- let fundingPayment = $t08668286906._3
1885- let rolloverFee = $t08668286906._4
1868+ let $t08635086486 = getPosition(_trader, _direction)
1869+ let positionSize = $t08635086486._1
1870+ let positionMargin = $t08635086486._2
1871+ let pon = $t08635086486._3
1872+ let positionLstUpdCPF = $t08635086486._4
1873+ let positionTimestamp = $t08635086486._5
1874+ let $t08648986602 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1875+ let positionNotional = $t08648986602._1
1876+ let unrealizedPnl = $t08648986602._2
1877+ let $t08660586829 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1878+ let remainMargin = $t08660586829._1
1879+ let badDebt = $t08660586829._2
1880+ let fundingPayment = $t08660586829._3
1881+ let rolloverFee = $t08660586829._4
18861882 let underlyingPrice = getOraclePrice()
18871883 let spotPrice = getSpotPrice()
18881884 throw(((((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader, _direction))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)) + s(underlyingPrice)) + s(spotPrice)))
18891885 }
18901886 else throw("Strict value is not equal to itself.")
18911887 }
18921888 else throw("Strict value is not equal to itself.")
18931889 }
18941890
18951891
18961892
18971893 @Callable(i)
18981894 func view_getPegAdjustCost (_price) = {
18991895 let _qtAstR = qtAstR()
19001896 let _bsAstR = bsAstR()
19011897 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
19021898 throw(toString(result._3))
19031899 }
19041900
19051901
19061902
19071903 @Callable(i)
19081904 func view_getTerminalAmmPrice () = {
1909- let $t08775987840 = getTerminalAmmState()
1910- let terminalQuoteAssetReserve = $t08775987840._1
1911- let terminalBaseAssetReserve = $t08775987840._2
1905+ let $t08768287763 = getTerminalAmmState()
1906+ let terminalQuoteAssetReserve = $t08768287763._1
1907+ let terminalBaseAssetReserve = $t08768287763._2
19121908 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
19131909 throw(toString(price))
19141910 }
19151911
19161912
19171913
19181914 @Callable(i)
19191915 func view_getFunding (_priceUpdate) = {
19201916 let updateOracle = invoke(this, "updateOracle", [_priceUpdate], nil)
19211917 if ((updateOracle == updateOracle))
19221918 then {
19231919 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19241920 if ((sync == sync))
19251921 then {
19261922 let underlyingPrice = getOraclePrice()
1927- let $t08849288570 = getFunding()
1928- let shortPremiumFraction = $t08849288570._1
1929- let longPremiumFraction = $t08849288570._2
1930- let premiumToVault = $t08849288570._3
1923+ let $t08841588493 = getFunding()
1924+ let shortPremiumFraction = $t08841588493._1
1925+ let longPremiumFraction = $t08841588493._2
1926+ let premiumToVault = $t08841588493._3
19311927 let longFunding = divd(longPremiumFraction, underlyingPrice)
19321928 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
19331929 throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
19341930 }
19351931 else throw("Strict value is not equal to itself.")
19361932 }
19371933 else throw("Strict value is not equal to itself.")
19381934 }
19391935
19401936
19411937
19421938 @Callable(i)
19431939 func computeSpotPrice () = {
19441940 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
19451941 if ((sync == sync))
19461942 then {
19471943 let result = getSpotPrice()
19481944 $Tuple2(nil, result)
19491945 }
19501946 else throw("Strict value is not equal to itself.")
19511947 }
19521948
19531949
19541950
19551951 @Callable(i)
19561952 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
19571953 let result = getForTraderWithArtifact(_trader, _artifactId)
19581954 $Tuple2(nil, result)
19591955 }
19601956
19611957
19621958 @Verifier(tx)
19631959 func verify () = {
19641960 let coordinatorStr = getString(this, k_coordinatorAddress)
19651961 if (isDefined(coordinatorStr))
19661962 then {
19671963 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
19681964 if (isDefined(admin))
19691965 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
19701966 else throw("unable to verify: admin not set in coordinator")
19711967 }
19721968 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
19731969 }
19741970

github/deemru/w8io/026f985 
318.13 ms