tx · CEtTD3RcGxR4kaMChCRvFHnePB6sXuXfpBaYPk8hNfxo

3MuCofTkjmv397dEuRXE3pZxTb4zDWa96uo:  -0.05100000 Waves

2022.08.10 10:50 [2178067] smart account 3MuCofTkjmv397dEuRXE3pZxTb4zDWa96uo > SELF 0.00000000 Waves

{ "type": 13, "id": "CEtTD3RcGxR4kaMChCRvFHnePB6sXuXfpBaYPk8hNfxo", "fee": 5100000, "feeAssetId": null, "timestamp": 1660117849506, "version": 2, "chainId": 84, "sender": "3MuCofTkjmv397dEuRXE3pZxTb4zDWa96uo", "senderPublicKey": "HGKkqEdKKPVXHMq25FyB6nm1kyvrixu1a8Av6wc9t5CG", "proofs": [ "FNdCiVLJTwpMxC9PtXTUeYHnbahpuBWiNnGN9Kxmy7v4LwERa4ZSQokPZufPxxwucJ7oeht5Gxz1SD4CmJtLyDf" ], "script": "base64:BgJZCAISABIAEgMKAQESAwoBARIJCgcBAQEBAQEBEg4KDAEBAQEBAQEICAgBARIFCgMBAQESBQoDAQEBEgASAwoBARIAEgMKAQgSABIDCgEIEgMKAQgSBAoCCAF3AAlrX29yYV9rZXkCCWtfb3JhX2tleQAPa19vcmFfYmxvY2tfa2V5Ag9rX29yYV9ibG9ja19rZXkABWtfb3JhAgVrX29yYQAJa19iYWxhbmNlAglrX2JhbGFuY2UADmtfcG9zaXRpb25TaXplAg5rX3Bvc2l0aW9uU2l6ZQAQa19wb3NpdGlvbk1hcmdpbgIQa19wb3NpdGlvbk1hcmdpbgAWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAIWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAAua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgISa19wb3NpdGlvbkZyYWN0aW9uAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAhrX3BhdXNlZAIIa19wYXVzZWQABWtfZmVlAgVrX2ZlZQAPa19mdW5kaW5nUGVyaW9kAg9rX2Z1bmRpbmdQZXJpb2QAEWtfaW5pdE1hcmdpblJhdGlvAhFrX2luaXRNYXJnaW5SYXRpbwAYa19tYWludGVuYW5jZU1hcmdpblJhdGlvAgVrX21tcgAVa19saXF1aWRhdGlvbkZlZVJhdGlvAhVrX2xpcXVpZGF0aW9uRmVlUmF0aW8ADWtfc3ByZWFkTGltaXQCDWtfc3ByZWFkTGltaXQAEGtfbWF4UHJpY2VJbXBhY3QCEGtfbWF4UHJpY2VJbXBhY3QADWtfbGFzdERhdGFTdHICDWtfbGFzdERhdGFTdHIADmtfbGFzdE1pbnV0ZUlkAg5rX2xhc3RNaW51dGVJZAAda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UCHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlABNrX3R3YXBEYXRhTGFzdFByaWNlAhNrX3R3YXBEYXRhTGFzdFByaWNlABprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAIaa190d2FwRGF0YVByZXZpb3VzTWludXRlSWQAJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CG2tfbGF0ZXN0TG9uZ1ByZW1pdW1GcmFjdGlvbgAma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CHGtfbGF0ZXN0U2hvcnRQcmVtaXVtRnJhY3Rpb24AEmtfbmV4dEZ1bmRpbmdCbG9jawIea19uZXh0RnVuZGluZ0Jsb2NrTWluVGltZXN0YW1wABFrX2xvbmdGdW5kaW5nUmF0ZQIRa19sb25nRnVuZGluZ1JhdGUAEmtfc2hvcnRGdW5kaW5nUmF0ZQISa19zaG9ydEZ1bmRpbmdSYXRlABNrX3F1b3RlQXNzZXRSZXNlcnZlAghrX3F0QXN0UgASa19iYXNlQXNzZXRSZXNlcnZlAghrX2JzQXN0UgATa190b3RhbFBvc2l0aW9uU2l6ZQITa190b3RhbFBvc2l0aW9uU2l6ZQAXa190b3RhbExvbmdQb3NpdGlvblNpemUCF2tfdG90YWxMb25nUG9zaXRpb25TaXplABhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAUa19jdW11bGF0aXZlTm90aW9uYWwCFGtfY3VtdWxhdGl2ZU5vdGlvbmFsABZrX29wZW5JbnRlcmVzdE5vdGlvbmFsAhZrX29wZW5JbnRlcmVzdE5vdGlvbmFsABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MAE2tfaW5zdXJhbmNlX2FkZHJlc3MCE2tfaW5zdXJhbmNlX2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAAPa19xdW90ZV9zdGFraW5nAg9rX3F1b3RlX3N0YWtpbmcAEWtfc3Rha2luZ19hZGRyZXNzAhFrX3N0YWtpbmdfYWRkcmVzcwAPa19taW5lcl9hZGRyZXNzAg9rX21pbmVyX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEOYWRtaW5QdWJsaWNLZXkACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfYWRtaW5fcHVibGljX2tleQEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAERcXVvdGVBc3NldFN0YWtpbmcACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUPa19xdW90ZV9zdGFraW5nAhtRdW90ZSBhc3NldCBzdGFraW5nIG5vdCBzZXQBDnN0YWtpbmdBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfc3Rha2luZ19hZGRyZXNzAhFJbnN1cmFuY2Ugbm90IHNldAEQaW5zdXJhbmNlQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRNrX2luc3VyYW5jZV9hZGRyZXNzAhFJbnN1cmFuY2Ugbm90IHNldAEMbWluZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfbWluZXJfYWRkcmVzcwIRSW5zdXJhbmNlIG5vdCBzZXQACERJUl9MT05HAAEACURJUl9TSE9SVAACAA1UV0FQX0lOVEVSVkFMAA8AD09SQUNMRV9JTlRFUlZBTAAPAAdTRUNPTkRTAOgHAAxERUNJTUFMX1VOSVQJAGgCAAEJAGgCCQBoAgkAaAIJAGgCCQBoAgAKAAoACgAKAAoACgAHT05FX0RBWQkAaAIAgKMFBQxERUNJTUFMX1VOSVQACEFMTF9GRUVTAGQAD1BOTF9PUFRJT05fU1BPVAABABFQTkxfT1BUSU9OX09SQUNMRQACAQFzAQJfeAkArAICCQCkAwEFAl94AgEsAQRkaXZkAgJfeAJfeQkAbgQFAl94BQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEEbXVsZAICX3gCX3kJAG4EBQJfeAUCX3kFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQ50b0NvbXBvc2l0ZUtleQIEX2tleQhfYWRkcmVzcwkArAICCQCsAgIFBF9rZXkCAV8FCF9hZGRyZXNzAQlsaXN0VG9TdHIBBV9saXN0CgEFX2pvaW4CC2FjY3VtdWxhdG9yA3ZhbAkArAICCQCsAgIFC2FjY3VtdWxhdG9yBQN2YWwCASwECm5ld0xpc3RTdHIKAAIkbAUFX2xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBV9qb2luAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQEC25ld0xpc3RTdHJVCQCzAgIFCm5ld0xpc3RTdHIAAQQLbmV3TGlzdFN0clIDCQAAAgkArwICBQtuZXdMaXN0U3RyVQABAgEsCQCwAgIFC25ld0xpc3RTdHJVAAEFC25ld0xpc3RTdHJVBQtuZXdMaXN0U3RyUgEJc3RyVG9MaXN0AQRfc3RyCQC1CQIFBF9zdHICASwBC3B1c2hUb1F1ZXVlAwVfbGlzdAhfbWF4U2l6ZQZfdmFsdWUDCQBmAgkAkAMBBQVfbGlzdAUIX21heFNpemUJAM0IAgkA0QgCBQVfbGlzdAAABQZfdmFsdWUJAM0IAgUFX2xpc3QFBl92YWx1ZQEDaW50AQFrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUEdGhpcwUBawkArAICAg1ubyB2YWx1ZSBmb3IgBQFrAQhjYmFsYW5jZQAJAQNpbnQBBQlrX2JhbGFuY2UBA2ZlZQAJAQNpbnQBBQVrX2ZlZQEPaW5pdE1hcmdpblJhdGlvAAkBA2ludAEFEWtfaW5pdE1hcmdpblJhdGlvAQZxdEFzdFIACQEDaW50AQUTa19xdW90ZUFzc2V0UmVzZXJ2ZQEGYnNBc3RSAAkBA2ludAEFEmtfYmFzZUFzc2V0UmVzZXJ2ZQERdG90YWxQb3NpdGlvblNpemUACQEDaW50AQUTa190b3RhbFBvc2l0aW9uU2l6ZQESY3VtdWxhdGl2ZU5vdGlvbmFsAAkBA2ludAEFFGtfY3VtdWxhdGl2ZU5vdGlvbmFsARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAJAQNpbnQBBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAkBA2ludAEFEmtfbmV4dEZ1bmRpbmdCbG9jawEQZnVuZGluZ1BlcmlvZFJhdwAJAQNpbnQBBQ9rX2Z1bmRpbmdQZXJpb2QBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAkAaAIJARBmdW5kaW5nUGVyaW9kUmF3AAUMREVDSU1BTF9VTklUARRmdW5kaW5nUGVyaW9kU2Vjb25kcwAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFB1NFQ09ORFMBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ACQEDaW50AQUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvARNsaXF1aWRhdGlvbkZlZVJhdGlvAAkBA2ludAEFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwELc3ByZWFkTGltaXQACQEDaW50AQUNa19zcHJlYWRMaW1pdAEObWF4UHJpY2VJbXBhY3QACQEDaW50AQUQa19tYXhQcmljZUltcGFjdAEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBA2ludAEFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBA2ludAEFF2tfdG90YWxMb25nUG9zaXRpb25TaXplARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwxfbWFyZ2luUmF0aW8QX2Jhc2VNYXJnaW5SYXRpbxRfbGFyZ2VyVGhhbk9yRXF1YWxUbwQUcmVtYWluaW5nTWFyZ2luUmF0aW8JAGUCBQxfbWFyZ2luUmF0aW8FEF9iYXNlTWFyZ2luUmF0aW8DAwUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGYCAAAFFHJlbWFpbmluZ01hcmdpblJhdGlvBwkAAgECDkludmFsaWQgbWFyZ2luAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwkAAgECDkludmFsaWQgbWFyZ2luBgEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAJASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24AAQtnZXRQb3NpdGlvbgEHX3RyYWRlcgQPcG9zaXRpb25TaXplT3B0CQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAckbWF0Y2gwBQ9wb3NpdGlvblNpemVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAxwb3NpdGlvblNpemUFByRtYXRjaDAJAJYKBAUMcG9zaXRpb25TaXplCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQdfdHJhZGVyCQCWCgQAAAAAAAAAAAETcmVxdWlyZU9wZW5Qb3NpdGlvbgEHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgJfMQAACQACAQIQTm8gb3BlbiBwb3NpdGlvbgYBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBDXVwZGF0ZVJlc2VydmUDBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudBBfYmFzZUFzc2V0QW1vdW50AwUGX2lzQWRkBAduZXdCYXNlCQBlAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQDCQBnAgAABQduZXdCYXNlCQACAQIqVHggbGVhZCB0byBiYXNlIGFzc2V0IHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCWCgQJAGQCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQFB25ld0Jhc2UJAGQCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50CQBkAgkBEmN1bXVsYXRpdmVOb3Rpb25hbAAFEV9xdW90ZUFzc2V0QW1vdW50BAhuZXdRdW90ZQkAZQIJAQZxdEFzdFIABRFfcXVvdGVBc3NldEFtb3VudAMJAGcCAAAFCG5ld1F1b3RlCQACAQIqVHggbGVhZCB0byBiYXNlIHF1b3RlIHJlc2VydmUgPD0gMCwgcmV2ZXJ0CQCWCgQFCG5ld1F1b3RlCQBkAgkBBmJzQXN0UgAFEF9iYXNlQXNzZXRBbW91bnQJAGUCCQERdG90YWxQb3NpdGlvblNpemUABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEmN1bXVsYXRpdmVOb3Rpb25hbAAFEV9xdW90ZUFzc2V0QW1vdW50AQlzd2FwSW5wdXQCBl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudAQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAtwcmljZUJlZm9yZQkBBGRpdmQCBQdfcXRBc3RSBQdfYnNBc3RSBCdhbW91bnRCYXNlQXNzZXRCb3VnaHRXaXRob3V0UHJpY2VJbXBhY3QJAQRtdWxkAgURX3F1b3RlQXNzZXRBbW91bnQFC3ByaWNlQmVmb3JlBAFrCQEEbXVsZAIFB19xdEFzdFIFB19ic0FzdFIEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIDBQZfaXNBZGQJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAkAZQIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAQRkaXZkAgUBawUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEDYWJzAQkAZQIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUHX2JzQXN0UgQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AwUGX2lzQWRkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQEtAQUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBAtwcmljZUltcGFjdAkAaQIJAGUCBSdhbW91bnRCYXNlQXNzZXRCb3VnaHRXaXRob3V0UHJpY2VJbXBhY3QFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwUnYW1vdW50QmFzZUFzc2V0Qm91Z2h0V2l0aG91dFByaWNlSW1wYWN0BBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QAAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlCQACAQkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQQNJHQwMTIzMTIxMjUxNQkBDXVwZGF0ZVJlc2VydmUDBQZfaXNBZGQFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTIzMTIxMjUxNQJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDEyMzEyMTI1MTUCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTIzMTIxMjUxNQJfMwQYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxCAUNJHQwMTIzMTIxMjUxNQJfNAkAlwoFBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQUYY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIxASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BBBfb2xkUG9zaXRpb25TaXplEl9vbGRQb3NpdGlvbk1hcmdpbiVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uDF9tYXJnaW5EZWx0YQQOZnVuZGluZ1BheW1lbnQDCQECIT0CBRBfb2xkUG9zaXRpb25TaXplAAAEIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEDHNpZ25lZE1hcmdpbgkAZAIJAGUCBQxfbWFyZ2luRGVsdGEFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDEzMjYyMTMzODkDCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTMyNjIxMzM4OQJfMQQHYmFkRGVidAgFDSR0MDEzMjYyMTMzODkCXzIJAJUKAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAEKc3dhcE91dHB1dAIGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQEEl9xdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0UgAEEV9iYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RSAAMJAAACBRBfYmFzZUFzc2V0QW1vdW50AAAJAAIBAhlJbnZhbGlkIGJhc2UgYXNzZXQgYW1vdW50BAFrCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX2Jhc2VBc3NldFJlc2VydmUEGGJhc2VBc3NldFBvb2xBbW91bnRBZnRlcgMFBl9pc0FkZAkAZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50CQBlAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQED3F1b3RlQXNzZXRBZnRlcgkBBGRpdmQCBQFrBRhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIEDnF1b3RlQXNzZXRTb2xkCQEDYWJzAQkAZQIFD3F1b3RlQXNzZXRBZnRlcgUSX3F1b3RlQXNzZXRSZXNlcnZlBA0kdDAxNDIyNzE0NDIwCQENdXBkYXRlUmVzZXJ2ZQMJAQEhAQUGX2lzQWRkBQ5xdW90ZUFzc2V0U29sZAUQX2Jhc2VBc3NldEFtb3VudAQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxNDIyNzE0NDIwAl8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTQyMjcxNDQyMAJfMgQXdG90YWxQb3NpdGlvblNpemVBZnRlcjEIBQ0kdDAxNDIyNzE0NDIwAl8zBBhjdW11bGF0aXZlTm90aW9uYWxBZnRlcjEIBQ0kdDAxNDIyNzE0NDIwAl80CQCZCgcFDnF1b3RlQXNzZXRTb2xkBRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEFGGN1bXVsYXRpdmVOb3Rpb25hbEFmdGVyMQkAZQIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwUGX2lzQWRkCQEDYWJzAQUQX2Jhc2VBc3NldEFtb3VudAAACQBlAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkBASEBBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAABEmdldE9yYWNsZVR3YXBQcmljZQAEBm9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFBWtfb3JhAgAECHByaWNlS2V5CQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQlrX29yYV9rZXkECGJsb2NrS2V5CQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQ9rX29yYV9ibG9ja19rZXkECWxhc3RWYWx1ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUGb3JhY2xlBQhwcmljZUtleQUJbGFzdFZhbHVlAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAJAQRkaXZkAgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQMY3VycmVudFByaWNlCQEMZ2V0U3BvdFByaWNlAAkAZgIJAQRkaXZkAgkBA2FicwEJAGUCBQtvcmFjbGVQcmljZQUMY3VycmVudFByaWNlBQtvcmFjbGVQcmljZQkBC3NwcmVhZExpbWl0AAEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCB190cmFkZXIHX29wdGlvbgQNJHQwMTYwNTIxNjE4MAkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMTYwNTIxNjE4MAJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAxNjA1MjE2MTgwAl8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDE2MDUyMTYxODACXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMTYwNTIxNjE4MAJfNAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUMcG9zaXRpb25TaXplAwkAAAIFD3Bvc2l0aW9uU2l6ZUFicwAACQACAQIVSW52YWxpZCBwb3NpdGlvbiBzaXplBAdpc1Nob3J0CQBmAgAABQxwb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwDCQAAAgUHX29wdGlvbgUPUE5MX09QVElPTl9TUE9UBA0kdDAxNjQyNzE2NTM0CQEKc3dhcE91dHB1dAIJAQEhAQUHaXNTaG9ydAUPcG9zaXRpb25TaXplQWJzBBNvdXRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMTY0MjcxNjUzNAJfMQQCeDEIBQ0kdDAxNjQyNzE2NTM0Al8yBAJ4MggFDSR0MDE2NDI3MTY1MzQCXzMEAngzCAUNJHQwMTY0MjcxNjUzNAJfNAUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJARJnZXRPcmFjbGVUd2FwUHJpY2UABA11bnJlYWxpemVkUG5sAwUHaXNTaG9ydAkAZQIFFHBvc2l0aW9uT3Blbk5vdGlvbmFsBRBwb3NpdGlvbk5vdGlvbmFsCQBlAgUQcG9zaXRpb25Ob3Rpb25hbAUUcG9zaXRpb25PcGVuTm90aW9uYWwJAJQKAgUQcG9zaXRpb25Ob3Rpb25hbAUNdW5yZWFsaXplZFBubAEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24CB190cmFkZXIHX29wdGlvbgQNJHQwMTcyMDQxNzMxNQkBC2dldFBvc2l0aW9uAQUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUNJHQwMTcyMDQxNzMxNQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAxNzIwNDE3MzE1Al8yBANwb24IBQ0kdDAxNzIwNDE3MzE1Al8zBBFwb3NpdGlvbkxzdFVwZENQRggFDSR0MDE3MjA0MTczMTUCXzQEDSR0MDE3MzIxMTc0MTQJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAIFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAxNzMyMTE3NDE0Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMTczMjExNzQxNAJfMgQNJHQwMTc0MTkxNzU4NQkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQxwb3NpdGlvblNpemUFDnBvc2l0aW9uTWFyZ2luBRFwb3NpdGlvbkxzdFVwZENQRgUNdW5yZWFsaXplZFBubAQMcmVtYWluTWFyZ2luCAUNJHQwMTc0MTkxNzU4NQJfMQQHYmFkRGVidAgFDSR0MDE3NDE5MTc1ODUCXzIJAQ9jYWxjTWFyZ2luUmF0aW8DBQxyZW1haW5NYXJnaW4FB2JhZERlYnQFEHBvc2l0aW9uTm90aW9uYWwBDmdldE1hcmdpblJhdGlvAQdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgIFB190cmFkZXIFD1BOTF9PUFRJT05fU1BPVAEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uAQdfdHJhZGVyBA0kdDAxNzkwMTE4MDI5CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDAxNzkwMTE4MDI5Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDE3OTAxMTgwMjkCXzIEFHBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMTc5MDExODAyOQJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAxNzkwMTE4MDI5Al80BA0kdDAxODAzNTE4MTIyCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCBQdfdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEAngxCAUNJHQwMTgwMzUxODEyMgJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDE4MDM1MTgxMjICXzIEDSR0MDE4MTI3MTgyOTUJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDE4MTI3MTgyOTUCXzEEB2JhZERlYnQIBQ0kdDAxODEyNzE4Mjk1Al8yBBVleGNoYW5nZWRQb3NpdGlvblNpemUJAQEtAQUMcG9zaXRpb25TaXplBAtyZWFsaXplZFBubAUNdW5yZWFsaXplZFBubAQNbWFyZ2luVG9WYXVsdAkBAS0BBQxyZW1haW5NYXJnaW4EDSR0MDE4NDIyMTg3MDMJAQpzd2FwT3V0cHV0AgkAZgIFDHBvc2l0aW9uU2l6ZQAACQEDYWJzAQUMcG9zaXRpb25TaXplBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwMTg0MjIxODcwMwJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDE4NDIyMTg3MDMCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDE4NDIyMTg3MDMCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDAxODQyMjE4NzAzAl80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDE4NDIyMTg3MDMCXzUEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwMTg0MjIxODcwMwJfNgQPdG90YWxTaG9ydEFmdGVyCAUNJHQwMTg0MjIxODcwMwJfNwQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgkAZQIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQCeCgwFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQUHYmFkRGVidAULcmVhbGl6ZWRQbmwFDW1hcmdpblRvVmF1bHQFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIBEGdldFR3YXBTcG90UHJpY2UABAhtaW51dGVJZAkAaQIJAGkCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcADoBwA8BA1zdGFydE1pbnV0ZUlkCQBlAgUIbWludXRlSWQFDVRXQVBfSU5URVJWQUwEB2xpc3RTdHIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUNa19sYXN0RGF0YVN0cgIABARsaXN0CQC1CQIFB2xpc3RTdHICASwKAQhmaWx0ZXJGbgILYWNjdW11bGF0b3IEbmV4dAMJAGcCBQ1zdGFydE1pbnV0ZUlkCQENcGFyc2VJbnRWYWx1ZQEFBG5leHQJAM0IAgULYWNjdW11bGF0b3IJAQ1wYXJzZUludFZhbHVlAQUEbmV4dAULYWNjdW11bGF0b3IEBWxpc3RGCgACJGwFBGxpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGZpbHRlckZuAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQECG1heEluZGV4AwkAZgIJAJADAQUFbGlzdEYAAAkAlgMBBQVsaXN0RgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxpc3QAAAQMbGFzdE1pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFDmtfbGFzdE1pbnV0ZUlkAAAEFmVuZExhc3RDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFDGxhc3RNaW51dGVJZAAABAxlbmRMYXN0UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFE2tfdHdhcERhdGFMYXN0UHJpY2UCAV8JAKQDAQUMbGFzdE1pbnV0ZUlkAAAEEm5vd0N1bXVsYXRpdmVQcmljZQkAZAIFFmVuZExhc3RDdW11bGF0aXZlUHJpY2UJAGgCCQBlAgUIbWludXRlSWQFDGxhc3RNaW51dGVJZAUMZW5kTGFzdFByaWNlBBhzdGFydExhc3RDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFCG1heEluZGV4AAAEDnN0YXJ0TGFzdFByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFCG1heEluZGV4AAAEFHN0YXJ0Q3VtdWxhdGl2ZVByaWNlCQBkAgUYc3RhcnRMYXN0Q3VtdWxhdGl2ZVByaWNlCQBoAgkAZQIFDXN0YXJ0TWludXRlSWQFCG1heEluZGV4BQ5zdGFydExhc3RQcmljZQkAaQIJAGUCBRJub3dDdW11bGF0aXZlUHJpY2UFFHN0YXJ0Q3VtdWxhdGl2ZVByaWNlBQ1UV0FQX0lOVEVSVkFMAQ51cGRhdGVTZXR0aW5ncwcQX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa19pbml0TWFyZ2luUmF0aW8FEF9pbml0TWFyZ2luUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwUEX21tcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUVa19saXF1aWRhdGlvbkZlZVJhdGlvBRRfbGlxdWlkYXRpb25GZWVSYXRpbwkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa19mdW5kaW5nUGVyaW9kBQ5fZnVuZGluZ1BlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUFa19mZWUFBF9mZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfc3ByZWFkTGltaXQFDF9zcHJlYWRMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa19tYXhQcmljZUltcGFjdAUPX21heFByaWNlSW1wYWN0BQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBDnVwZGF0ZVBvc2l0aW9uBQhfYWRkcmVzcwVfc2l6ZQdfbWFyZ2luDV9vcGVuTm90aW9uYWwgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQhfYWRkcmVzcwUFX3NpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzBQdfbWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQhfYWRkcmVzcwUNX29wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUIX2FkZHJlc3MFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQNuaWwBCmFwcGVuZFR3YXABBXByaWNlBAhtaW51dGVJZAkAaQIJAGkCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcADoBwA8BBBwcmV2aW91c01pbnV0ZUlkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFDmtfbGFzdE1pbnV0ZUlkAAADCQBmAgUQcHJldmlvdXNNaW51dGVJZAUIbWludXRlSWQJAAIBAhFUV0FQIG91dC1vZi1vcmRlcgQMbGFzdE1pbnV0ZUlkAwkAAAIFEHByZXZpb3VzTWludXRlSWQAAAUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQDCQBmAgUIbWludXRlSWQFEHByZXZpb3VzTWludXRlSWQEE3ByZXZDdW11bGF0aXZlUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICCQCsAgIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlAgFfCQCkAwEFEHByZXZpb3VzTWludXRlSWQAAAQJcHJldlByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICBRNrX3R3YXBEYXRhTGFzdFByaWNlAgFfCQCkAwEFEHByZXZpb3VzTWludXRlSWQFBXByaWNlBBNsYXN0Q3VtdWxhdGl2ZVByaWNlCQBkAgUTcHJldkN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUMbGFzdE1pbnV0ZUlkBQlwcmV2UHJpY2UEBGxpc3QJAQtwdXNoVG9RdWV1ZQMJAQlzdHJUb0xpc3QBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFDWtfbGFzdERhdGFTdHICAAUNVFdBUF9JTlRFUlZBTAkApAMBBQhtaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UJAKQDAQUIbWludXRlSWQFE2xhc3RDdW11bGF0aXZlUHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFE2tfdHdhcERhdGFMYXN0UHJpY2UJAKQDAQUIbWludXRlSWQFBXByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAUQcHJldmlvdXNNaW51dGVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa19sYXN0TWludXRlSWQFCG1pbnV0ZUlkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDWtfbGFzdERhdGFTdHIJAQlsaXN0VG9TdHIBBQRsaXN0BQNuaWwEGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAkApAMBBQhtaW51dGVJZAAABBNwcmV2Q3VtdWxhdGl2ZVByaWNlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFGHR3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAABAlwcmV2UHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUTa190d2FwRGF0YUxhc3RQcmljZQkApAMBBRh0d2FwRGF0YVByZXZpb3VzTWludXRlSWQFBXByaWNlBBNsYXN0Q3VtdWxhdGl2ZVByaWNlCQBkAgUTcHJldkN1bXVsYXRpdmVQcmljZQkAaAIJAGUCBQhtaW51dGVJZAUYdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkBQlwcmV2UHJpY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFHWtfdHdhcERhdGFMYXN0Q3VtdWxhdGl2ZVByaWNlCQCkAwEFCG1pbnV0ZUlkBRNsYXN0Q3VtdWxhdGl2ZVByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRNrX3R3YXBEYXRhTGFzdFByaWNlCQCkAwEFCG1pbnV0ZUlkBQVwcmljZQUDbmlsARF1cGRhdGVBbW1SZXNlcnZlcwIHX3F0QXN0UgdfYnNBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFIFA25pbAEJdXBkYXRlQW1tBwdfcXRBc3RSB19ic0FzdFIXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIYX2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyFV9vcGVuSW50ZXJlc3ROb3Rpb25hbBZfdG90YWxMb25nUG9zaXRpb25TaXplF190b3RhbFNob3J0UG9zaXRpb25TaXplAwkBAiE9AgkAZQIFFl90b3RhbExvbmdQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhJbnZhbGlkIEFNTSBzdGF0ZSBkYXRhOiAJAKQDAQUWX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQIEICsgIAkApAMBBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQIEICE9IAkApAMBBRdfdG90YWxQb3NpdGlvblNpemVBZnRlcgkAzggCCQDOCAIJARF1cGRhdGVBbW1SZXNlcnZlcwIFB19xdEFzdFIFB19ic0FzdFIJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tfdG90YWxQb3NpdGlvblNpemUFF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRRrX2N1bXVsYXRpdmVOb3Rpb25hbAUYX2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsBRVfb3BlbkludGVyZXN0Tm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIFF2tfdG90YWxMb25nUG9zaXRpb25TaXplBRZfdG90YWxMb25nUG9zaXRpb25TaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUFF190b3RhbFNob3J0UG9zaXRpb25TaXplBQNuaWwJAQphcHBlbmRUd2FwAQkBBGRpdmQCBQdfcXRBc3RSBQdfYnNBc3RSAQ5kZWxldGVQb3NpdGlvbgEIX2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFCF9hZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FCF9hZGRyZXNzBQNuaWwBCHdpdGhkcmF3AghfYWRkcmVzcwdfYW1vdW50BAdiYWxhbmNlCQDwBwIFBHRoaXMJAQpxdW90ZUFzc2V0AAMJAGYCBQdfYW1vdW50BQdiYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgITVW5hYmxlIHRvIHdpdGhkcmF3IAkApAMBBQdfYW1vdW50AhcgZnJvbSBjb250cmFjdCBiYWxhbmNlIAkApAMBBQdiYWxhbmNlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCF9hZGRyZXNzBQdfYW1vdW50CQEKcXVvdGVBc3NldAAFA25pbAENdXBkYXRlQmFsYW5jZQEBaQMJAGYCAAAFAWkJAAIBAgdCYWxhbmNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrX2JhbGFuY2UFAWkFA25pbAELdHJhbnNmZXJGZWUBAWkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBDnN0YWtpbmdBZGRyZXNzAAUBaQkBCnF1b3RlQXNzZXQABQNuaWwQAWkBBXBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhpJbnZhbGlkIHRvZ2dsZVBhdXNlIHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUIa19wYXVzZWQGBQNuaWwBaQEHdW5wYXVzZQADCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIaSW52YWxpZCB0b2dnbGVQYXVzZSBwYXJhbXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCGtfcGF1c2VkBwUDbmlsAWkBDGFkZExpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIbSW52YWxpZCBhZGRMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBXByaWNlCQEEZGl2ZAIFB19xdEFzdFIFB19ic0FzdFIEFGJhc2VBc3NldEFtb3VudFRvQWRkCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQVwcmljZQQLcXRBc3RSQWZ0ZXIJAGQCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQLYnNBc3RSQWZ0ZXIJAGQCBQdfYnNBc3RSBRRiYXNlQXNzZXRBbW91bnRUb0FkZAkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyAWkBD3JlbW92ZUxpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCAAAFEV9xdW90ZUFzc2V0QW1vdW50CQACAQIeSW52YWxpZCByZW1vdmVMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBXByaWNlCQEEZGl2ZAIFB19xdEFzdFIFB19ic0FzdFIEF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BQVwcmljZQQLcXRBc3RSQWZ0ZXIJAGUCBQdfcXRBc3RSBRFfcXVvdGVBc3NldEFtb3VudAQLYnNBc3RSQWZ0ZXIJAGUCBQdfYnNBc3RSBRdiYXNlQXNzZXRBbW91bnRUb1JlbW92ZQkBEXVwZGF0ZUFtbVJlc2VydmVzAgULcXRBc3RSQWZ0ZXIFC2JzQXN0UkFmdGVyAWkBDmNoYW5nZVNldHRpbmdzBxBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0AwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MHBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0AWkBCmluaXRpYWxpemUMB19xdEFzdFIHX2JzQXN0Ug5fZnVuZGluZ1BlcmlvZBBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8EX2ZlZQdfb3JhY2xlCl9vcmFjbGVLZXkMX2Nvb3JkaW5hdG9yDF9zcHJlYWRMaW1pdA9fbWF4UHJpY2VJbXBhY3QDAwMDAwMDAwMDCQBnAgAABQdfcXRBc3RSBgkAZwIAAAUHX2JzQXN0UgYJAGcCAAAFDl9mdW5kaW5nUGVyaW9kBgkAZwIAAAUQX2luaXRNYXJnaW5SYXRpbwYJAGcCAAAFBF9tbXIGCQBnAgAABRRfbGlxdWlkYXRpb25GZWVSYXRpbwYJAGcCAAAFBF9mZWUGCQBnAgAABQxfc3ByZWFkTGltaXQGCQBnAgAABQ9fbWF4UHJpY2VJbXBhY3QGCQELaW5pdGlhbGl6ZWQACQACAQIdSW52YWxpZCBpbml0aWFsaXplIHBhcmFtZXRlcnMJAM4IAgkAzggCCQDOCAIJAM4IAgkBCXVwZGF0ZUFtbQcFB19xdEFzdFIFB19ic0FzdFIAAAAAAAAAAAAACQEOdXBkYXRlU2V0dGluZ3MHBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0CQENdXBkYXRlRnVuZGluZwUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUOX2Z1bmRpbmdQZXJpb2QAAAAAAAAAAAkBDXVwZGF0ZUJhbGFuY2UBAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWtfb3JhBQdfb3JhY2xlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtfb3JhX2tleQUKX29yYWNsZUtleQkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yBQNuaWwBaQEQZGVjcmVhc2VQb3NpdGlvbgMHX2Ftb3VudAlfbGV2ZXJhZ2UTX21pbkJhc2VBc3NldEFtb3VudAMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMJAQRkaXZkAgUMREVDSU1BTF9VTklUBQlfbGV2ZXJhZ2UJAQ9pbml0TWFyZ2luUmF0aW8ABgYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQZwYXVzZWQACQACAQIjSW52YWxpZCBkZWNyZWFzZVBvc2l0aW9uIHBhcmFtZXRlcnMEDSR0MDI5NjEyMjk3NjQJAQtnZXRQb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBA9vbGRQb3NpdGlvblNpemUIBQ0kdDAyOTYxMjI5NzY0Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDI5NjEyMjk3NjQCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMjk2MTIyOTc2NAJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAyOTYxMjI5NzY0Al80BApfZGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAABQlESVJfU0hPUlQFCERJUl9MT05HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDAyOTkzNzMwMDUzCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwCCQClCAEIBQFpBmNhbGxlcgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMjk5MzczMDA1MwJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDI5OTM3MzAwNTMCXzIEDSR0MDMwMDU5MzI2MDgDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsBA0kdDAzMDQzNjMwNjU1CQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplCAUNJHQwMzA0MzYzMDY1NQJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDMwNDM2MzA2NTUCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDMwNDM2MzA2NTUCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDAzMDQzNjMwNjU1Al80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDMwNDM2MzA2NTUCXzUEGGV4Y2hhbmdlZFBvc2l0aW9uU2l6ZUFicwkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50BRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMHCQACAQkArAICCQCsAgIJAKwCAgIlVG9vIGxpdHRsZSBiYXNlIGFzc2V0IGV4Y2hhbmdlZCwgZ290IAkApAMBBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMCCiBleHBlY3RlZCAJAKQDAQUTX21pbkJhc2VBc3NldEFtb3VudAQLcmVhbGl6ZWRQbmwJAQRkaXZkAgkBBG11bGQCBQ11bnJlYWxpemVkUG5sBRhleGNoYW5nZWRQb3NpdGlvblNpemVBYnMJAQNhYnMBBQ9vbGRQb3NpdGlvblNpemUEDSR0MDMxMDkyMzEzMzcJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC3JlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDAzMTA5MjMxMzM3Al8xBAdiYWREZWJ0CAUNJHQwMzEwOTIzMTMzNwJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDAzMTA5MjMxMzM3Al8zBBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BQxvcGVuTm90aW9uYWwEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUJAJ0KCwUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAQNhYnMBBRJyZW1haW5PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPbmV3UG9zaXRpb25TaXplBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAUMb3Blbk5vdGlvbmFsCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADCQBmAgUPbmV3UG9zaXRpb25TaXplAAAJAQNhYnMBBRVleGNoYW5nZWRQb3NpdGlvblNpemUAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAMJAGYCAAAFD25ld1Bvc2l0aW9uU2l6ZQkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQAACQACAQIUQ2xvc2UgcG9zaXRpb24gZmlyc3QED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDMwMDU5MzI2MDgCXzEEF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luCAUNJHQwMzAwNTkzMjYwOAJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAzMDA1OTMyNjA4Al8zBBRuZXdQb3NpdGlvbkxhdGVzdENQRggFDSR0MDMwMDU5MzI2MDgCXzQEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDMwMDU5MzI2MDgCXzUEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMDA1OTMyNjA4Al82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMzAwNTkzMjYwOAJfNwQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDAzMDA1OTMyNjA4Al84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwMzAwNTkzMjYwOAJfOQQOdG90YWxMb25nQWZ0ZXIIBQ0kdDAzMDA1OTMyNjA4A18xMAQPdG90YWxTaG9ydEFmdGVyCAUNJHQwMzAwNTkzMjYwOANfMTEEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCCQClCAEIBQFpBmNhbGxlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUJAKUIAQgFAWkGY2FsbGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGluY3JlYXNlUG9zaXRpb24DCl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQECl9yYXdBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AwMDAwMDAwkBAiE9AgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAQIhPQIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAcGCQBnAgAABQpfcmF3QW1vdW50BgkBASEBCQELaW5pdGlhbGl6ZWQABgkBAiE9AggJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkCQEKcXVvdGVBc3NldAAGCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwkBBGRpdmQCBQxERUNJTUFMX1VOSVQFCV9sZXZlcmFnZQkBD2luaXRNYXJnaW5SYXRpbwAGBgkBBnBhdXNlZAAJAAIBAiNJbnZhbGlkIGluY3JlYXNlUG9zaXRpb24gcGFyYW1ldGVycwQJZmVlQW1vdW50CQEEbXVsZAIFCl9yYXdBbW91bnQJAQNmZWUABAdfYW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUJZmVlQW1vdW50BA0kdDAzMzcyNjMzODc4CQELZ2V0UG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwMzM3MjYzMzg3OAJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDAzMzcyNjMzODc4Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDMzNzI2MzM4NzgCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMzM3MjYzMzg3OAJfNAQNaXNOZXdQb3NpdGlvbgkAAAIFD29sZFBvc2l0aW9uU2l6ZQAABA9pc1NhbWVEaXJlY3Rpb24DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAAACBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkAAAIFCl9kaXJlY3Rpb24FCURJUl9TSE9SVAQOZXhwYW5kRXhpc3RpbmcDCQEBIQEFDWlzTmV3UG9zaXRpb24FD2lzU2FtZURpcmVjdGlvbgcEBWlzQWRkCQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcEDSR0MDM0MTY3MzY1NTYDAwUNaXNOZXdQb3NpdGlvbgYFDmV4cGFuZEV4aXN0aW5nBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDAzNDU5MTM0Nzk3CQEJc3dhcElucHV0AgUFaXNBZGQFDG9wZW5Ob3Rpb25hbAQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0CAUNJHQwMzQ1OTEzNDc5NwJfMQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDM0NTkxMzQ3OTcCXzIEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDM0NTkxMzQ3OTcCXzMEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDAzNDU5MTM0Nzk3Al80BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDM0NTkxMzQ3OTcCXzUDAwkBAiE9AgUTX21pbkJhc2VBc3NldEFtb3VudAAACQBmAgUTX21pbkJhc2VBc3NldEFtb3VudAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAcJAAIBCQCsAgIJAKwCAgkArAICAg1MaW1pdCBlcnJvcjogCQCkAwEJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQCAyA8IAkApAMBBRNfbWluQmFzZUFzc2V0QW1vdW50BA9uZXdQb3NpdGlvblNpemUJAGQCBQ9vbGRQb3NpdGlvblNpemUFFWFtb3VudEJhc2VBc3NldEJvdWdodAQZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAkBBGRpdmQCBQxvcGVuTm90aW9uYWwFCV9sZXZlcmFnZQQNJHQwMzUxNzgzNTQxNwkBImNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnQEBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUZaW5jcmVhc2VNYXJnaW5SZXF1aXJlbWVudAQMcmVtYWluTWFyZ2luCAUNJHQwMzUxNzgzNTQxNwJfMQQCeDEIBQ0kdDAzNTE3ODM1NDE3Al8yBAJ4MggFDSR0MDM1MTc4MzU0MTcCXzMJAJ0KCwUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAGQCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRdjdW11bGF0aXZlTm90aW9uYWxBZnRlcgkAZAIJARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAFDG9wZW5Ob3Rpb25hbAkAZAIJARV0b3RhbExvbmdQb3NpdGlvblNpemUAAwkAZgIFD25ld1Bvc2l0aW9uU2l6ZQAACQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAJAGQCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUJAQNhYnMBBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQAAAQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwMzYyNDkzNjM2NQkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgkApQgBCAUBaQZjYWxsZXIFD1BOTF9PUFRJT05fU1BPVAQTb2xkUG9zaXRpb25Ob3Rpb25hbAgFDSR0MDM2MjQ5MzYzNjUCXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDAzNjI0OTM2MzY1Al8yAwkAZgIFE29sZFBvc2l0aW9uTm90aW9uYWwFDG9wZW5Ob3Rpb25hbAkAAgECLlVzZSBkZWNyZWFzZVBvc2l0aW9uIHRvIGRlY3JlYXNlIHBvc2l0aW9uIHNpemUJAAIBAhRDbG9zZSBwb3NpdGlvbiBmaXJzdAQPbmV3UG9zaXRpb25TaXplCAUNJHQwMzQxNjczNjU1NgJfMQQXbmV3UG9zaXRpb25SZW1haW5NYXJnaW4IBQ0kdDAzNDE2NzM2NTU2Al8yBBduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDM0MTY3MzY1NTYCXzMEFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGCAUNJHQwMzQxNjczNjU1NgJfNAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwMzQxNjczNjU1NgJfNQQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDM0MTY3MzY1NTYCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDAzNDE2NzM2NTU2Al83BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDM0MTY3MzY1NTYCXzgEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDAzNDE2NzM2NTU2Al85BA50b3RhbExvbmdBZnRlcggFDSR0MDM0MTY3MzY1NTYDXzEwBA90b3RhbFNob3J0QWZ0ZXIIBQ0kdDAzNDE2NzM2NTU2A18xMQQMZmVlVG9TdGFrZXJzCQBpAgUJZmVlQW1vdW50AAIEDmZlZVRvSW5zdXJhbmNlCQBlAgUJZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMEBXN0YWtlCQD8BwQJARFxdW90ZUFzc2V0U3Rha2luZwACDmxvY2tOZXV0cmlub1NQCQDMCAIJAKUIAQkBDnN0YWtpbmdBZGRyZXNzAAkAzAgCBQhBTExfRkVFUwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBEGluc3VyYW5jZUFkZHJlc3MAAgdkZXBvc2l0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUOZmVlVG9JbnN1cmFuY2UFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgkApQgBCAUBaQZjYWxsZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIJAKUIAQgFAWkGY2FsbGVyCQDMCAIFF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUJAKUIAQgFAWkGY2FsbGVyBQ9uZXdQb3NpdGlvblNpemUFF25ld1Bvc2l0aW9uUmVtYWluTWFyZ2luBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUUbmV3UG9zaXRpb25MYXRlc3RDUEYJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJYWRkTWFyZ2luAAQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQDAwMDCQECIT0CCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQJZmVlQW1vdW50CQEEbXVsZAIFCl9yYXdBbW91bnQJAQNmZWUABAdfYW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUJZmVlQW1vdW50BA0kdDAzODExMjM4MjY0CQELZ2V0UG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgQPb2xkUG9zaXRpb25TaXplCAUNJHQwMzgxMTIzODI2NAJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDAzODExMjM4MjY0Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDM4MTEyMzgyNjQCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMzgxMTIzODI2NAJfNAQMZmVlVG9TdGFrZXJzCQBpAgUJZmVlQW1vdW50AAIEDmZlZVRvSW5zdXJhbmNlCQBlAgUJZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMEBXN0YWtlCQD8BwQJARFxdW90ZUFzc2V0U3Rha2luZwACDmxvY2tOZXV0cmlub1NQCQDMCAIJAKUIAQkBDnN0YWtpbmdBZGRyZXNzAAkAzAgCBQhBTExfRkVFUwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEEGRlcG9zaXRJbnN1cmFuY2UJAPwHBAkBEGluc3VyYW5jZUFkZHJlc3MAAgdkZXBvc2l0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUOZmVlVG9JbnN1cmFuY2UFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBAlub3RpZnlGZWUJAPwHBAkBDG1pbmVyQWRkcmVzcwACCm5vdGlmeUZlZXMJAMwIAgkApQgBCAUBaQZjYWxsZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgUJAKUIAQgFAWkGY2FsbGVyBQ9vbGRQb3NpdGlvblNpemUJAGQCBRFvbGRQb3NpdGlvbk1hcmdpbgUHX2Ftb3VudAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwFFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAQ11cGRhdGVCYWxhbmNlAQkAZAIJAQhjYmFsYW5jZQAFB19hbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMcmVtb3ZlTWFyZ2luAQdfYW1vdW50AwMDAwkAZwIAAAUHX2Ftb3VudAYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24BCQClCAEIBQFpBmNhbGxlcgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQACQACAQIfSW52YWxpZCByZW1vdmVNYXJnaW4gcGFyYW1ldGVycwQNJHQwMzkzMTMzOTQ2NQkBC2dldFBvc2l0aW9uAQkApQgBCAUBaQZjYWxsZXIED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDM5MzEzMzk0NjUCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwMzkzMTMzOTQ2NQJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAzOTMxMzM5NDY1Al8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDM5MzEzMzk0NjUCXzQEC21hcmdpbkRlbHRhCQEBLQEFB19hbW91bnQEDSR0MDM5NTAyMzk2ODEJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFC21hcmdpbkRlbHRhBAxyZW1haW5NYXJnaW4IBQ0kdDAzOTUwMjM5NjgxAl8xBAdiYWREZWJ0CAUNJHQwMzk1MDIzOTY4MQJfMgMJAQIhPQIFB2JhZERlYnQAAAkAAgECHUludmFsaWQgcmVtb3ZlZCBtYXJnaW4gYW1vdW50BAttYXJnaW5SYXRpbwkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwULbWFyZ2luUmF0aW8JAQ9pbml0TWFyZ2luUmF0aW8ABgkAAgEJAKwCAgkArAICCQCsAgICGVRvbyBtdWNoIG1hcmdpbiByZW1vdmVkOiAJAKQDAQULbWFyZ2luUmF0aW8CAyA8IAkApAMBCQEPaW5pdE1hcmdpblJhdGlvAAQHdW5zdGFrZQkA/AcECQERcXVvdGVBc3NldFN0YWtpbmcAAg51bmxvY2tOZXV0cmlubwkAzAgCBQdfYW1vdW50CQDMCAIJANgEAQkBCnF1b3RlQXNzZXQABQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBQkApQgBCAUBaQZjYWxsZXIFD29sZFBvc2l0aW9uU2l6ZQUMcmVtYWluTWFyZ2luBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9vbGRQb3NpdGlvblNpemUJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUHX2Ftb3VudAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1jbG9zZVBvc2l0aW9uAAMDAwkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQNJHQwNDA3Nzc0MTE2MQkBFWludGVybmFsQ2xvc2VQb3NpdGlvbgEJAKUIAQgFAWkGY2FsbGVyBAJ4MQgFDSR0MDQwNzc3NDExNjECXzEED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDQwNzc3NDExNjECXzIEC3JlYWxpemVkUG5sCAUNJHQwNDA3Nzc0MTE2MQJfMwQNbWFyZ2luVG9WYXVsdAgFDSR0MDQwNzc3NDExNjECXzQEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA0MDc3NzQxMTYxAl81BBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA0MDc3NzQxMTYxAl82BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNDA3Nzc0MTE2MQJfNwQXY3VtdWxhdGl2ZU5vdGlvbmFsQWZ0ZXIIBQ0kdDA0MDc3NzQxMTYxAl84BBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNDA3Nzc0MTE2MQJfOQQCeDIIBQ0kdDA0MDc3NzQxMTYxA18xMAQOdG90YWxMb25nQWZ0ZXIIBQ0kdDA0MDc3NzQxMTYxA18xMQQPdG90YWxTaG9ydEFmdGVyCAUNJHQwNDA3Nzc0MTE2MQNfMTIDCQBmAgUPcG9zaXRpb25CYWREZWJ0AAAJAAIBAiZVbmFibGUgdG8gY2xvc2UgcG9zaXRpb24gd2l0aCBiYWQgZGVidAQOd2l0aGRyYXdBbW91bnQJAQNhYnMBBQ1tYXJnaW5Ub1ZhdWx0BAphbW1CYWxhbmNlCQBlAgkBCGNiYWxhbmNlAAUOd2l0aGRyYXdBbW91bnQEDSR0MDQxMzcwNDE1MTIDCQBmAgAABQphbW1CYWxhbmNlCQCUCgIAAAkBA2FicwEFCmFtbUJhbGFuY2UJAJQKAgUKYW1tQmFsYW5jZQAABA1hbW1OZXdCYWxhbmNlCAUNJHQwNDEzNzA0MTUxMgJfMQQQZ2V0RnJvbUluc3VyYW5jZQgFDSR0MDQxMzcwNDE1MTICXzIEAXgDCQBmAgUQZ2V0RnJvbUluc3VyYW5jZQAABBF3aXRoZHJhd0luc3VyYW5jZQkA/AcECQEQaW5zdXJhbmNlQWRkcmVzcwACCHdpdGhkcmF3CQDMCAIFEGdldEZyb21JbnN1cmFuY2UFA25pbAUDbmlsAwkAAAIFEXdpdGhkcmF3SW5zdXJhbmNlBRF3aXRoZHJhd0luc3VyYW5jZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUBeAUBeAQHdW5zdGFrZQkA/AcECQERcXVvdGVBc3NldFN0YWtpbmcAAg51bmxvY2tOZXV0cmlubwkAzAgCCQBlAgUOd2l0aGRyYXdBbW91bnQFEGdldEZyb21JbnN1cmFuY2UJAMwIAgkA2AQBCQEKcXVvdGVBc3NldAAFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEDm5vdGlmeU5vdGlvbmFsCQD8BwQJAQxtaW5lckFkZHJlc3MAAg5ub3RpZnlOb3Rpb25hbAkAzAgCCQClCAEIBQFpBmNhbGxlcgkAzAgCAAAFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkBDmRlbGV0ZVBvc2l0aW9uAQkApQgBCAUBaQZjYWxsZXIJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFDndpdGhkcmF3QW1vdW50CQENdXBkYXRlQmFsYW5jZQEFDWFtbU5ld0JhbGFuY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJbGlxdWlkYXRlAQdfdHJhZGVyBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBAttYXJnaW5SYXRpbwMJARZpc092ZXJGbHVjdHVhdGlvbkxpbWl0AAQRb3JhY2xlTWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAgUHX3RyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvAwMDAwkBASEBCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFC21hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwAHBgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgEFB190cmFkZXIGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgECE1VuYWJsZSB0byBsaXF1aWRhdGUEDSR0MDQzMjAyNDM2MTgJARVpbnRlcm5hbENsb3NlUG9zaXRpb24BBQdfdHJhZGVyBAJ4MQgFDSR0MDQzMjAyNDM2MTgCXzEEB2JhZERlYnQIBQ0kdDA0MzIwMjQzNjE4Al8yBAJ4MggFDSR0MDQzMjAyNDM2MTgCXzMEAngzCAUNJHQwNDMyMDI0MzYxOAJfNAQWcXVvdGVBc3NldFJlc2VydmVBZnRlcggFDSR0MDQzMjAyNDM2MTgCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDQzMjAyNDM2MTgCXzYEFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIIBQ0kdDA0MzIwMjQzNjE4Al83BBdjdW11bGF0aXZlTm90aW9uYWxBZnRlcggFDSR0MDQzMjAyNDM2MTgCXzgEGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIIBQ0kdDA0MzIwMjQzNjE4Al85BBlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUNJHQwNDMyMDI0MzYxOANfMTAEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNDMyMDI0MzYxOANfMTEED3RvdGFsU2hvcnRBZnRlcggFDSR0MDQzMjAyNDM2MTgDXzEyBBJsaXF1aWRhdGlvblBlbmFsdHkJAQRtdWxkAgUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ABA9mZWVUb0xpcXVpZGF0b3IJAGkCBRJsaXF1aWRhdGlvblBlbmFsdHkAAgQOZmVlVG9JbnN1cmFuY2UJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFD2ZlZVRvTGlxdWlkYXRvcgQKYW1tQmFsYW5jZQkAZQIJAQhjYmFsYW5jZQAFEmxpcXVpZGF0aW9uUGVuYWx0eQQNJHQwNDQwMTY0NDE1MQMJAGYCAAAFCmFtbUJhbGFuY2UJAJQKAgAACQEDYWJzAQUKYW1tQmFsYW5jZQkAlAoCBQphbW1CYWxhbmNlAAAEDW5ld0FtbUJhbGFuY2UIBQ0kdDA0NDAxNjQ0MTUxAl8xBBF0YWtlRnJvbUluc3VyYW5jZQgFDSR0MDQ0MDE2NDQxNTECXzIEAXgDCQBmAgURdGFrZUZyb21JbnN1cmFuY2UAAAQRd2l0aGRyYXdJbnN1cmFuY2UJAPwHBAkBEGluc3VyYW5jZUFkZHJlc3MAAgh3aXRoZHJhdwkAzAgCBRF0YWtlRnJvbUluc3VyYW5jZQUDbmlsBQNuaWwDCQAAAgURd2l0aGRyYXdJbnN1cmFuY2UFEXdpdGhkcmF3SW5zdXJhbmNlBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQF4BQF4BAd1bnN0YWtlCQD8BwQJARFxdW90ZUFzc2V0U3Rha2luZwACDnVubG9ja05ldXRyaW5vCQDMCAIJAGUCBRJsaXF1aWRhdGlvblBlbmFsdHkFEXRha2VGcm9tSW5zdXJhbmNlCQDMCAIJANgEAQkBCnF1b3RlQXNzZXQABQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlBBBkZXBvc2l0SW5zdXJhbmNlCQD8BwQJARBpbnN1cmFuY2VBZGRyZXNzAAIHZGVwb3NpdAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFDmZlZVRvSW5zdXJhbmNlBQNuaWwDCQAAAgUQZGVwb3NpdEluc3VyYW5jZQUQZGVwb3NpdEluc3VyYW5jZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQ5ub3RpZnlOb3Rpb25hbAUObm90aWZ5Tm90aW9uYWwJAM4IAgkAzggCCQDOCAIJAQ5kZWxldGVQb3NpdGlvbgEFB190cmFkZXIJAQl1cGRhdGVBbW0HBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFF2N1bXVsYXRpdmVOb3Rpb25hbEFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABBVmdW5kaW5nQmxvY2tUaW1lc3RhbXAJARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAAMDAwkAZgIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAgFCWxhc3RCbG9jawl0aW1lc3RhbXAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAIDIDwgCQCkAwEFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAQPdW5kZXJseWluZ1ByaWNlCQESZ2V0T3JhY2xlVHdhcFByaWNlAAQNc3BvdFR3YXBQcmljZQkBEGdldFR3YXBTcG90UHJpY2UABAdwcmVtaXVtCQBlAgUNc3BvdFR3YXBQcmljZQUPdW5kZXJseWluZ1ByaWNlBA0kdDA0NTY0NTQ2OTgwAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAACQCUCgIAAAAAAwkAZgIAAAUHcHJlbWl1bQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZBBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJAJQKAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24EE2xvbmdQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZBBRzaG9ydFByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUACQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJAJQKAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24EFHNob3J0UHJlbWl1bUZyYWN0aW9uCAUNJHQwNDU2NDU0Njk4MAJfMQQTbG9uZ1ByZW1pdW1GcmFjdGlvbggFDSR0MDQ1NjQ1NDY5ODACXzIJAQ11cGRhdGVGdW5kaW5nBQkAZAIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAZAIJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFE2xvbmdQcmVtaXVtRnJhY3Rpb24JAGQCCQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UBaQEFdl9nZXQBB190cmFkZXIEDSR0MDQ3MzU1NDc0MDgJARVpbnRlcm5hbENsb3NlUG9zaXRpb24BBQdfdHJhZGVyBAJ4MQgFDSR0MDQ3MzU1NDc0MDgCXzEEAngyCAUNJHQwNDczNTU0NzQwOAJfMgQCeDMIBQ0kdDA0NzM1NTQ3NDA4Al8zBAJ4NAgFDSR0MDQ3MzU1NDc0MDgCXzQJAAIBCQCsAgIJAKwCAgkArAICCQEBcwEFAngyCQEBcwEFAngzCQEBcwEFAng0CQEBcwEJAQ5nZXRNYXJnaW5SYXRpbwEFB190cmFkZXIBaQEndmlld19jYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50AQdfdHJhZGVyBA0kdDA0NzU1NTQ3NjY2CQELZ2V0UG9zaXRpb24BBQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQ0kdDA0NzU1NTQ3NjY2Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDQ3NTU1NDc2NjYCXzIEA3BvbggFDSR0MDQ3NTU1NDc2NjYCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNDc1NTU0NzY2NgJfNAQNJHQwNDc2NzE0Nzc3MgkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAgUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UBBBwb3NpdGlvbk5vdGlvbmFsCAUNJHQwNDc2NzE0Nzc3MgJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDQ3NjcxNDc3NzICXzIEDSR0MDQ3Nzc3NDc5NTkJASJjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50BAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFDSR0MDQ3Nzc3NDc5NTkCXzEEB2JhZERlYnQIBQ0kdDA0Nzc3NzQ3OTU5Al8yBA5mdW5kaW5nUGF5bWVudAgFDSR0MDQ3Nzc3NDc5NTkCXzMJAAIBCQCsAgIJAKwCAgkBAXMBBQxyZW1haW5NYXJnaW4JAQFzAQUOZnVuZGluZ1BheW1lbnQJAQFzAQkBDmdldE1hcmdpblJhdGlvAQUHX3RyYWRlcgFpAQ5mb3JjZU1vdmVBc3NldAIHX3RyYWRlcgdfYW1vdW50AwMJAQIhPQIJAKcIAQkBDmFkbWluUHVibGljS2V5AAgFAWkGY2FsbGVyBgkAZgIAAAUHX2Ftb3VudAkAAgECIUludmFsaWQgZm9yY2VNb3ZlQXNzZXQgcGFyYW1ldGVycwQHdW5zdGFrZQkA/AcECQERcXVvdGVBc3NldFN0YWtpbmcAAg51bmxvY2tOZXV0cmlubwkAzAgCBQdfYW1vdW50CQDMCAIJANgEAQkBCnF1b3RlQXNzZXQABQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQDOCAIJAQh3aXRoZHJhdwIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB190cmFkZXIFB19hbW91bnQJAQ11cGRhdGVCYWxhbmNlAQkAZQIJAQhjYmFsYW5jZQAFB19hbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAnR4AQZ2ZXJpZnkACQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACQEOYWRtaW5QdWJsaWNLZXkAxZdflA==", "height": 2178067, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: D9R93wvrjVumiadztcugyjxbH4hBsCBuQmpxJpRZHtX5 Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let k_ora_key = "k_ora_key"
5+
6+let k_ora_block_key = "k_ora_block_key"
7+
8+let k_ora = "k_ora"
9+
10+let k_balance = "k_balance"
11+
12+let k_positionSize = "k_positionSize"
13+
14+let k_positionMargin = "k_positionMargin"
15+
16+let k_positionOpenNotional = "k_positionOpenNotional"
17+
18+let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
19+
20+let k_initialized = "k_initialized"
21+
22+let k_paused = "k_paused"
23+
24+let k_fee = "k_fee"
25+
26+let k_fundingPeriod = "k_fundingPeriod"
27+
28+let k_initMarginRatio = "k_initMarginRatio"
29+
30+let k_maintenanceMarginRatio = "k_mmr"
31+
32+let k_liquidationFeeRatio = "k_liquidationFeeRatio"
33+
34+let k_spreadLimit = "k_spreadLimit"
35+
36+let k_maxPriceImpact = "k_maxPriceImpact"
37+
38+let k_lastDataStr = "k_lastDataStr"
39+
40+let k_lastMinuteId = "k_lastMinuteId"
41+
42+let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
43+
44+let k_twapDataLastPrice = "k_twapDataLastPrice"
45+
46+let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
47+
48+let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
49+
50+let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
51+
52+let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
53+
54+let k_longFundingRate = "k_longFundingRate"
55+
56+let k_shortFundingRate = "k_shortFundingRate"
57+
58+let k_quoteAssetReserve = "k_qtAstR"
59+
60+let k_baseAssetReserve = "k_bsAstR"
61+
62+let k_totalPositionSize = "k_totalPositionSize"
63+
64+let k_totalLongPositionSize = "k_totalLongPositionSize"
65+
66+let k_totalShortPositionSize = "k_totalShortPositionSize"
67+
68+let k_cumulativeNotional = "k_cumulativeNotional"
69+
70+let k_openInterestNotional = "k_openInterestNotional"
71+
72+let k_coordinatorAddress = "k_coordinatorAddress"
73+
74+let k_insurance_address = "k_insurance_address"
75+
76+let k_admin_address = "k_admin_address"
77+
78+let k_admin_public_key = "k_admin_public_key"
79+
80+let k_quote_asset = "k_quote_asset"
81+
82+let k_quote_staking = "k_quote_staking"
83+
84+let k_staking_address = "k_staking_address"
85+
86+let k_miner_address = "k_miner_address"
87+
88+func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
89+
90+
91+func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
92+
93+
94+func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
95+
96+
97+func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
98+
99+
100+func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
101+
102+
103+func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Insurance not set")
104+
105+
106+func insuranceAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_insurance_address)), "Insurance not set")
107+
108+
109+func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Insurance not set")
110+
111+
112+let DIR_LONG = 1
113+
114+let DIR_SHORT = 2
115+
116+let TWAP_INTERVAL = 15
117+
118+let ORACLE_INTERVAL = 15
119+
120+let SECONDS = 1000
121+
122+let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
123+
124+let ONE_DAY = (86400 * DECIMAL_UNIT)
125+
126+let ALL_FEES = 100
127+
128+let PNL_OPTION_SPOT = 1
129+
130+let PNL_OPTION_ORACLE = 2
131+
132+func s (_x) = (toString(_x) + ",")
133+
134+
135+func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
136+
137+
138+func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
139+
140+
141+func abs (_x) = if ((_x > 0))
142+ then _x
143+ else -(_x)
144+
145+
146+func vmax (_x,_y) = if ((_x >= _y))
147+ then _x
148+ else _y
149+
150+
151+func toCompositeKey (_key,_address) = ((_key + "_") + _address)
152+
153+
154+func listToStr (_list) = {
155+ func _join (accumulator,val) = ((accumulator + val) + ",")
156+
157+ let newListStr = {
158+ let $l = _list
159+ let $s = size($l)
160+ let $acc0 = ""
161+ func $f0_1 ($a,$i) = if (($i >= $s))
162+ then $a
163+ else _join($a, $l[$i])
164+
165+ func $f0_2 ($a,$i) = if (($i >= $s))
166+ then $a
167+ else throw("List size exceeds 20")
168+
169+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
170+ }
171+ let newListStrU = dropRight(newListStr, 1)
172+ let newListStrR = if ((take(newListStrU, 1) == ","))
173+ then drop(newListStrU, 1)
174+ else newListStrU
175+ newListStrR
176+ }
177+
178+
179+func strToList (_str) = split(_str, ",")
180+
181+
182+func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
183+ then (removeByIndex(_list, 0) :+ _value)
184+ else (_list :+ _value)
185+
186+
187+func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
188+
189+
190+func cbalance () = int(k_balance)
191+
192+
193+func fee () = int(k_fee)
194+
195+
196+func initMarginRatio () = int(k_initMarginRatio)
197+
198+
199+func qtAstR () = int(k_quoteAssetReserve)
200+
201+
202+func bsAstR () = int(k_baseAssetReserve)
203+
204+
205+func totalPositionSize () = int(k_totalPositionSize)
206+
207+
208+func cumulativeNotional () = int(k_cumulativeNotional)
209+
210+
211+func openInterestNotional () = int(k_openInterestNotional)
212+
213+
214+func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
215+
216+
217+func fundingPeriodRaw () = int(k_fundingPeriod)
218+
219+
220+func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
221+
222+
223+func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
224+
225+
226+func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
227+
228+
229+func liquidationFeeRatio () = int(k_liquidationFeeRatio)
230+
231+
232+func spreadLimit () = int(k_spreadLimit)
233+
234+
235+func maxPriceImpact () = int(k_maxPriceImpact)
236+
237+
238+func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
239+
240+
241+func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
242+
243+
244+func totalShortPositionSize () = int(k_totalShortPositionSize)
245+
246+
247+func totalLongPositionSize () = int(k_totalLongPositionSize)
248+
249+
250+func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
251+ let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
252+ if (if (_largerThanOrEqualTo)
253+ then (0 > remainingMarginRatio)
254+ else false)
255+ then throw("Invalid margin")
256+ else if (if (!(_largerThanOrEqualTo))
257+ then (remainingMarginRatio >= 0)
258+ else false)
259+ then throw("Invalid margin")
260+ else true
261+ }
262+
263+
264+func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
265+ then throw("Should not be called with _positionSize == 0")
266+ else if ((_positionSize > 0))
267+ then latestLongCumulativePremiumFraction()
268+ else latestShortCumulativePremiumFraction()
269+
270+
271+func getPosition (_trader) = {
272+ let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
273+ match positionSizeOpt {
274+ case positionSize: Int =>
275+ $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
276+ case _ =>
277+ $Tuple4(0, 0, 0, 0)
278+ }
279+ }
280+
281+
282+func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
283+ then throw("No open position")
284+ else true
285+
286+
287+func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
288+
289+
290+func paused () = valueOrElse(getBoolean(this, k_paused), false)
291+
292+
293+func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
294+ then {
295+ let newBase = (bsAstR() - _baseAssetAmount)
296+ if ((0 >= newBase))
297+ then throw("Tx lead to base asset reserve <= 0, revert")
298+ else $Tuple4((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount), (cumulativeNotional() + _quoteAssetAmount))
299+ }
300+ else {
301+ let newQuote = (qtAstR() - _quoteAssetAmount)
302+ if ((0 >= newQuote))
303+ then throw("Tx lead to base quote reserve <= 0, revert")
304+ else $Tuple4(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount), (cumulativeNotional() - _quoteAssetAmount))
305+ }
306+
307+
308+func swapInput (_isAdd,_quoteAssetAmount) = {
309+ let _qtAstR = qtAstR()
310+ let _bsAstR = bsAstR()
311+ let priceBefore = divd(_qtAstR, _bsAstR)
312+ let amountBaseAssetBoughtWithoutPriceImpact = muld(_quoteAssetAmount, priceBefore)
313+ let k = muld(_qtAstR, _bsAstR)
314+ let quoteAssetReserveAfter = if (_isAdd)
315+ then (_qtAstR + _quoteAssetAmount)
316+ else (_qtAstR - _quoteAssetAmount)
317+ let baseAssetReserveAfter = divd(k, quoteAssetReserveAfter)
318+ let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
319+ let amountBaseAssetBought = if (_isAdd)
320+ then amountBaseAssetBoughtAbs
321+ else -(amountBaseAssetBoughtAbs)
322+ let priceImpact = ((amountBaseAssetBoughtWithoutPriceImpact - amountBaseAssetBoughtAbs) / amountBaseAssetBoughtWithoutPriceImpact)
323+ let maxPriceImpactValue = maxPriceImpact()
324+ if ((priceImpact > maxPriceImpactValue))
325+ then throw(((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)))
326+ else {
327+ let $t01231212515 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
328+ let quoteAssetReserveAfter1 = $t01231212515._1
329+ let baseAssetReserveAfter1 = $t01231212515._2
330+ let totalPositionSizeAfter1 = $t01231212515._3
331+ let cumulativeNotionalAfter1 = $t01231212515._4
332+ $Tuple5(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1)
333+ }
334+ }
335+
336+
337+func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
338+ let fundingPayment = if ((_oldPositionSize != 0))
339+ then {
340+ let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
341+ muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
342+ }
343+ else 0
344+ let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
345+ let $t01326213389 = if ((0 > signedMargin))
346+ then $Tuple2(0, abs(signedMargin))
347+ else $Tuple2(abs(signedMargin), 0)
348+ let remainMargin = $t01326213389._1
349+ let badDebt = $t01326213389._2
350+ $Tuple3(remainMargin, badDebt, fundingPayment)
351+ }
352+
353+
354+func swapOutput (_isAdd,_baseAssetAmount) = {
355+ let _quoteAssetReserve = qtAstR()
356+ let _baseAssetReserve = bsAstR()
357+ if ((_baseAssetAmount == 0))
358+ then throw("Invalid base asset amount")
359+ else {
360+ let k = muld(_quoteAssetReserve, _baseAssetReserve)
361+ let baseAssetPoolAmountAfter = if (_isAdd)
362+ then (_baseAssetReserve + _baseAssetAmount)
363+ else (_baseAssetReserve - _baseAssetAmount)
364+ let quoteAssetAfter = divd(k, baseAssetPoolAmountAfter)
365+ let quoteAssetSold = abs((quoteAssetAfter - _quoteAssetReserve))
366+ let $t01422714420 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
367+ let quoteAssetReserveAfter1 = $t01422714420._1
368+ let baseAssetReserveAfter1 = $t01422714420._2
369+ let totalPositionSizeAfter1 = $t01422714420._3
370+ let cumulativeNotionalAfter1 = $t01422714420._4
371+ $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1, (totalLongPositionSize() - (if (_isAdd)
372+ then abs(_baseAssetAmount)
373+ else 0)), (totalShortPositionSize() - (if (!(_isAdd))
374+ then abs(_baseAssetAmount)
375+ else 0)))
376+ }
377+ }
378+
379+
380+func getOracleTwapPrice () = {
381+ let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
382+ let priceKey = getStringValue(this, k_ora_key)
383+ let blockKey = getStringValue(this, k_ora_block_key)
384+ let lastValue = getIntegerValue(oracle, priceKey)
385+ lastValue
386+ }
387+
388+
389+func getSpotPrice () = {
390+ let _quoteAssetReserve = qtAstR()
391+ let _baseAssetReserve = bsAstR()
392+ divd(_quoteAssetReserve, _baseAssetReserve)
393+ }
394+
395+
396+func isOverFluctuationLimit () = {
397+ let oraclePrice = getOracleTwapPrice()
398+ let currentPrice = getSpotPrice()
399+ (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
400+ }
401+
402+
403+func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
404+ let $t01605216180 = getPosition(_trader)
405+ let positionSize = $t01605216180._1
406+ let positionMargin = $t01605216180._2
407+ let positionOpenNotional = $t01605216180._3
408+ let positionLstUpdCPF = $t01605216180._4
409+ let positionSizeAbs = abs(positionSize)
410+ if ((positionSizeAbs == 0))
411+ then throw("Invalid position size")
412+ else {
413+ let isShort = (0 > positionSize)
414+ let positionNotional = if ((_option == PNL_OPTION_SPOT))
415+ then {
416+ let $t01642716534 = swapOutput(!(isShort), positionSizeAbs)
417+ let outPositionNotional = $t01642716534._1
418+ let x1 = $t01642716534._2
419+ let x2 = $t01642716534._3
420+ let x3 = $t01642716534._4
421+ outPositionNotional
422+ }
423+ else muld(positionSizeAbs, getOracleTwapPrice())
424+ let unrealizedPnl = if (isShort)
425+ then (positionOpenNotional - positionNotional)
426+ else (positionNotional - positionOpenNotional)
427+ $Tuple2(positionNotional, unrealizedPnl)
428+ }
429+ }
430+
431+
432+func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
433+
434+
435+func getMarginRatioByOption (_trader,_option) = {
436+ let $t01720417315 = getPosition(_trader)
437+ let positionSize = $t01720417315._1
438+ let positionMargin = $t01720417315._2
439+ let pon = $t01720417315._3
440+ let positionLstUpdCPF = $t01720417315._4
441+ let $t01732117414 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
442+ let positionNotional = $t01732117414._1
443+ let unrealizedPnl = $t01732117414._2
444+ let $t01741917585 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
445+ let remainMargin = $t01741917585._1
446+ let badDebt = $t01741917585._2
447+ calcMarginRatio(remainMargin, badDebt, positionNotional)
448+ }
449+
450+
451+func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
452+
453+
454+func internalClosePosition (_trader) = {
455+ let $t01790118029 = getPosition(_trader)
456+ let positionSize = $t01790118029._1
457+ let positionMargin = $t01790118029._2
458+ let positionOpenNotional = $t01790118029._3
459+ let positionLstUpdCPF = $t01790118029._4
460+ let $t01803518122 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
461+ let x1 = $t01803518122._1
462+ let unrealizedPnl = $t01803518122._2
463+ let $t01812718295 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
464+ let remainMargin = $t01812718295._1
465+ let badDebt = $t01812718295._2
466+ let exchangedPositionSize = -(positionSize)
467+ let realizedPnl = unrealizedPnl
468+ let marginToVault = -(remainMargin)
469+ let $t01842218703 = swapOutput((positionSize > 0), abs(positionSize))
470+ let exchangedQuoteAssetAmount = $t01842218703._1
471+ let quoteAssetReserveAfter = $t01842218703._2
472+ let baseAssetReserveAfter = $t01842218703._3
473+ let totalPositionSizeAfter = $t01842218703._4
474+ let cumulativeNotionalAfter = $t01842218703._5
475+ let totalLongAfter = $t01842218703._6
476+ let totalShortAfter = $t01842218703._7
477+ let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
478+ $Tuple12(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter)
479+ }
480+
481+
482+func getTwapSpotPrice () = {
483+ let minuteId = ((lastBlock.timestamp / 1000) / 60)
484+ let startMinuteId = (minuteId - TWAP_INTERVAL)
485+ let listStr = valueOrElse(getString(this, k_lastDataStr), "")
486+ let list = split(listStr, ",")
487+ func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
488+ then (accumulator :+ parseIntValue(next))
489+ else accumulator
490+
491+ let listF = {
492+ let $l = list
493+ let $s = size($l)
494+ let $acc0 = nil
495+ func $f0_1 ($a,$i) = if (($i >= $s))
496+ then $a
497+ else filterFn($a, $l[$i])
498+
499+ func $f0_2 ($a,$i) = if (($i >= $s))
500+ then $a
501+ else throw("List size exceeds 20")
502+
503+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
504+ }
505+ let maxIndex = if ((size(listF) > 0))
506+ then max(listF)
507+ else parseIntValue(list[0])
508+ let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
509+ let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
510+ let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
511+ let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
512+ let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
513+ let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
514+ let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
515+ ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
516+ }
517+
518+
519+func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact)]
520+
521+
522+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)]
523+
524+
525+func updatePosition (_address,_size,_margin,_openNotional,_latestCumulativePremiumFraction) = [IntegerEntry(toCompositeKey(k_positionSize, _address), _size), IntegerEntry(toCompositeKey(k_positionMargin, _address), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, _address), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address), _latestCumulativePremiumFraction)]
526+
527+
528+func appendTwap (price) = {
529+ let minuteId = ((lastBlock.timestamp / 1000) / 60)
530+ let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
531+ if ((previousMinuteId > minuteId))
532+ then throw("TWAP out-of-order")
533+ else {
534+ let lastMinuteId = if ((previousMinuteId == 0))
535+ then minuteId
536+ else previousMinuteId
537+ if ((minuteId > previousMinuteId))
538+ then {
539+ let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
540+ let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), price)
541+ let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
542+ let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
543+[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price), IntegerEntry(toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId)), previousMinuteId), IntegerEntry(k_lastMinuteId, minuteId), StringEntry(k_lastDataStr, listToStr(list))]
544+ }
545+ else {
546+ let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
547+ let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
548+ let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), price)
549+ let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
550+[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price)]
551+ }
552+ }
553+ }
554+
555+
556+func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
557+
558+
559+func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_cumulativeNotionalAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize) = if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
560+ then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
561+ else ((updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_cumulativeNotional, _cumulativeNotionalAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize)]) ++ appendTwap(divd(_qtAstR, _bsAstR)))
562+
563+
564+func deletePosition (_address) = [DeleteEntry(toCompositeKey(k_positionSize, _address)), DeleteEntry(toCompositeKey(k_positionMargin, _address)), DeleteEntry(toCompositeKey(k_positionOpenNotional, _address)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address))]
565+
566+
567+func withdraw (_address,_amount) = {
568+ let balance = assetBalance(this, quoteAsset())
569+ if ((_amount > balance))
570+ then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
571+ else [ScriptTransfer(_address, _amount, quoteAsset())]
572+ }
573+
574+
575+func updateBalance (i) = if ((0 > i))
576+ then throw("Balance")
577+ else [IntegerEntry(k_balance, i)]
578+
579+
580+func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
581+
582+
583+@Callable(i)
584+func pause () = if ((i.caller != adminAddress()))
585+ then throw("Invalid togglePause params")
586+ else [BooleanEntry(k_paused, true)]
587+
588+
589+
590+@Callable(i)
591+func unpause () = if ((i.caller != adminAddress()))
592+ then throw("Invalid togglePause params")
593+ else [BooleanEntry(k_paused, false)]
594+
595+
596+
597+@Callable(i)
598+func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
599+ then true
600+ else (0 >= _quoteAssetAmount))
601+ then throw("Invalid addLiquidity params")
602+ else {
603+ let _qtAstR = qtAstR()
604+ let _bsAstR = bsAstR()
605+ let price = divd(_qtAstR, _bsAstR)
606+ let baseAssetAmountToAdd = divd(_quoteAssetAmount, price)
607+ let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
608+ let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
609+ updateAmmReserves(qtAstRAfter, bsAstRAfter)
610+ }
611+
612+
613+
614+@Callable(i)
615+func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
616+ then true
617+ else (0 >= _quoteAssetAmount))
618+ then throw("Invalid removeLiquidity params")
619+ else {
620+ let _qtAstR = qtAstR()
621+ let _bsAstR = bsAstR()
622+ let price = divd(_qtAstR, _bsAstR)
623+ let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
624+ let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
625+ let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
626+ updateAmmReserves(qtAstRAfter, bsAstRAfter)
627+ }
628+
629+
630+
631+@Callable(i)
632+func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact) = if ((i.caller != adminAddress()))
633+ then throw("Invalid changeSettings params")
634+ else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact)
635+
636+
637+
638+@Callable(i)
639+func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_oracle,_oracleKey,_coordinator,_spreadLimit,_maxPriceImpact) = if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
640+ then true
641+ else (0 >= _bsAstR))
642+ then true
643+ else (0 >= _fundingPeriod))
644+ then true
645+ else (0 >= _initMarginRatio))
646+ then true
647+ else (0 >= _mmr))
648+ then true
649+ else (0 >= _liquidationFeeRatio))
650+ then true
651+ else (0 >= _fee))
652+ then true
653+ else (0 >= _spreadLimit))
654+ then true
655+ else (0 >= _maxPriceImpact))
656+ then true
657+ else initialized())
658+ then throw("Invalid initialize parameters")
659+ else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact)) ++ updateFunding((lastBlock.timestamp + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_ora, _oracle), StringEntry(k_ora_key, _oracleKey), StringEntry(k_coordinatorAddress, _coordinator)])
660+
661+
662+
663+@Callable(i)
664+func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = if (if (if (if (if ((0 >= _amount))
665+ then true
666+ else !(initialized()))
667+ then true
668+ else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
669+ then true
670+ else !(requireOpenPosition(toString(i.caller))))
671+ then true
672+ else paused())
673+ then throw("Invalid decreasePosition parameters")
674+ else {
675+ let $t02961229764 = getPosition(toString(i.caller))
676+ let oldPositionSize = $t02961229764._1
677+ let oldPositionMargin = $t02961229764._2
678+ let oldPositionOpenNotional = $t02961229764._3
679+ let oldPositionLstUpdCPF = $t02961229764._4
680+ let _direction = if ((oldPositionSize > 0))
681+ then DIR_SHORT
682+ else DIR_LONG
683+ let isAdd = (_direction == DIR_LONG)
684+ let openNotional = muld(_amount, _leverage)
685+ let $t02993730053 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
686+ let oldPositionNotional = $t02993730053._1
687+ let unrealizedPnl = $t02993730053._2
688+ let $t03005932608 = if ((oldPositionNotional > openNotional))
689+ then {
690+ let $t03043630655 = swapInput(isAdd, openNotional)
691+ let exchangedPositionSize = $t03043630655._1
692+ let quoteAssetReserveAfter = $t03043630655._2
693+ let baseAssetReserveAfter = $t03043630655._3
694+ let totalPositionSizeAfter = $t03043630655._4
695+ let cumulativeNotionalAfter = $t03043630655._5
696+ let exchangedPositionSizeAbs = abs(exchangedPositionSize)
697+ if (if ((_minBaseAssetAmount != 0))
698+ then (_minBaseAssetAmount > exchangedPositionSizeAbs)
699+ else false)
700+ then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
701+ else {
702+ let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
703+ let $t03109231337 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
704+ let remainMargin = $t03109231337._1
705+ let badDebt = $t03109231337._2
706+ let fundingPayment = $t03109231337._3
707+ let exchangedQuoteAssetAmount = openNotional
708+ let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
709+ let remainOpenNotional = if ((oldPositionSize > 0))
710+ then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
711+ else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
712+ let newPositionSize = (oldPositionSize + exchangedPositionSize)
713+ $Tuple11(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
714+ then abs(exchangedPositionSize)
715+ else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
716+ then abs(exchangedPositionSize)
717+ else 0)))
718+ }
719+ }
720+ else throw("Close position first")
721+ let newPositionSize = $t03005932608._1
722+ let newPositionRemainMargin = $t03005932608._2
723+ let newPositionOpenNotional = $t03005932608._3
724+ let newPositionLatestCPF = $t03005932608._4
725+ let baseAssetReserveAfter = $t03005932608._5
726+ let quoteAssetReserveAfter = $t03005932608._6
727+ let totalPositionSizeAfter = $t03005932608._7
728+ let cumulativeNotionalAfter = $t03005932608._8
729+ let openInterestNotionalAfter = $t03005932608._9
730+ let totalLongAfter = $t03005932608._10
731+ let totalShortAfter = $t03005932608._11
732+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
733+ if ((notifyNotional == notifyNotional))
734+ then (updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter))
735+ else throw("Strict value is not equal to itself.")
736+ }
737+
738+
739+
740+@Callable(i)
741+func increasePosition (_direction,_leverage,_minBaseAssetAmount) = {
742+ let _rawAmount = i.payments[0].amount
743+ if (if (if (if (if (if (if ((_direction != DIR_LONG))
744+ then (_direction != DIR_SHORT)
745+ else false)
746+ then true
747+ else (0 >= _rawAmount))
748+ then true
749+ else !(initialized()))
750+ then true
751+ else (i.payments[0].assetId != quoteAsset()))
752+ then true
753+ else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
754+ then true
755+ else paused())
756+ then throw("Invalid increasePosition parameters")
757+ else {
758+ let feeAmount = muld(_rawAmount, fee())
759+ let _amount = (_rawAmount - feeAmount)
760+ let $t03372633878 = getPosition(toString(i.caller))
761+ let oldPositionSize = $t03372633878._1
762+ let oldPositionMargin = $t03372633878._2
763+ let oldPositionOpenNotional = $t03372633878._3
764+ let oldPositionLstUpdCPF = $t03372633878._4
765+ let isNewPosition = (oldPositionSize == 0)
766+ let isSameDirection = if ((oldPositionSize > 0))
767+ then (_direction == DIR_LONG)
768+ else (_direction == DIR_SHORT)
769+ let expandExisting = if (!(isNewPosition))
770+ then isSameDirection
771+ else false
772+ let isAdd = (_direction == DIR_LONG)
773+ let $t03416736556 = if (if (isNewPosition)
774+ then true
775+ else expandExisting)
776+ then {
777+ let openNotional = muld(_amount, _leverage)
778+ let $t03459134797 = swapInput(isAdd, openNotional)
779+ let amountBaseAssetBought = $t03459134797._1
780+ let quoteAssetReserveAfter = $t03459134797._2
781+ let baseAssetReserveAfter = $t03459134797._3
782+ let totalPositionSizeAfter = $t03459134797._4
783+ let cumulativeNotionalAfter = $t03459134797._5
784+ if (if ((_minBaseAssetAmount != 0))
785+ then (_minBaseAssetAmount > abs(amountBaseAssetBought))
786+ else false)
787+ then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
788+ else {
789+ let newPositionSize = (oldPositionSize + amountBaseAssetBought)
790+ let increaseMarginRequirement = divd(openNotional, _leverage)
791+ let $t03517835417 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
792+ let remainMargin = $t03517835417._1
793+ let x1 = $t03517835417._2
794+ let x2 = $t03517835417._3
795+ $Tuple11(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
796+ then abs(amountBaseAssetBought)
797+ else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
798+ then abs(amountBaseAssetBought)
799+ else 0)))
800+ }
801+ }
802+ else {
803+ let openNotional = muld(_amount, _leverage)
804+ let $t03624936365 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
805+ let oldPositionNotional = $t03624936365._1
806+ let unrealizedPnl = $t03624936365._2
807+ if ((oldPositionNotional > openNotional))
808+ then throw("Use decreasePosition to decrease position size")
809+ else throw("Close position first")
810+ }
811+ let newPositionSize = $t03416736556._1
812+ let newPositionRemainMargin = $t03416736556._2
813+ let newPositionOpenNotional = $t03416736556._3
814+ let newPositionLatestCPF = $t03416736556._4
815+ let baseAssetReserveAfter = $t03416736556._5
816+ let quoteAssetReserveAfter = $t03416736556._6
817+ let totalPositionSizeAfter = $t03416736556._7
818+ let cumulativeNotionalAfter = $t03416736556._8
819+ let openInterestNotionalAfter = $t03416736556._9
820+ let totalLongAfter = $t03416736556._10
821+ let totalShortAfter = $t03416736556._11
822+ let feeToStakers = (feeAmount / 2)
823+ let feeToInsurance = (feeAmount - feeToStakers)
824+ let stake = invoke(quoteAssetStaking(), "lockNeutrinoSP", [toString(stakingAddress()), ALL_FEES], [AttachedPayment(quoteAsset(), _amount)])
825+ if ((stake == stake))
826+ then {
827+ let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
828+ if ((depositInsurance == depositInsurance))
829+ then {
830+ let notifyFee = invoke(minerAddress(), "notifyFees", [toString(i.caller), feeAmount], nil)
831+ if ((notifyFee == notifyFee))
832+ then {
833+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
834+ if ((notifyNotional == notifyNotional))
835+ then (((updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount)))
836+ else throw("Strict value is not equal to itself.")
837+ }
838+ else throw("Strict value is not equal to itself.")
839+ }
840+ else throw("Strict value is not equal to itself.")
841+ }
842+ else throw("Strict value is not equal to itself.")
843+ }
844+ }
845+
846+
847+
848+@Callable(i)
849+func addMargin () = {
850+ let _rawAmount = i.payments[0].amount
851+ if (if (if (if ((i.payments[0].assetId != quoteAsset()))
852+ then true
853+ else !(requireOpenPosition(toString(i.caller))))
854+ then true
855+ else !(initialized()))
856+ then true
857+ else paused())
858+ then throw("Invalid addMargin parameters")
859+ else {
860+ let feeAmount = muld(_rawAmount, fee())
861+ let _amount = (_rawAmount - feeAmount)
862+ let $t03811238264 = getPosition(toString(i.caller))
863+ let oldPositionSize = $t03811238264._1
864+ let oldPositionMargin = $t03811238264._2
865+ let oldPositionOpenNotional = $t03811238264._3
866+ let oldPositionLstUpdCPF = $t03811238264._4
867+ let feeToStakers = (feeAmount / 2)
868+ let feeToInsurance = (feeAmount - feeToStakers)
869+ let stake = invoke(quoteAssetStaking(), "lockNeutrinoSP", [toString(stakingAddress()), ALL_FEES], [AttachedPayment(quoteAsset(), _amount)])
870+ if ((stake == stake))
871+ then {
872+ let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
873+ if ((depositInsurance == depositInsurance))
874+ then {
875+ let notifyFee = invoke(minerAddress(), "notifyFees", [toString(i.caller), feeAmount], nil)
876+ if ((notifyFee == notifyFee))
877+ then ((updatePosition(toString(i.caller), oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount)))
878+ else throw("Strict value is not equal to itself.")
879+ }
880+ else throw("Strict value is not equal to itself.")
881+ }
882+ else throw("Strict value is not equal to itself.")
883+ }
884+ }
885+
886+
887+
888+@Callable(i)
889+func removeMargin (_amount) = if (if (if (if ((0 >= _amount))
890+ then true
891+ else !(requireOpenPosition(toString(i.caller))))
892+ then true
893+ else !(initialized()))
894+ then true
895+ else paused())
896+ then throw("Invalid removeMargin parameters")
897+ else {
898+ let $t03931339465 = getPosition(toString(i.caller))
899+ let oldPositionSize = $t03931339465._1
900+ let oldPositionMargin = $t03931339465._2
901+ let oldPositionOpenNotional = $t03931339465._3
902+ let oldPositionLstUpdCPF = $t03931339465._4
903+ let marginDelta = -(_amount)
904+ let $t03950239681 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
905+ let remainMargin = $t03950239681._1
906+ let badDebt = $t03950239681._2
907+ if ((badDebt != 0))
908+ then throw("Invalid removed margin amount")
909+ else {
910+ let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
911+ if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
912+ then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
913+ else {
914+ let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [_amount, toBase58String(quoteAsset())], nil)
915+ if ((unstake == unstake))
916+ then ((updatePosition(toString(i.caller), oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ withdraw(i.caller, _amount)) ++ updateBalance((cbalance() - _amount)))
917+ else throw("Strict value is not equal to itself.")
918+ }
919+ }
920+ }
921+
922+
923+
924+@Callable(i)
925+func closePosition () = if (if (if (!(requireOpenPosition(toString(i.caller))))
926+ then true
927+ else !(initialized()))
928+ then true
929+ else paused())
930+ then throw("Invalid closePosition parameters")
931+ else {
932+ let $t04077741161 = internalClosePosition(toString(i.caller))
933+ let x1 = $t04077741161._1
934+ let positionBadDebt = $t04077741161._2
935+ let realizedPnl = $t04077741161._3
936+ let marginToVault = $t04077741161._4
937+ let quoteAssetReserveAfter = $t04077741161._5
938+ let baseAssetReserveAfter = $t04077741161._6
939+ let totalPositionSizeAfter = $t04077741161._7
940+ let cumulativeNotionalAfter = $t04077741161._8
941+ let openInterestNotionalAfter = $t04077741161._9
942+ let x2 = $t04077741161._10
943+ let totalLongAfter = $t04077741161._11
944+ let totalShortAfter = $t04077741161._12
945+ if ((positionBadDebt > 0))
946+ then throw("Unable to close position with bad debt")
947+ else {
948+ let withdrawAmount = abs(marginToVault)
949+ let ammBalance = (cbalance() - withdrawAmount)
950+ let $t04137041512 = if ((0 > ammBalance))
951+ then $Tuple2(0, abs(ammBalance))
952+ else $Tuple2(ammBalance, 0)
953+ let ammNewBalance = $t04137041512._1
954+ let getFromInsurance = $t04137041512._2
955+ let x = if ((getFromInsurance > 0))
956+ then {
957+ let withdrawInsurance = invoke(insuranceAddress(), "withdraw", [getFromInsurance], nil)
958+ if ((withdrawInsurance == withdrawInsurance))
959+ then nil
960+ else throw("Strict value is not equal to itself.")
961+ }
962+ else nil
963+ if ((x == x))
964+ then {
965+ let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [(withdrawAmount - getFromInsurance), toBase58String(quoteAsset())], nil)
966+ if ((unstake == unstake))
967+ then {
968+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), 0], nil)
969+ if ((notifyNotional == notifyNotional))
970+ then (((deletePosition(toString(i.caller)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ withdraw(i.caller, withdrawAmount)) ++ updateBalance(ammNewBalance))
971+ else throw("Strict value is not equal to itself.")
972+ }
973+ else throw("Strict value is not equal to itself.")
974+ }
975+ else throw("Strict value is not equal to itself.")
976+ }
977+ }
978+
979+
980+
981+@Callable(i)
982+func liquidate (_trader) = {
983+ let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
984+ let marginRatio = if (isOverFluctuationLimit())
985+ then {
986+ let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
987+ vmax(spotMarginRatio, oracleMarginRatio)
988+ }
989+ else spotMarginRatio
990+ if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
991+ then true
992+ else !(requireOpenPosition(_trader)))
993+ then true
994+ else !(initialized()))
995+ then true
996+ else paused())
997+ then throw("Unable to liquidate")
998+ else {
999+ let $t04320243618 = internalClosePosition(_trader)
1000+ let x1 = $t04320243618._1
1001+ let badDebt = $t04320243618._2
1002+ let x2 = $t04320243618._3
1003+ let x3 = $t04320243618._4
1004+ let quoteAssetReserveAfter = $t04320243618._5
1005+ let baseAssetReserveAfter = $t04320243618._6
1006+ let totalPositionSizeAfter = $t04320243618._7
1007+ let cumulativeNotionalAfter = $t04320243618._8
1008+ let openInterestNotionalAfter = $t04320243618._9
1009+ let exchangedQuoteAssetAmount = $t04320243618._10
1010+ let totalLongAfter = $t04320243618._11
1011+ let totalShortAfter = $t04320243618._12
1012+ let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
1013+ let feeToLiquidator = (liquidationPenalty / 2)
1014+ let feeToInsurance = (liquidationPenalty - feeToLiquidator)
1015+ let ammBalance = (cbalance() - liquidationPenalty)
1016+ let $t04401644151 = if ((0 > ammBalance))
1017+ then $Tuple2(0, abs(ammBalance))
1018+ else $Tuple2(ammBalance, 0)
1019+ let newAmmBalance = $t04401644151._1
1020+ let takeFromInsurance = $t04401644151._2
1021+ let x = if ((takeFromInsurance > 0))
1022+ then {
1023+ let withdrawInsurance = invoke(insuranceAddress(), "withdraw", [takeFromInsurance], nil)
1024+ if ((withdrawInsurance == withdrawInsurance))
1025+ then nil
1026+ else throw("Strict value is not equal to itself.")
1027+ }
1028+ else nil
1029+ if ((x == x))
1030+ then {
1031+ let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [(liquidationPenalty - takeFromInsurance), toBase58String(quoteAsset())], nil)
1032+ if ((unstake == unstake))
1033+ then {
1034+ let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1035+ if ((depositInsurance == depositInsurance))
1036+ then {
1037+ let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
1038+ if ((notifyNotional == notifyNotional))
1039+ then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
1040+ else throw("Strict value is not equal to itself.")
1041+ }
1042+ else throw("Strict value is not equal to itself.")
1043+ }
1044+ else throw("Strict value is not equal to itself.")
1045+ }
1046+ else throw("Strict value is not equal to itself.")
1047+ }
1048+ }
1049+
1050+
1051+
1052+@Callable(i)
1053+func payFunding () = {
1054+ let fundingBlockTimestamp = nextFundingBlockTimestamp()
1055+ if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
1056+ then true
1057+ else !(initialized()))
1058+ then true
1059+ else paused())
1060+ then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
1061+ else {
1062+ let underlyingPrice = getOracleTwapPrice()
1063+ let spotTwapPrice = getTwapSpotPrice()
1064+ let premium = (spotTwapPrice - underlyingPrice)
1065+ let $t04564546980 = if (if ((totalShortPositionSize() == 0))
1066+ then true
1067+ else (totalLongPositionSize() == 0))
1068+ then $Tuple2(0, 0)
1069+ else if ((0 > premium))
1070+ then {
1071+ let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
1072+ let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
1073+ $Tuple2(shortPremiumFraction, longPremiumFraction)
1074+ }
1075+ else {
1076+ let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
1077+ let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
1078+ $Tuple2(shortPremiumFraction, longPremiumFraction)
1079+ }
1080+ let shortPremiumFraction = $t04564546980._1
1081+ let longPremiumFraction = $t04564546980._2
1082+ updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1083+ }
1084+ }
1085+
1086+
1087+
1088+@Callable(i)
1089+func v_get (_trader) = {
1090+ let $t04735547408 = internalClosePosition(_trader)
1091+ let x1 = $t04735547408._1
1092+ let x2 = $t04735547408._2
1093+ let x3 = $t04735547408._3
1094+ let x4 = $t04735547408._4
1095+ throw((((s(x2) + s(x3)) + s(x4)) + s(getMarginRatio(_trader))))
1096+ }
1097+
1098+
1099+
1100+@Callable(i)
1101+func view_calcRemainMarginWithFundingPayment (_trader) = {
1102+ let $t04755547666 = getPosition(_trader)
1103+ let positionSize = $t04755547666._1
1104+ let positionMargin = $t04755547666._2
1105+ let pon = $t04755547666._3
1106+ let positionLstUpdCPF = $t04755547666._4
1107+ let $t04767147772 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1108+ let positionNotional = $t04767147772._1
1109+ let unrealizedPnl = $t04767147772._2
1110+ let $t04777747959 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1111+ let remainMargin = $t04777747959._1
1112+ let badDebt = $t04777747959._2
1113+ let fundingPayment = $t04777747959._3
1114+ throw(((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))))
1115+ }
1116+
1117+
1118+
1119+@Callable(i)
1120+func forceMoveAsset (_trader,_amount) = if (if ((addressFromPublicKey(adminPublicKey()) != i.caller))
1121+ then true
1122+ else (0 > _amount))
1123+ then throw("Invalid forceMoveAsset parameters")
1124+ else {
1125+ let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [_amount, toBase58String(quoteAsset())], nil)
1126+ if ((unstake == unstake))
1127+ then (withdraw(addressFromStringValue(_trader), _amount) ++ updateBalance((cbalance() - _amount)))
1128+ else throw("Strict value is not equal to itself.")
1129+ }
1130+
1131+
1132+@Verifier(tx)
1133+func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
1134+

github/deemru/w8io/026f985 
53.10 ms