tx · 7GX6k16jNdeL7SbAwX3q2g8jUrvEhc6jbb5Cf8NKX13y

3MuzRcW6fRnqCC76KgKznZP68qsWB1J6shn:  -0.07500000 Waves

2023.04.28 10:01 [2554086] smart account 3MuzRcW6fRnqCC76KgKznZP68qsWB1J6shn > SELF 0.00000000 Waves

{ "type": 13, "id": "7GX6k16jNdeL7SbAwX3q2g8jUrvEhc6jbb5Cf8NKX13y", "fee": 7500000, "feeAssetId": null, "timestamp": 1682665299727, "version": 2, "chainId": 84, "sender": "3MuzRcW6fRnqCC76KgKznZP68qsWB1J6shn", "senderPublicKey": "EjNbd48ENcnJ4wjBkASdYJHavM8QHrAbFDbJ46ffyUcU", "proofs": [ "3DUdDLymV6JjKffhBzNpTzm8is2Pf67jaG67APXqhHRe11hjyd1BAkEQhJHZEdz3mBTc2DhQy5db1rF8jXmHirht" ], "script": "base64:BgKAAQgCEgASABIAEgASAwoBARIDCgEBEhAKDgEBAQEBAQEBAQEBAQEBEhUKEwEBAQEBAQEICAgBAQEBAQEBAQESBgoEAQEBCBIDCgEBEgQKAgEBEgYKBAEBAQQSBAoCCAESABIAEgASAwoBCBIECgIIARIDCgEBEgASABIAEgQKAggIrwEADGtfYmFzZU9yYWNsZQIMa19iYXNlT3JhY2xlAA1rX3F1b3RlT3JhY2xlAg1rX3F1b3RlT3JhY2xlAAlrX2JhbGFuY2UCCWtfYmFsYW5jZQAKa19zZXF1ZW5jZQIKa19zZXF1ZW5jZQAOa19wb3NpdGlvblNpemUCDmtfcG9zaXRpb25TaXplABBrX3Bvc2l0aW9uTWFyZ2luAhBrX3Bvc2l0aW9uTWFyZ2luABZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsAhZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsAC5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAhJrX3Bvc2l0aW9uRnJhY3Rpb24AEmtfcG9zaXRpb25TZXF1ZW5jZQISa19wb3NpdGlvblNlcXVlbmNlAA1rX3Bvc2l0aW9uRmVlAg1rX3Bvc2l0aW9uRmVlAB5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXACE2tfcG9zaXRpb25UaW1lc3RhbXAADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUADWtfcm9sbG92ZXJGZWUCDmtfcm9sbG92ZXJfZmVlAA9rX2Z1bmRpbmdQZXJpb2QCD2tfZnVuZGluZ1BlcmlvZAARa19pbml0TWFyZ2luUmF0aW8CEWtfaW5pdE1hcmdpblJhdGlvABhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8CBWtfbW1yABVrX2xpcXVpZGF0aW9uRmVlUmF0aW8CFWtfbGlxdWlkYXRpb25GZWVSYXRpbwAZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwIWa19wYXJ0TGlxdWlkYXRpb25SYXRpbwANa19zcHJlYWRMaW1pdAINa19zcHJlYWRMaW1pdAAQa19tYXhQcmljZUltcGFjdAIQa19tYXhQcmljZUltcGFjdAAQa19tYXhQcmljZVNwcmVhZAIQa19tYXhQcmljZVNwcmVhZAARa19tYXhPcGVuTm90aW9uYWwCEWtfbWF4T3Blbk5vdGlvbmFsABVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQCFWtfZmVlVG9TdGFrZXJzUGVyY2VudAAQa19tYXhPcmFjbGVEZWxheQIQa19tYXhPcmFjbGVEZWxheQANa19mdW5kaW5nTW9kZQINa19mdW5kaW5nTW9kZQAla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIba19sYXRlc3RMb25nUHJlbWl1bUZyYWN0aW9uACZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIca19sYXRlc3RTaG9ydFByZW1pdW1GcmFjdGlvbgASa19uZXh0RnVuZGluZ0Jsb2NrAh5rX25leHRGdW5kaW5nQmxvY2tNaW5UaW1lc3RhbXAAEWtfbG9uZ0Z1bmRpbmdSYXRlAhFrX2xvbmdGdW5kaW5nUmF0ZQASa19zaG9ydEZ1bmRpbmdSYXRlAhJrX3Nob3J0RnVuZGluZ1JhdGUAE2tfcXVvdGVBc3NldFJlc2VydmUCCGtfcXRBc3RSABJrX2Jhc2VBc3NldFJlc2VydmUCCGtfYnNBc3RSABJrX3F1b3RlQXNzZXRXZWlnaHQCCGtfcXRBc3RXABFrX2Jhc2VBc3NldFdlaWdodAIIa19ic0FzdFcAE2tfdG90YWxQb3NpdGlvblNpemUCE2tfdG90YWxQb3NpdGlvblNpemUAF2tfdG90YWxMb25nUG9zaXRpb25TaXplAhdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAYa190b3RhbFNob3J0UG9zaXRpb25TaXplAhhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAE2tfb3BlbkludGVyZXN0U2hvcnQCE2tfb3BlbkludGVyZXN0U2hvcnQAEmtfb3BlbkludGVyZXN0TG9uZwISa19vcGVuSW50ZXJlc3RMb25nAAhrX2xhc3RUeAIIa19sYXN0VHgAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzAA1rX3F1b3RlX2Fzc2V0Ag1rX3F1b3RlX2Fzc2V0ABFrX3N0YWtpbmdfYWRkcmVzcwIRa19zdGFraW5nX2FkZHJlc3MAD2tfbWluZXJfYWRkcmVzcwIPa19taW5lcl9hZGRyZXNzABBrX29yZGVyc19hZGRyZXNzAhBrX29yZGVyc19hZGRyZXNzABJrX3JlZmVycmFsX2FkZHJlc3MCEmtfcmVmZXJyYWxfYWRkcmVzcwAVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhVrX25mdF9tYW5hZ2VyX2FkZHJlc3MBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQxhZG1pbkFkZHJlc3MACQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwEKcXVvdGVBc3NldAAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUNa19xdW90ZV9hc3NldAEOc3Rha2luZ0FkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAURa19zdGFraW5nX2FkZHJlc3MCD1N0YWtpbmcgbm90IHNldAEMdmF1bHRBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfdmF1bHRfYWRkcmVzcwINVmF1bHQgbm90IHNldAEMbWluZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFD2tfbWluZXJfYWRkcmVzcwINTWluZXIgbm90IHNldAENb3JkZXJzQWRkcmVzcwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABRBrX29yZGVyc19hZGRyZXNzAg5PcmRlcnMgbm90IHNldAEPcmVmZXJyYWxBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfcmVmZXJyYWxfYWRkcmVzcwIQUmVmZXJyYWwgbm90IHNldAERbmZ0TWFuYWdlckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhNORlQgTWFuYWdlciBub3Qgc2V0AA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgAHU0VDT05EUwDoBwAPREVDSU1BTF9OVU1CRVJTAAYADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAA9NSU5VVEVTX0lOX1lFQVIJAGgCAKCKIAUMREVDSU1BTF9VTklUAAdPTkVfREFZCQBoAgCAowUFDERFQ0lNQUxfVU5JVAAPUE5MX09QVElPTl9TUE9UAAEAEVBOTF9PUFRJT05fT1JBQ0xFAAIAEkZVTkRJTkdfQVNZTU1FVFJJQwABABFGVU5ESU5HX1NZTU1FVFJJQwACAQFzAQJfeAkArAICCQCkAwEFAl94AgEsAQRkaXZkAgJfeAJfeQkAbgQFAl94BQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEEbXVsZAICX3gCX3kJAG4EBQJfeAUCX3kFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BBWJkaXZkAgJfeAJfeQkAvQIEBQJfeAkAtgIBBQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEFYm11bGQCAl94Al95CQC9AgQFAl94BQJfeQkAtgIBBQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQNhYnMBAl94AwkAZgIFAl94AAAFAl94CQEBLQEFAl94AQR2bWF4AgJfeAJfeQMJAGcCBQJfeAUCX3kFAl94BQJfeQEDaW50AQFrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUEdGhpcwUBawkArAICAg1ubyB2YWx1ZSBmb3IgBQFrAQVpbnRPcgIBawNkZWYJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBawUDZGVmAQRzdHJBAghfYWRkcmVzcwRfa2V5BAN2YWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQhfYWRkcmVzcwUEX2tleQkArAICAhFObyB2YWx1ZSBmb3Iga2V5IAUEX2tleQUDdmFsAQRpbnRBAghfYWRkcmVzcwRfa2V5BAN2YWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQhfYWRkcmVzcwUEX2tleQkArAICAhFObyB2YWx1ZSBmb3Iga2V5IAUEX2tleQUDdmFsAQhjYmFsYW5jZQAJAQNpbnQBBQlrX2JhbGFuY2UBA2ZlZQAJAQNpbnQBBQVrX2ZlZQEPcm9sbG92ZXJGZWVSYXRlAAkBA2ludAEFDWtfcm9sbG92ZXJGZWUBD2luaXRNYXJnaW5SYXRpbwAJAQNpbnQBBRFrX2luaXRNYXJnaW5SYXRpbwEGcXRBc3RSAAkBA2ludAEFE2tfcXVvdGVBc3NldFJlc2VydmUBBmJzQXN0UgAJAQNpbnQBBRJrX2Jhc2VBc3NldFJlc2VydmUBBnF0QXN0VwAJAQVpbnRPcgIFEmtfcXVvdGVBc3NldFdlaWdodAUMREVDSU1BTF9VTklUAQZic0FzdFcACQEFaW50T3ICBRFrX2Jhc2VBc3NldFdlaWdodAUMREVDSU1BTF9VTklUARF0b3RhbFBvc2l0aW9uU2l6ZQAJAQNpbnQBBRNrX3RvdGFsUG9zaXRpb25TaXplARRvcGVuSW50ZXJlc3ROb3Rpb25hbAAJAQNpbnQBBRZrX29wZW5JbnRlcmVzdE5vdGlvbmFsARFvcGVuSW50ZXJlc3RTaG9ydAAJAQNpbnQBBRNrX29wZW5JbnRlcmVzdFNob3J0ARBvcGVuSW50ZXJlc3RMb25nAAkBA2ludAEFEmtfb3BlbkludGVyZXN0TG9uZwEZbmV4dEZ1bmRpbmdCbG9ja1RpbWVzdGFtcAAJAQNpbnQBBRJrX25leHRGdW5kaW5nQmxvY2sBEGZ1bmRpbmdQZXJpb2RSYXcACQEDaW50AQUPa19mdW5kaW5nUGVyaW9kARRmdW5kaW5nUGVyaW9kRGVjaW1hbAAJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwAFDERFQ0lNQUxfVU5JVAEUZnVuZGluZ1BlcmlvZFNlY29uZHMACQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcABQdTRUNPTkRTARZtYWludGVuYW5jZU1hcmdpblJhdGlvAAkBA2ludAEFGGtfbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwETbGlxdWlkYXRpb25GZWVSYXRpbwAJAQNpbnQBBRVrX2xpcXVpZGF0aW9uRmVlUmF0aW8BF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAkBA2ludAEFGWtfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8BC3NwcmVhZExpbWl0AAkBA2ludAEFDWtfc3ByZWFkTGltaXQBDm1heFByaWNlSW1wYWN0AAkBA2ludAEFEGtfbWF4UHJpY2VJbXBhY3QBDm1heFByaWNlU3ByZWFkAAkBA2ludAEFEGtfbWF4UHJpY2VTcHJlYWQBD21heE9wZW5Ob3Rpb25hbAAJAQNpbnQBBRFrX21heE9wZW5Ob3Rpb25hbAEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEDaW50AQUla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAkBA2ludAEFJmtfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkBA2ludAEFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQEVdG90YWxMb25nUG9zaXRpb25TaXplAAkBA2ludAEFF2tfdG90YWxMb25nUG9zaXRpb25TaXplAQxsYXN0U2VxdWVuY2UACQEFaW50T3ICBQprX3NlcXVlbmNlAAABE2ZlZVRvU3Rha2Vyc1BlcmNlbnQACQEDaW50AQUVa19mZWVUb1N0YWtlcnNQZXJjZW50AQ5tYXhPcmFjbGVEZWxheQAJAQNpbnQBBRBrX21heE9yYWNsZURlbGF5AQtmdW5kaW5nTW9kZQAJAQVpbnRPcgIFDWtfZnVuZGluZ01vZGUFEkZVTkRJTkdfQVNZTU1FVFJJQwENbGFzdFRpbWVzdGFtcAAIBQlsYXN0QmxvY2sJdGltZXN0YW1wAQ9nZXRBY3R1YWxDYWxsZXIBAWkJAQt2YWx1ZU9yRWxzZQIJAJ0IAgkBDW9yZGVyc0FkZHJlc3MAAghrX3NlbmRlcgkApQgBCAUBaQZjYWxsZXIBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DDF9tYXJnaW5SYXRpbxBfYmFzZU1hcmdpblJhdGlvFF9sYXJnZXJUaGFuT3JFcXVhbFRvBBRyZW1haW5pbmdNYXJnaW5SYXRpbwkAZQIFDF9tYXJnaW5SYXRpbwUQX2Jhc2VNYXJnaW5SYXRpbwMDBRRfbGFyZ2VyVGhhbk9yRXF1YWxUbwkAZgIAAAUUcmVtYWluaW5nTWFyZ2luUmF0aW8HCQACAQkArAICCQCsAgIJAKwCAgIQSW52YWxpZCBtYXJnaW46IAkApAMBBQxfbWFyZ2luUmF0aW8CAyA8IAkApAMBBRBfYmFzZU1hcmdpblJhdGlvAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwkAAgEJAKwCAgkArAICCQCsAgICEEludmFsaWQgbWFyZ2luOiAJAKQDAQUMX21hcmdpblJhdGlvAgMgPiAJAKQDAQUQX2Jhc2VNYXJnaW5SYXRpbwYBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BDV9wb3NpdGlvblNpemUDCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIsU2hvdWxkIG5vdCBiZSBjYWxsZWQgd2l0aCBfcG9zaXRpb25TaXplID09IDADCQBmAgUNX3Bvc2l0aW9uU2l6ZQAACQEjbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24ACQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAELZ2V0UG9zaXRpb24CB190cmFkZXIKX2RpcmVjdGlvbgQLcG9zaXRpb25LZXkJAKwCAgkArAICBQdfdHJhZGVyAgFfCQCkAwEFCl9kaXJlY3Rpb24ED3Bvc2l0aW9uU2l6ZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQULcG9zaXRpb25LZXkEByRtYXRjaDAFD3Bvc2l0aW9uU2l6ZU9wdAMJAAECBQckbWF0Y2gwAgNJbnQEDHBvc2l0aW9uU2l6ZQUHJG1hdGNoMAkAlwoFBQxwb3NpdGlvblNpemUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FC3Bvc2l0aW9uS2V5CQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQtwb3NpdGlvbktleQkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgULcG9zaXRpb25LZXkJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAULcG9zaXRpb25LZXkJAJcKBQAAAAAAAAAAAAABDGdldERpcmVjdGlvbgENX3Bvc2l0aW9uU2l6ZQMJAGYCAAAFDV9wb3NpdGlvblNpemUFCURJUl9TSE9SVAUIRElSX0xPTkcBDmdldFBvc2l0aW9uRmVlAgdfdHJhZGVyCl9kaXJlY3Rpb24EC3Bvc2l0aW9uS2V5CQCsAgIJAKwCAgUHX3RyYWRlcgIBXwkApAMBBQpfZGlyZWN0aW9uBA5wb3NpdGlvbkZlZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQtwb3NpdGlvbktleQQHJG1hdGNoMAUOcG9zaXRpb25GZWVPcHQDCQABAgUHJG1hdGNoMAIDSW50BAtwb3NpdGlvbkZlZQUHJG1hdGNoMAULcG9zaXRpb25GZWUJAQNmZWUAARNyZXF1aXJlT3BlblBvc2l0aW9uAgdfdHJhZGVyCl9kaXJlY3Rpb24DCQAAAggJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24CXzEAAAkAAgECEE5vIG9wZW4gcG9zaXRpb24GAQ1nZXRPcmFjbGVEYXRhAQNrZXkEDW9yYWNsZURhdGFTdHIJAJ0IAgUEdGhpcwUDa2V5AwMJAQlpc0RlZmluZWQBBQ1vcmFjbGVEYXRhU3RyCQECIT0CCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyAgAHBApvcmFjbGVEYXRhCQC1CQIJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHICASwEDW9yYWNsZUFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCm9yYWNsZURhdGEAAAkArAICAhtJbnZhbGlkIG9yYWNsZSBhZGRyZXNzIGluOiAJAQV2YWx1ZQEFDW9yYWNsZURhdGFTdHIECHByaWNlS2V5CQCRAwIFCm9yYWNsZURhdGEAAQQIYmxvY2tLZXkJAJEDAgUKb3JhY2xlRGF0YQACBAdvcGVuS2V5CQCRAwIFCm9yYWNsZURhdGEAAwkAlgoEBQ1vcmFjbGVBZGRyZXNzBQhwcmljZUtleQUIYmxvY2tLZXkFB29wZW5LZXkFBHVuaXQBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEGcGF1c2VkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQhrX3BhdXNlZAcBCWNsb3NlT25seQAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwULa19jbG9zZU9ubHkHAQ11cGRhdGVSZXNlcnZlAwZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQQX2Jhc2VBc3NldEFtb3VudAMFBl9pc0FkZAQHbmV3QmFzZQkAZQIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50AwkAZwIAAAUHbmV3QmFzZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBhc3NldCByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDCQBkAgkBBnF0QXN0UgAFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAQIbmV3UXVvdGUJAGUCCQEGcXRBc3RSAAURX3F1b3RlQXNzZXRBbW91bnQDCQBnAgAABQhuZXdRdW90ZQkAAgECKlR4IGxlYWQgdG8gYmFzZSBxdW90ZSByZXNlcnZlIDw9IDAsIHJldmVydAkAlQoDBQhuZXdRdW90ZQkAZAIJAQZic0FzdFIABRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAAUQX2Jhc2VBc3NldEFtb3VudAENY2FsY0ludmFyaWFudAIHX3F0QXN0UgdfYnNBc3RSBAdicXRBc3RSCQC2AgEFB19xdEFzdFIEB2Jic0FzdFIJALYCAQUHX2JzQXN0UgkBBWJtdWxkAgUHYnF0QXN0UgUHYmJzQXN0UgEJc3dhcElucHV0AgZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQHX3F0QXN0VwkBBnF0QXN0VwAEB19ic0FzdFcJAQZic0FzdFcABBhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFB19xdEFzdFcEAWsJAQ1jYWxjSW52YXJpYW50AgUHX3F0QXN0UgUHX2JzQXN0UgQWcXVvdGVBc3NldFJlc2VydmVBZnRlcgMFBl9pc0FkZAkAZAIFB19xdEFzdFIFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkAZQIFB19xdEFzdFIFGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCQCgAwEJAQViZGl2ZAIFAWsJALYCAQUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgQYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzCQEDYWJzAQkAZQIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUHX2JzQXN0UgQVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AwUGX2lzQWRkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQEtAQUYYW1vdW50QmFzZUFzc2V0Qm91Z2h0QWJzBA0kdDAxNTU4NjE1NzU2CQENdXBkYXRlUmVzZXJ2ZQMFBl9pc0FkZAUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUNJHQwMTU1ODYxNTc1NgJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE1NTg2MTU3NTYCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUNJHQwMTU1ODYxNTc1NgJfMwQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC21hcmtldFByaWNlCQEEZGl2ZAIFEV9xdW90ZUFzc2V0QW1vdW50BRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMECXByaWNlRGlmZgkBA2FicwEJAGUCBQtwcmljZUJlZm9yZQULbWFya2V0UHJpY2UEC3ByaWNlSW1wYWN0CQBlAgUMREVDSU1BTF9VTklUCQEEZGl2ZAIFC3ByaWNlQmVmb3JlCQBkAgULcHJpY2VCZWZvcmUFCXByaWNlRGlmZgQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAMJAGYCBQtwcmljZUltcGFjdAUTbWF4UHJpY2VJbXBhY3RWYWx1ZQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINUHJpY2UgaW1wYWN0IAkApAMBBQtwcmljZUltcGFjdAIUID4gbWF4IHByaWNlIGltcGFjdCAJAKQDAQUTbWF4UHJpY2VJbXBhY3RWYWx1ZQIVIGJlZm9yZSBxdW90ZSBhc3NldDogCQCkAwEFB19xdEFzdFICFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFB19ic0FzdFICISBxdW90ZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRFfcXVvdGVBc3NldEFtb3VudAIPIHByaWNlIGJlZm9yZTogCQCkAwEFC3ByaWNlQmVmb3JlAg4gbWFya2V0UHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAlgoEBRVhbW91bnRCYXNlQXNzZXRCb3VnaHQFF3F1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIxBRZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxBRd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQEPY2FsY1JvbGxvdmVyRmVlAhJfb2xkUG9zaXRpb25NYXJnaW4gX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAED3Bvc2l0aW9uTWludXRlcwkAaAIJAGkCCQBpAgkAZQIJAQ1sYXN0VGltZXN0YW1wAAUgX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAA6AcAPAUMREVDSU1BTF9VTklUBAtyb2xsb3ZlckZlZQkBBGRpdmQCCQEEbXVsZAIJAQRtdWxkAgUSX29sZFBvc2l0aW9uTWFyZ2luBQ9wb3NpdGlvbk1pbnV0ZXMJAQ9yb2xsb3ZlckZlZVJhdGUABQ9NSU5VVEVTX0lOX1lFQVIFC3JvbGxvdmVyRmVlATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFEF9vbGRQb3NpdGlvblNpemUSX29sZFBvc2l0aW9uTWFyZ2luJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24gX29sZFBvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAMX21hcmdpbkRlbHRhBA5mdW5kaW5nUGF5bWVudAMJAQIhPQIFEF9vbGRQb3NpdGlvblNpemUAAAQgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUQX29sZFBvc2l0aW9uU2l6ZQkBBG11bGQCCQBlAgUgX2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9vbGRQb3NpdGlvbkN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FEF9vbGRQb3NpdGlvblNpemUAAAQLcm9sbG92ZXJGZWUJAQ9jYWxjUm9sbG92ZXJGZWUCBRJfb2xkUG9zaXRpb25NYXJnaW4FIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBAxzaWduZWRNYXJnaW4JAGQCCQBlAgkAZQIFDF9tYXJnaW5EZWx0YQULcm9sbG92ZXJGZWUFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EDSR0MDE4NDIzMTg1NTADCQBmAgAABQxzaWduZWRNYXJnaW4JAJQKAgAACQEDYWJzAQUMc2lnbmVkTWFyZ2luCQCUCgIJAQNhYnMBBQxzaWduZWRNYXJnaW4AAAQMcmVtYWluTWFyZ2luCAUNJHQwMTg0MjMxODU1MAJfMQQHYmFkRGVidAgFDSR0MDE4NDIzMTg1NTACXzIJAJYKBAUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAULcm9sbG92ZXJGZWUBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0El9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0BAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQDCQAAAgUQX2Jhc2VBc3NldEFtb3VudAAACQACAQIZSW52YWxpZCBiYXNlIGFzc2V0IGFtb3VudAQBawkBDWNhbGNJbnZhcmlhbnQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBBhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIDBQZfaXNBZGQJAGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAkAZQIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0QW1vdW50BA9xdW90ZUFzc2V0QWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRhiYXNlQXNzZXRQb29sQW1vdW50QWZ0ZXIED3F1b3RlQXNzZXREZWx0YQkBA2FicwEJAGUCBQ9xdW90ZUFzc2V0QWZ0ZXIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQQOcXVvdGVBc3NldFNvbGQJAQRtdWxkAgUPcXVvdGVBc3NldERlbHRhBRFfcXVvdGVBc3NldFdlaWdodAQTbWF4UHJpY2VJbXBhY3RWYWx1ZQkBDm1heFByaWNlSW1wYWN0AAQNJHQwMTk4MTIxOTk3NAkBDXVwZGF0ZVJlc2VydmUDCQEBIQEFBl9pc0FkZAUPcXVvdGVBc3NldERlbHRhBRBfYmFzZUFzc2V0QW1vdW50BBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFDSR0MDE5ODEyMTk5NzQCXzEEFmJhc2VBc3NldFJlc2VydmVBZnRlcjEIBQ0kdDAxOTgxMjE5OTc0Al8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFDSR0MDE5ODEyMTk5NzQCXzMEC21hcmtldFByaWNlCQEEZGl2ZAIFDnF1b3RlQXNzZXRTb2xkBRBfYmFzZUFzc2V0QW1vdW50BAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYDAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlBRRfY2hlY2tNYXhQcmljZUltcGFjdAcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBRJfcXVvdGVBc3NldFJlc2VydmUCFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFEV9iYXNlQXNzZXRSZXNlcnZlAiAgYmFzZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRBfYmFzZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDyBtYXJrZXQgcHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAmQoHBQ5xdW90ZUFzc2V0U29sZAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQADBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAULcHJpY2VJbXBhY3QBCnN3YXBPdXRwdXQDBl9pc0FkZBBfYmFzZUFzc2V0QW1vdW50FF9jaGVja01heFByaWNlSW1wYWN0CQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwcFBl9pc0FkZAUQX2Jhc2VBc3NldEFtb3VudAUUX2NoZWNrTWF4UHJpY2VJbXBhY3QJAQZxdEFzdFIACQEGcXRBc3RXAAkBBmJzQXN0UgAJAQZic0FzdFcAARNnZXRPcmFjbGVQcmljZVZhbHVlAwZvcmFjbGUIcHJpY2VLZXkIYmxvY2tLZXkECWxhc3RWYWx1ZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBm9yYWNsZQUIcHJpY2VLZXkJAKwCAgkArAICCQCsAgICIkNhbiBub3QgZ2V0IG9yYWNsZSBwcmljZS4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFCHByaWNlS2V5AwkBAiE9AgUIYmxvY2tLZXkCAAQMY3VycmVudEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAQPbGFzdE9yYWNsZUJsb2NrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGb3JhY2xlBQhibG9ja0tleQkArAICCQCsAgIJAKwCAgIiQ2FuIG5vdCBnZXQgb3JhY2xlIGJsb2NrLiBPcmFjbGU6IAkApQgBBQZvcmFjbGUCBiBrZXk6IAUIYmxvY2tLZXkDCQBmAgkAZQIFDGN1cnJlbnRCbG9jawUPbGFzdE9yYWNsZUJsb2NrCQEObWF4T3JhY2xlRGVsYXkACQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmdldE9yYWNsZVByaWNlAAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQEFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQPYmFzZU9yYWNsZVByaWNlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQMIBQpiYXNlT3JhY2xlAl8xCAUKYmFzZU9yYWNsZQJfMggFCmJhc2VPcmFjbGUCXzMEC3F1b3RlT3JhY2xlCQENZ2V0T3JhY2xlRGF0YQEFDWtfcXVvdGVPcmFjbGUEEHF1b3RlT3JhY2xlUHJpY2UDCQEJaXNEZWZpbmVkAQULcXVvdGVPcmFjbGUEDHF1b3RlT3JhY2xlVgkBBXZhbHVlAQULcXVvdGVPcmFjbGUJARNnZXRPcmFjbGVQcmljZVZhbHVlAwgFDHF1b3RlT3JhY2xlVgJfMQgFDHF1b3RlT3JhY2xlVgJfMggFDHF1b3RlT3JhY2xlVgJfMwUMREVDSU1BTF9VTklUCQEEZGl2ZAIFD2Jhc2VPcmFjbGVQcmljZQUQcXVvdGVPcmFjbGVQcmljZQEOaXNNYXJrZXRDbG9zZWQABApiYXNlT3JhY2xlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQ1nZXRPcmFjbGVEYXRhAQUMa19iYXNlT3JhY2xlAhlObyBiYXNlIGFzc2V0IG9yYWNsZSBkYXRhBAZvcmFjbGUIBQpiYXNlT3JhY2xlAl8xBAdvcGVuS2V5CAUKYmFzZU9yYWNsZQJfNAMJAQIhPQIFB29wZW5LZXkCAAQGaXNPcGVuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJsIAgUGb3JhY2xlBQdvcGVuS2V5CQCsAgIJAKwCAgkArAICAitDYW4gbm90IGdldCBvcmFjbGUgaXMgb3Blbi9jbG9zZWQuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQdvcGVuS2V5CQEBIQEFBmlzT3BlbgcBDGFic1ByaWNlRGlmZgUMX29yYWNsZVByaWNlEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQdfcXRBc3RXB19ic0FzdFcECnByaWNlQWZ0ZXIJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcEDGF2ZXJhZ2VQcmljZQkBBGRpdmQCCQBkAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgUMYXZlcmFnZVByaWNlBQxhYnNQcmljZURpZmYBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQCEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQQLb3JhY2xlUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQSYWJzUHJpY2VEaWZmQmVmb3JlCQEMYWJzUHJpY2VEaWZmBQULb3JhY2xlUHJpY2UJAQZxdEFzdFIACQEGYnNBc3RSAAUHX3F0QXN0VwUHX2JzQXN0VwQRYWJzUHJpY2VEaWZmQWZ0ZXIJAQxhYnNQcmljZURpZmYFBQtvcmFjbGVQcmljZQUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwUHX2JzQXN0VwMDCQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIJAQ5tYXhQcmljZVNwcmVhZAAJAGYCBRFhYnNQcmljZURpZmZBZnRlcgUSYWJzUHJpY2VEaWZmQmVmb3JlBwkAAgEJAKwCAgkArAICCQCsAgICDVByaWNlIHNwcmVhZCAJAKQDAQURYWJzUHJpY2VEaWZmQWZ0ZXICFCA+IG1heCBwcmljZSBzcHJlYWQgCQCkAwEJAQ5tYXhQcmljZVNwcmVhZAAGAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAIRX2xvbmdPcGVuTm90aW9uYWwSX3Nob3J0T3Blbk5vdGlvbmFsBBBfbWF4T3Blbk5vdGlvbmFsCQEPbWF4T3Blbk5vdGlvbmFsAAMJAGYCBRFfbG9uZ09wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICE0xvbmcgb3BlbiBub3Rpb25hbCAJAKQDAQURX2xvbmdPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsAwkAZgIFEl9zaG9ydE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICFFNob3J0IG9wZW4gbm90aW9uYWwgCQCkAwEFEl9zaG9ydE9wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwGAQxnZXRTcG90UHJpY2UABBJfcXVvdGVBc3NldFJlc2VydmUJAQZxdEFzdFIABBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEC29yYWNsZVByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABAxjdXJyZW50UHJpY2UJAQxnZXRTcG90UHJpY2UACQBmAgkBBGRpdmQCCQEDYWJzAQkAZQIFC29yYWNsZVByaWNlBQxjdXJyZW50UHJpY2UFC29yYWNsZVByaWNlCQELc3ByZWFkTGltaXQAAR9nZXRQb3NpdGlvbkFkanVzdGVkT3Blbk5vdGlvbmFsBg1fcG9zaXRpb25TaXplB19vcHRpb24SX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQED3Bvc2l0aW9uU2l6ZUFicwkBA2FicwEFDV9wb3NpdGlvblNpemUEB2lzU2hvcnQJAGYCAAAFDV9wb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwDCQAAAgUHX29wdGlvbgUPUE5MX09QVElPTl9TUE9UBBNvdXRQb3NpdGlvbk5vdGlvbmFsCAkBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMHCQEBIQEFB2lzU2hvcnQFD3Bvc2l0aW9uU2l6ZUFicwcFEl9xdW90ZUFzc2V0UmVzZXJ2ZQURX3F1b3RlQXNzZXRXZWlnaHQFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0Al8xBRNvdXRQb3NpdGlvbk5vdGlvbmFsCQEEbXVsZAIFD3Bvc2l0aW9uU2l6ZUFicwkBDmdldE9yYWNsZVByaWNlAAUQcG9zaXRpb25Ob3Rpb25hbAErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwcNX3Bvc2l0aW9uU2l6ZRVfcG9zaXRpb25PcGVuTm90aW9uYWwSX3F1b3RlQXNzZXRSZXNlcnZlEV9xdW90ZUFzc2V0V2VpZ2h0EV9iYXNlQXNzZXRSZXNlcnZlEF9iYXNlQXNzZXRXZWlnaHQHX29wdGlvbgMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAhVJbnZhbGlkIHBvc2l0aW9uIHNpemUEB2lzU2hvcnQJAGYCAAAFDV9wb3NpdGlvblNpemUEEHBvc2l0aW9uTm90aW9uYWwJAR9nZXRQb3NpdGlvbkFkanVzdGVkT3Blbk5vdGlvbmFsBgUNX3Bvc2l0aW9uU2l6ZQUHX29wdGlvbgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEDXVucmVhbGl6ZWRQbmwDBQdpc1Nob3J0CQBlAgUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBRBwb3NpdGlvbk5vdGlvbmFsCQBlAgUQcG9zaXRpb25Ob3Rpb25hbAUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsCQCUCgIFEHBvc2l0aW9uTm90aW9uYWwFDXVucmVhbGl6ZWRQbmwBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAwdfdHJhZGVyCl9kaXJlY3Rpb24HX29wdGlvbgQNJHQwMjc4NjkyODAwOQkBC2dldFBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgQMcG9zaXRpb25TaXplCAUNJHQwMjc4NjkyODAwOQJfMQQOcG9zaXRpb25NYXJnaW4IBQ0kdDAyNzg2OTI4MDA5Al8yBBRwb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDI3ODY5MjgwMDkCXzMEEXBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwMjc4NjkyODAwOQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMHBQxwb3NpdGlvblNpemUFFHBvc2l0aW9uT3Blbk5vdGlvbmFsCQEGcXRBc3RSAAkBBnF0QXN0VwAJAQZic0FzdFIACQEGYnNBc3RXAAUHX29wdGlvbgEPY2FsY01hcmdpblJhdGlvAw1fcmVtYWluTWFyZ2luCF9iYWREZWJ0EV9wb3NpdGlvbk5vdGlvbmFsCQEEZGl2ZAIJAGUCBQ1fcmVtYWluTWFyZ2luBQhfYmFkRGVidAURX3Bvc2l0aW9uTm90aW9uYWwBFmdldE1hcmdpblJhdGlvQnlPcHRpb24DB190cmFkZXIKX2RpcmVjdGlvbgdfb3B0aW9uBA0kdDAyODU0MTI4Njk0CQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBAxwb3NpdGlvblNpemUIBQ0kdDAyODU0MTI4Njk0Al8xBA5wb3NpdGlvbk1hcmdpbggFDSR0MDI4NTQxMjg2OTQCXzIEA3BvbggFDSR0MDI4NTQxMjg2OTQCXzMEFnBvc2l0aW9uTGFzdFVwZGF0ZWRDUEYIBQ0kdDAyODU0MTI4Njk0Al80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDI4NTQxMjg2OTQCXzUEDSR0MDI4NzAwMjg4MDUJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAMFB190cmFkZXIFCl9kaXJlY3Rpb24FB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQ0kdDAyODcwMDI4ODA1Al8xBA11bnJlYWxpemVkUG5sCAUNJHQwMjg3MDAyODgwNQJfMgQNJHQwMjg4MTAyOTAyMgkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQUFDHBvc2l0aW9uU2l6ZQUOcG9zaXRpb25NYXJnaW4FFnBvc2l0aW9uTGFzdFVwZGF0ZWRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDAyODgxMDI5MDIyAl8xBAdiYWREZWJ0CAUNJHQwMjg4MTAyOTAyMgJfMgkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUQcG9zaXRpb25Ob3Rpb25hbAEOZ2V0TWFyZ2luUmF0aW8CB190cmFkZXIKX2RpcmVjdGlvbgkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24DBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQ9QTkxfT1BUSU9OX1NQT1QBG2dldFBhcnRpYWxMaXF1aWRhdGlvbkFtb3VudAIHX3RyYWRlcg1fcG9zaXRpb25TaXplBAxtYXhpbXVtUmF0aW8JAQR2bWF4AgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCCQEOZ2V0TWFyZ2luUmF0aW8CBQdfdHJhZGVyCQEMZ2V0RGlyZWN0aW9uAQUNX3Bvc2l0aW9uU2l6ZQkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABBhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUJAQRtdWxkAgkBA2FicwEFDV9wb3NpdGlvblNpemUFDG1heGltdW1SYXRpbwQKc3dhcFJlc3VsdAkBCnN3YXBPdXRwdXQDCQBmAgUNX3Bvc2l0aW9uU2l6ZQAABRhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUHBBxtYXhFeGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50CAUKc3dhcFJlc3VsdAJfMQQLcHJpY2VJbXBhY3QIBQpzd2FwUmVzdWx0Al83AwkAZgIJAQ5tYXhQcmljZUltcGFjdAAFC3ByaWNlSW1wYWN0BRhtYXhFeGNoYW5nZWRQb3NpdGlvblNpemUJAQRtdWxkAgkBA2FicwEFDV9wb3NpdGlvblNpemUJARdwYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwABFWludGVybmFsQ2xvc2VQb3NpdGlvbggHX3RyYWRlcgpfZGlyZWN0aW9uBV9zaXplBF9mZWUUX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luFF9jaGVja01heFByaWNlSW1wYWN0Cl9saXF1aWRhdGUEDSR0MDMwMTg1MzAzNTMJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24ED29sZFBvc2l0aW9uU2l6ZQgFDSR0MDMwMTg1MzAzNTMCXzEEEW9sZFBvc2l0aW9uTWFyZ2luCAUNJHQwMzAxODUzMDM1MwJfMgQXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDAzMDE4NTMwMzUzAl8zBBRvbGRQb3NpdGlvbkxzdFVwZENQRggFDSR0MDMwMTg1MzAzNTMCXzQEFG9sZFBvc2l0aW9uVGltZXN0YW1wCAUNJHQwMzAxODUzMDM1MwJfNQQOaXNMb25nUG9zaXRpb24JAGYCBQ9vbGRQb3NpdGlvblNpemUAAAQSYWJzT2xkUG9zaXRpb25TaXplCQEDYWJzAQUPb2xkUG9zaXRpb25TaXplAwMJAGcCBRJhYnNPbGRQb3NpdGlvblNpemUFBV9zaXplCQBmAgUFX3NpemUAAAcEDmlzUGFydGlhbENsb3NlCQBmAgUSYWJzT2xkUG9zaXRpb25TaXplBQVfc2l6ZQQNJHQwMzA2NDUzMTA5NgkBCnN3YXBPdXRwdXQDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAFBV9zaXplBRRfY2hlY2tNYXhQcmljZUltcGFjdAQZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAgFDSR0MDMwNjQ1MzEwOTYCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMDY0NTMxMDk2Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDAzMDY0NTMxMDk2Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwMzA2NDUzMTA5NgJfNAQVZXhjaGFuZ2VkUG9zaXRpb25TaXplAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQEBLQEFBV9zaXplBQVfc2l6ZQQNJHQwMzEzMTEzMTUzNQkBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAwUHX3RyYWRlcgUKX2RpcmVjdGlvbgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwMzEzMTEzMTUzNQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDMxMzExMzE1MzUCXzIEDXJlYWxpemVkUmF0aW8JAQRkaXZkAgkBA2FicwEFFWV4Y2hhbmdlZFBvc2l0aW9uU2l6ZQUSYWJzT2xkUG9zaXRpb25TaXplBAtyZWFsaXplZFBubAkBBG11bGQCBQ11bnJlYWxpemVkUG5sBQ1yZWFsaXplZFJhdGlvBA0kdDAzMTg3NjMyMTIyCQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBBJyZW1haW5NYXJnaW5CZWZvcmUIBQ0kdDAzMTg3NjMyMTIyAl8xBAJ4MQgFDSR0MDMxODc2MzIxMjICXzIEAngyCAUNJHQwMzE4NzYzMjEyMgJfMwQLcm9sbG92ZXJGZWUIBQ0kdDAzMTg3NjMyMTIyAl80BA9wb3NpdGlvbkJhZERlYnQICQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQtyZWFsaXplZFBubAJfMgQQcmVhbGl6ZWRDbG9zZUZlZQkBBG11bGQCCQEEbXVsZAIFE29sZFBvc2l0aW9uTm90aW9uYWwFDXJlYWxpemVkUmF0aW8FBF9mZWUEEnVucmVhbGl6ZWRQbmxBZnRlcgkAZQIFDXVucmVhbGl6ZWRQbmwFC3JlYWxpemVkUG5sBBJyZW1haW5PcGVuTm90aW9uYWwDCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQBlAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkAZAIFEnVucmVhbGl6ZWRQbmxBZnRlcgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAQPbmV3UG9zaXRpb25TaXplCQBkAgUPb2xkUG9zaXRpb25TaXplBRVleGNoYW5nZWRQb3NpdGlvblNpemUEDSR0MDMzNTI4MzM5MTQDCQAAAgUPbmV3UG9zaXRpb25TaXplAAAJAJQKAgAAAAAJAJQKAgkBA2FicwEFEnJlbWFpbk9wZW5Ob3Rpb25hbAkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBQ9uZXdQb3NpdGlvblNpemUEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwMzM1MjgzMzkxNAJfMQQUbmV3UG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDAzMzUyODMzOTE0Al8yBBFvcGVuTm90aW9uYWxEZWx0YQkAZQIFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAQLbWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAwUHX3RyYWRlcgUKX2RpcmVjdGlvbgUPUE5MX09QVElPTl9TUE9UBB5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8DCQBmAgUPb2xkUG9zaXRpb25TaXplAAAJAGUCCQEEbXVsZAIJAGQCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUSdW5yZWFsaXplZFBubEFmdGVyBQttYXJnaW5SYXRpbwUSdW5yZWFsaXplZFBubEFmdGVyCQBlAgkBBG11bGQCCQBlAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFEnVucmVhbGl6ZWRQbmxBZnRlcgULbWFyZ2luUmF0aW8FEnVucmVhbGl6ZWRQbmxBZnRlcgQRbWFyZ2luVG9UcmFkZXJSYXcJAGUCCQBlAgUScmVtYWluTWFyZ2luQmVmb3JlCQBkAgUebmV3UG9zaXRpb25NYXJnaW5XaXRoU2FtZVJhdGlvBRJ1bnJlYWxpemVkUG5sQWZ0ZXIFEHJlYWxpemVkQ2xvc2VGZWUEDm1hcmdpblRvVHJhZGVyAwkAZgIAAAURbWFyZ2luVG9UcmFkZXJSYXcDBQpfbGlxdWlkYXRlAAAJAAIBAjdJbnZhbGlkIGludGVybmFsQ2xvc2VQb3NpdGlvbiBwYXJhbXM6IHVuYWJsZSB0byBwYXkgZmVlBRFtYXJnaW5Ub1RyYWRlclJhdwQRbmV3UG9zaXRpb25NYXJnaW4DBQxfYWRkVG9NYXJnaW4JAGQCBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8FDm1hcmdpblRvVHJhZGVyBR5uZXdQb3NpdGlvbk1hcmdpbldpdGhTYW1lUmF0aW8DAwkBAiE9AgUUX21pblF1b3RlQXNzZXRBbW91bnQAAAkAZgIFFF9taW5RdW90ZUFzc2V0QW1vdW50BRlleGNoYW5nZWRRdW90ZUFzc2V0QW1vdW50BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQUZZXhjaGFuZ2VkUXVvdGVBc3NldEFtb3VudAIDIDwgCQCkAwEFFF9taW5RdW90ZUFzc2V0QW1vdW50CQCjChEFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgUPcG9zaXRpb25CYWREZWJ0BQtyZWFsaXplZFBubAMDBQxfYWRkVG9NYXJnaW4FDmlzUGFydGlhbENsb3NlBwAABQ5tYXJnaW5Ub1RyYWRlcgUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCQBlAgkBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAAURb3Blbk5vdGlvbmFsRGVsdGEJAGUCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMFDmlzTG9uZ1Bvc2l0aW9uCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQADCQEBIQEFDmlzTG9uZ1Bvc2l0aW9uCQEDYWJzAQUVZXhjaGFuZ2VkUG9zaXRpb25TaXplAAAJAGUCCQEQb3BlbkludGVyZXN0TG9uZwADBQ5pc0xvbmdQb3NpdGlvbgURb3Blbk5vdGlvbmFsRGVsdGEAAAkAZQIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQEBIQEFDmlzTG9uZ1Bvc2l0aW9uBRFvcGVuTm90aW9uYWxEZWx0YQAACQBkAgUQcmVhbGl6ZWRDbG9zZUZlZQULcm9sbG92ZXJGZWUFGWV4Y2hhbmdlZFF1b3RlQXNzZXRBbW91bnQJAAIBCQCsAgIJAKwCAgkArAICAj1JbnZhbGlkIGludGVybmFsQ2xvc2VQb3NpdGlvbiBwYXJhbXM6IGludmFsaWQgcG9zaXRpb24gc2l6ZTogCQCkAwEFBV9zaXplAgYgbWF4OiAJAKQDAQUSYWJzT2xkUG9zaXRpb25TaXplARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAJAJQKAgkBBnF0QXN0UgAJAQZic0FzdFIABAlkaXJlY3Rpb24JAGYCBQ1fcG9zaXRpb25TaXplAAAEDSR0MDM3MTYxMzczNDAJAQpzd2FwT3V0cHV0AwUJZGlyZWN0aW9uCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQcEFWN1cnJlbnROZXRNYXJrZXRWYWx1ZQgFDSR0MDM3MTYxMzczNDACXzEEGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUIBQ0kdDAzNzE2MTM3MzQwAl8yBBh0ZXJtaW5hbEJhc2VBc3NldFJlc2VydmUIBQ0kdDAzNzE2MTM3MzQwAl8zCQCUCgIFGXRlcm1pbmFsUXVvdGVBc3NldFJlc2VydmUFGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQETZ2V0UXVvdGVBc3NldFdlaWdodAQQYmFzZUFzc2V0UmVzZXJ2ZRF0b3RhbFBvc2l0aW9uU2l6ZRFxdW90ZUFzc2V0UmVzZXJ2ZQt0YXJnZXRQcmljZQQBYgkAtgIBBRBiYXNlQXNzZXRSZXNlcnZlBAJzegkAtgIBBRF0b3RhbFBvc2l0aW9uU2l6ZQQBcQkAtgIBBRFxdW90ZUFzc2V0UmVzZXJ2ZQQBcAkAtgIBBQt0YXJnZXRQcmljZQQBawkBBWJtdWxkAgUBcQUBYgQEbmV3QgkAtwICBQFiBQJzegQEbmV3UQkBBWJkaXZkAgUBawUEbmV3QgQBegkBBWJkaXZkAgUEbmV3UQUEbmV3QgQGcmVzdWx0CQEFYmRpdmQCBQFwBQF6CQCgAwEFBnJlc3VsdAEUZ2V0U3luY1Rlcm1pbmFsUHJpY2UDDl90ZXJtaW5hbFByaWNlB19xdEFzdFIHX2JzQXN0UgQNX3Bvc2l0aW9uU2l6ZQkBEXRvdGFsUG9zaXRpb25TaXplAAMJAAACBQ1fcG9zaXRpb25TaXplAAAECW5ld1F0QXN0VwkBBGRpdmQCCQEEbXVsZAIFDl90ZXJtaW5hbFByaWNlBQdfYnNBc3RSBQdfcXRBc3RSCQCVCgMFCW5ld1F0QXN0VwUMREVDSU1BTF9VTklUAAAECWRpcmVjdGlvbgkAZgIFDV9wb3NpdGlvblNpemUAAAQVY3VycmVudE5ldE1hcmtldFZhbHVlCAkBCnN3YXBPdXRwdXQDBQlkaXJlY3Rpb24JAQNhYnMBBQ1fcG9zaXRpb25TaXplBwJfMQQJbmV3UXRBc3RXCQETZ2V0UXVvdGVBc3NldFdlaWdodAQFB19ic0FzdFIFDV9wb3NpdGlvblNpemUFB19xdEFzdFIFDl90ZXJtaW5hbFByaWNlBAluZXdCc0FzdFcFDERFQ0lNQUxfVU5JVAQNbWFyZ2luVG9WYXVsdAgJAStnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubEJ5VmFsdWVzBwUNX3Bvc2l0aW9uU2l6ZQUVY3VycmVudE5ldE1hcmtldFZhbHVlBQdfcXRBc3RSBQluZXdRdEFzdFcFB19ic0FzdFIFCW5ld0JzQXN0VwUPUE5MX09QVElPTl9TUE9UAl8yCQCVCgMFCW5ld1F0QXN0VwUJbmV3QnNBc3RXBQ1tYXJnaW5Ub1ZhdWx0AQpnZXRGdW5kaW5nAAQPdW5kZXJseWluZ1ByaWNlCQEOZ2V0T3JhY2xlUHJpY2UABAlzcG90UHJpY2UJAQxnZXRTcG90UHJpY2UABAdwcmVtaXVtCQBlAgUJc3BvdFByaWNlBQ91bmRlcmx5aW5nUHJpY2UDAwMJAAACCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAAAAYJAAACCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAAABgkBDmlzTWFya2V0Q2xvc2VkAAkAlQoDAAAAAAAAAwkAZgIAAAUHcHJlbWl1bQQUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgkBBG11bGQCBQdwcmVtaXVtCQEUZnVuZGluZ1BlcmlvZERlY2ltYWwABQdPTkVfREFZAwkAAAIJAQtmdW5kaW5nTW9kZQAFEkZVTkRJTkdfQVNZTU1FVFJJQwQTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBBGRpdmQCCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAJARV0b3RhbExvbmdQb3NpdGlvblNpemUACQCVCgMFFHNob3J0UHJlbWl1bUZyYWN0aW9uBRNsb25nUHJlbWl1bUZyYWN0aW9uAAAEGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAEGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgkBA2FicwEJAQRtdWxkAgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUABA5wcmVtaXVtVG9WYXVsdAkAZQIFGXNob3J0VG90YWxQcmVtaXVtRnJhY3Rpb24FGGxvbmdUb3RhbFByZW1pdW1GcmFjdGlvbgkAlQoDBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUUc2hvcnRQcmVtaXVtRnJhY3Rpb24FDnByZW1pdW1Ub1ZhdWx0BBNsb25nUHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUHcHJlbWl1bQkBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAAUHT05FX0RBWQMJAAACCQELZnVuZGluZ01vZGUABRJGVU5ESU5HX0FTWU1NRVRSSUMEFHNob3J0UHJlbWl1bUZyYWN0aW9uCQEEZGl2ZAIJAQRtdWxkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAAkAlQoDBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgAABBhsb25nVG90YWxQcmVtaXVtRnJhY3Rpb24JAQNhYnMBCQEEbXVsZAIFE2xvbmdQcmVtaXVtRnJhY3Rpb24JARV0b3RhbExvbmdQb3NpdGlvblNpemUABBlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uCQEDYWJzAQkBBG11bGQCBRNsb25nUHJlbWl1bUZyYWN0aW9uCQEWdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQAEDnByZW1pdW1Ub1ZhdWx0CQBlAgUYbG9uZ1RvdGFsUHJlbWl1bUZyYWN0aW9uBRlzaG9ydFRvdGFsUHJlbWl1bUZyYWN0aW9uCQCVCgMFE2xvbmdQcmVtaXVtRnJhY3Rpb24FE2xvbmdQcmVtaXVtRnJhY3Rpb24FDnByZW1pdW1Ub1ZhdWx0AQ5nZXRBZGp1c3RlZEZlZQILX2FydGlmYWN0SWQQX2Jhc2VGZWVEaXNjb3VudAQKYmFzZUZlZVJhdwkBA2ZlZQAEB2Jhc2VGZWUJAQRtdWxkAgUKYmFzZUZlZVJhdwUQX2Jhc2VGZWVEaXNjb3VudAQNJHQwNDE5MTU0MjQxMAMJAQIhPQIFC19hcnRpZmFjdElkAgAEDGFydGlmYWN0S2luZAkBBHN0ckECCQERbmZ0TWFuYWdlckFkZHJlc3MACQEOdG9Db21wb3NpdGVLZXkCBQxrX3Rva2VuX3R5cGUFC19hcnRpZmFjdElkAwkAAAIFDGFydGlmYWN0S2luZAUYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFBAlyZWR1Y3Rpb24JAQRpbnRBAgkBEW5mdE1hbmFnZXJBZGRyZXNzAAkBDnRvQ29tcG9zaXRlS2V5AgUNa190b2tlbl9wYXJhbQULX2FydGlmYWN0SWQEC2FkanVzdGVkRmVlCQEEbXVsZAIFB2Jhc2VGZWUFCXJlZHVjdGlvbgkAlAoCBQthZGp1c3RlZEZlZQYJAAIBAhlJbnZhbGlkIGF0dGFjaGVkIGFydGlmYWN0CQCUCgIFB2Jhc2VGZWUHBAthZGp1c3RlZEZlZQgFDSR0MDQxOTE1NDI0MTACXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDQxOTE1NDI0MTACXzIJAJQKAgULYWRqdXN0ZWRGZWUFDGJ1cm5BcnRpZmFjdAEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgdfdHJhZGVyC19hcnRpZmFjdElkBBBkb0dldEZlZURpc2NvdW50CQD8BwQJAQxtaW5lckFkZHJlc3MAAhJjb21wdXRlRmVlRGlzY291bnQJAMwIAgUHX3RyYWRlcgUDbmlsBQNuaWwDCQAAAgUQZG9HZXRGZWVEaXNjb3VudAUQZG9HZXRGZWVEaXNjb3VudAQLZmVlRGlzY291bnQEByRtYXRjaDAFEGRvR2V0RmVlRGlzY291bnQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIhSW52YWxpZCBjb21wdXRlRmVlRGlzY291bnQgcmVzdWx0BA0kdDA0Mjc1NjQyODMwCQEOZ2V0QWRqdXN0ZWRGZWUCBQtfYXJ0aWZhY3RJZAULZmVlRGlzY291bnQEC2FkanVzdGVkRmVlCAUNJHQwNDI3NTY0MjgzMAJfMQQMYnVybkFydGlmYWN0CAUNJHQwNDI3NTY0MjgzMAJfMgkAlAoCBQthZGp1c3RlZEZlZQUMYnVybkFydGlmYWN0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1nZXRBcnRpZmFjdElkAQFpBAphcnRpZmFjdElkAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkA2AQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAISSW52YWxpZCBhcnRpZmFjdElkAgAFCmFydGlmYWN0SWQBDWRpc3RyaWJ1dGVGZWUBCl9mZWVBbW91bnQEDGZlZVRvU3Rha2VycwkBBG11bGQCBQpfZmVlQW1vdW50CQETZmVlVG9TdGFrZXJzUGVyY2VudAAECmZlZVRvVmF1bHQJAGUCBQpfZmVlQW1vdW50BQxmZWVUb1N0YWtlcnMJAJQKAgUMZmVlVG9TdGFrZXJzBQpmZWVUb1ZhdWx0AQ51cGRhdGVTZXR0aW5ncw4QX2luaXRNYXJnaW5SYXRpbwRfbW1yFF9saXF1aWRhdGlvbkZlZVJhdGlvDl9mdW5kaW5nUGVyaW9kBF9mZWUMX3NwcmVhZExpbWl0D19tYXhQcmljZUltcGFjdBhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8PX21heFByaWNlU3ByZWFkEF9tYXhPcGVuTm90aW9uYWwUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQPX21heE9yYWNsZURlbGF5DF9yb2xsb3ZlckZlZQxfZnVuZGluZ01vZGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfaW5pdE1hcmdpblJhdGlvBRBfaW5pdE1hcmdpblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8FBF9tbXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwUUX2xpcXVpZGF0aW9uRmVlUmF0aW8JAMwIAgkBDEludGVnZXJFbnRyeQIFD2tfZnVuZGluZ1BlcmlvZAUOX2Z1bmRpbmdQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFBWtfZmVlBQRfZmVlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3NwcmVhZExpbWl0BQxfc3ByZWFkTGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfbWF4UHJpY2VJbXBhY3QFD19tYXhQcmljZUltcGFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heFByaWNlU3ByZWFkBQ9fbWF4UHJpY2VTcHJlYWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbWF4T3Blbk5vdGlvbmFsBRBfbWF4T3Blbk5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFFF9mZWVUb1N0YWtlcnNQZXJjZW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX21heE9yYWNsZURlbGF5BQ9fbWF4T3JhY2xlRGVsYXkJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfcm9sbG92ZXJGZWUFDF9yb2xsb3ZlckZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19mdW5kaW5nTW9kZQUMX2Z1bmRpbmdNb2RlBQNuaWwBDXVwZGF0ZUZ1bmRpbmcFEV9uZXh0RnVuZGluZ0Jsb2NrJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiVfbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sb25nRnVuZGluZ1JhdGURX3Nob3J0RnVuZGluZ1JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfbmV4dEZ1bmRpbmdCbG9jawURX25leHRGdW5kaW5nQmxvY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFJWtfbGF0ZXN0TG9uZ0N1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJF9sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FJV9sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfbG9uZ0Z1bmRpbmdSYXRlBRBfbG9uZ0Z1bmRpbmdSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3Nob3J0RnVuZGluZ1JhdGUFEV9zaG9ydEZ1bmRpbmdSYXRlBQNuaWwBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXIDDl9pc05ld1Bvc2l0aW9uB190cmFkZXIKX2RpcmVjdGlvbgQLcG9zaXRpb25LZXkJAKwCAgkArAICBQdfdHJhZGVyAgFfCQCkAwEFCl9kaXJlY3Rpb24DBQ5faXNOZXdQb3NpdGlvbgQPY3VycmVudFNlcXVlbmNlCQEMbGFzdFNlcXVlbmNlAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUSa19wb3NpdGlvblNlcXVlbmNlBQtwb3NpdGlvbktleQkAZAIFD2N1cnJlbnRTZXF1ZW5jZQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQprX3NlcXVlbmNlCQBkAgUPY3VycmVudFNlcXVlbmNlAAEFA25pbAUDbmlsARF1cGRhdGVQb3NpdGlvbkZlZQQOX2lzTmV3UG9zaXRpb24HX3RyYWRlcgpfZGlyZWN0aW9uBF9mZWUEC3Bvc2l0aW9uS2V5CQCsAgIJAKwCAgUHX3RyYWRlcgIBXwkApAMBBQpfZGlyZWN0aW9uAwUOX2lzTmV3UG9zaXRpb24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFC3Bvc2l0aW9uS2V5BQRfZmVlBQNuaWwFA25pbAEOdXBkYXRlUG9zaXRpb24GB190cmFkZXIFX3NpemUHX21hcmdpbg1fb3Blbk5vdGlvbmFsIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uEF9sYXRlc3RUaW1lc3RhbXAECWRpcmVjdGlvbgkBDGdldERpcmVjdGlvbgEFBV9zaXplBAtwb3NpdGlvbktleQkArAICCQCsAgIFB190cmFkZXICAV8JAKQDAQUJZGlyZWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQULcG9zaXRpb25LZXkFBV9zaXplCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQtwb3NpdGlvbktleQUHX21hcmdpbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUWa19wb3NpdGlvbk9wZW5Ob3Rpb25hbAULcG9zaXRpb25LZXkFDV9vcGVuTm90aW9uYWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FC3Bvc2l0aW9uS2V5BSBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUea19wb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBQtwb3NpdGlvbktleQUQX2xhdGVzdFRpbWVzdGFtcAUDbmlsARF1cGRhdGVBbW1SZXNlcnZlcwIHX3F0QXN0UgdfYnNBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNrX3F1b3RlQXNzZXRSZXNlcnZlBQdfcXRBc3RSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFIFA25pbAEQdXBkYXRlQW1tV2VpZ2h0cwIHX3F0QXN0VwdfYnNBc3RXCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJrX3F1b3RlQXNzZXRXZWlnaHQFB19xdEFzdFcJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtfYmFzZUFzc2V0V2VpZ2h0BQdfYnNBc3RXBQNuaWwBCXVwZGF0ZUFtbQgHX3F0QXN0UgdfYnNBc3RSF190b3RhbFBvc2l0aW9uU2l6ZUFmdGVyFV9vcGVuSW50ZXJlc3ROb3Rpb25hbBZfdG90YWxMb25nUG9zaXRpb25TaXplF190b3RhbFNob3J0UG9zaXRpb25TaXplFl90b3RhbExvbmdPcGVuTm90aW9uYWwXX3RvdGFsU2hvcnRPcGVuTm90aW9uYWwEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAMJAQIhPQIJAGUCBRZfdG90YWxMb25nUG9zaXRpb25TaXplBRdfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIYSW52YWxpZCBBTU0gc3RhdGUgZGF0YTogCQCkAwEFFl90b3RhbExvbmdQb3NpdGlvblNpemUCBCArICAJAKQDAQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUCBCAhPSAJAKQDAQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAM4IAgkBEXVwZGF0ZUFtbVJlc2VydmVzAgUHX3F0QXN0UgUHX2JzQXN0UgkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa190b3RhbFBvc2l0aW9uU2l6ZQUXX3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwFFV9vcGVuSW50ZXJlc3ROb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXa190b3RhbExvbmdQb3NpdGlvblNpemUFFl90b3RhbExvbmdQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFGGtfdG90YWxTaG9ydFBvc2l0aW9uU2l6ZQUXX3RvdGFsU2hvcnRQb3NpdGlvblNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtfb3BlbkludGVyZXN0TG9uZwUWX3RvdGFsTG9uZ09wZW5Ob3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUTa19vcGVuSW50ZXJlc3RTaG9ydAUXX3RvdGFsU2hvcnRPcGVuTm90aW9uYWwFA25pbAEOZGVsZXRlUG9zaXRpb24CB190cmFkZXIKX2RpcmVjdGlvbgQLcG9zaXRpb25LZXkJAKwCAgkArAICBQdfdHJhZGVyAgFfCQCkAwEFCl9kaXJlY3Rpb24JAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUOa19wb3NpdGlvblNpemUFC3Bvc2l0aW9uS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FC3Bvc2l0aW9uS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFC3Bvc2l0aW9uS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFLmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24FC3Bvc2l0aW9uS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFC3Bvc2l0aW9uS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFHmtfcG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAULcG9zaXRpb25LZXkFA25pbAEId2l0aGRyYXcCCF9hZGRyZXNzB19hbW91bnQEB2JhbGFuY2UJAPAHAgUEdGhpcwkBCnF1b3RlQXNzZXQAAwkAZgIFB19hbW91bnQFB2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICAhNVbmFibGUgdG8gd2l0aGRyYXcgCQCkAwEFB19hbW91bnQCFyBmcm9tIGNvbnRyYWN0IGJhbGFuY2UgCQCkAwEFB2JhbGFuY2UJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUIX2FkZHJlc3MFB19hbW91bnQJAQpxdW90ZUFzc2V0AAUDbmlsAQ11cGRhdGVCYWxhbmNlAQFpAwkAZgIAAAUBaQkAAgECB0JhbGFuY2UJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtfYmFsYW5jZQUBaQUDbmlsAQt0cmFuc2ZlckZlZQEBaQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEOc3Rha2luZ0FkZHJlc3MABQFpCQEKcXVvdGVBc3NldAAFA25pbAEOZG9CdXJuQXJ0aWZhY3QCDV9idXJuQXJ0aWZhY3QBaQMFDV9idXJuQXJ0aWZhY3QJAMwIAgkBBEJ1cm4CCQETdmFsdWVPckVycm9yTWVzc2FnZQIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAIQSW52YWxpZCBhcnRpZmFjdAABBQNuaWwFA25pbBcBaQEFcGF1c2UAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECFEludmFsaWQgcGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAYFA25pbAFpAQd1bnBhdXNlAAMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIHVucGF1c2UgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQhrX3BhdXNlZAcFA25pbAFpAQxzZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECG0ludmFsaWQgc2V0Q2xvc2VPbmx5IHBhcmFtcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgULa19jbG9zZU9ubHkGBQNuaWwBaQEOdW5zZXRDbG9zZU9ubHkAAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgdW5zZXRDbG9zZU9ubHkgcGFyYW1zCQDMCAIJAQxCb29sZWFuRW50cnkCBQtrX2Nsb3NlT25seQcFA25pbAFpAQxhZGRMaXF1aWRpdHkBEV9xdW90ZUFzc2V0QW1vdW50AwMJAQIhPQIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAGCQBnAgAABRFfcXVvdGVBc3NldEFtb3VudAkAAgECG0ludmFsaWQgYWRkTGlxdWlkaXR5IHBhcmFtcwQHX3F0QXN0UgkBBnF0QXN0UgAEB19ic0FzdFIJAQZic0FzdFIABAdfcXRBc3RXCQEGcXRBc3RXAAQHX2JzQXN0VwkBBmJzQXN0VwAEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUHX3F0QXN0UgUHX3F0QXN0VwkBBG11bGQCBQdfYnNBc3RSBQdfYnNBc3RXBAtxdEFzdFJBZnRlcgkAZAIFB19xdEFzdFIFEV9xdW90ZUFzc2V0QW1vdW50BBRiYXNlQXNzZXRBbW91bnRUb0FkZAkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBkAgUHX2JzQXN0UgUUYmFzZUFzc2V0QW1vdW50VG9BZGQEDSR0MDUxMDgwNTEyMzEJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDUxMDgwNTEyMzECXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDUxMDgwNTEyMzECXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA1MTA4MDUxMjMxAl8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD3JlbW92ZUxpcXVpZGl0eQERX3F1b3RlQXNzZXRBbW91bnQDAwkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAGcCBRFfcXVvdGVBc3NldEFtb3VudAAACQACAQIeSW52YWxpZCByZW1vdmVMaXF1aWRpdHkgcGFyYW1zBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEB19xdEFzdFcJAQZxdEFzdFcABAdfYnNBc3RXCQEGYnNBc3RXAAQFcHJpY2UJAQRkaXZkAgkBBG11bGQCBQdfcXRBc3RSBQdfcXRBc3RXCQEEbXVsZAIFB19ic0FzdFIFB19ic0FzdFcEC3F0QXN0UkFmdGVyCQBlAgUHX3F0QXN0UgURX3F1b3RlQXNzZXRBbW91bnQEF2Jhc2VBc3NldEFtb3VudFRvUmVtb3ZlCQEDYWJzAQkAZQIJAQRkaXZkAgkBBG11bGQCBQtxdEFzdFJBZnRlcgUHX3F0QXN0VwUFcHJpY2UFB19ic0FzdFIEC2JzQXN0UkFmdGVyCQBlAgUHX2JzQXN0UgUXYmFzZUFzc2V0QW1vdW50VG9SZW1vdmUEDSR0MDUyMzI3NTI0NzgJARRnZXRTeW5jVGVybWluYWxQcmljZQMJAQ5nZXRPcmFjbGVQcmljZQAFC3F0QXN0UkFmdGVyBQtic0FzdFJBZnRlcgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDUyMzI3NTI0NzgCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDUyMzI3NTI0NzgCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA1MjMyNzUyNDc4Al8zBA1kb0V4Y2hhbmdlUG5MAwkBAiE9AgUNbWFyZ2luVG9WYXVsdAAABA1kb0V4Y2hhbmdlUG5MCQD8BwQJAQx2YXVsdEFkZHJlc3MAAhVleGNoYW5nZUZyZWVBbmRMb2NrZWQJAMwIAgUNbWFyZ2luVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUNZG9FeGNoYW5nZVBuTAUNZG9FeGNoYW5nZVBuTAkAzggCCQERdXBkYXRlQW1tUmVzZXJ2ZXMCBQtxdEFzdFJBZnRlcgULYnNBc3RSQWZ0ZXIJARB1cGRhdGVBbW1XZWlnaHRzAgUTbmV3UXVvdGVBc3NldFdlaWdodAUSbmV3QmFzZUFzc2V0V2VpZ2h0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmNoYW5nZVNldHRpbmdzDhBfaW5pdE1hcmdpblJhdGlvBF9tbXIUX2xpcXVpZGF0aW9uRmVlUmF0aW8OX2Z1bmRpbmdQZXJpb2QEX2ZlZQxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQMDAwMDAwMDAwMDAwMDAwMDCQBnAgAABQ5fZnVuZGluZ1BlcmlvZAYJAGcCAAAFEF9pbml0TWFyZ2luUmF0aW8GCQBnAgAABQRfbW1yBgkAZwIAAAUUX2xpcXVpZGF0aW9uRmVlUmF0aW8GCQBnAgAABQRfZmVlBgkAZwIAAAUMX3NwcmVhZExpbWl0BgkAZwIAAAUPX21heFByaWNlSW1wYWN0BgkAZwIAAAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBgkAZwIAAAUPX21heFByaWNlU3ByZWFkBgkAZwIAAAUQX21heE9wZW5Ob3Rpb25hbAYJAGcCAAAFFF9mZWVUb1N0YWtlcnNQZXJjZW50BgkAZgIFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQxERUNJTUFMX1VOSVQGCQBnAgAABQ9fbWF4T3JhY2xlRGVsYXkGCQBnAgAABQxfcm9sbG92ZXJGZWUGAwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRFGVU5ESU5HX1NZTU1FVFJJQwkBAiE9AgUMX2Z1bmRpbmdNb2RlBRJGVU5ESU5HX0FTWU1NRVRSSUMHBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECHUludmFsaWQgY2hhbmdlU2V0dGluZ3MgcGFyYW1zCQEOdXBkYXRlU2V0dGluZ3MOBRBfaW5pdE1hcmdpblJhdGlvBQRfbW1yBRRfbGlxdWlkYXRpb25GZWVSYXRpbwUOX2Z1bmRpbmdQZXJpb2QFBF9mZWUFDF9zcHJlYWRMaW1pdAUPX21heFByaWNlSW1wYWN0BRhfcGFydGlhbExpcXVpZGF0aW9uUmF0aW8FD19tYXhQcmljZVNwcmVhZAUQX21heE9wZW5Ob3Rpb25hbAUUX2ZlZVRvU3Rha2Vyc1BlcmNlbnQFD19tYXhPcmFjbGVEZWxheQUMX3JvbGxvdmVyRmVlBQxfZnVuZGluZ01vZGUBaQEKaW5pdGlhbGl6ZRMHX3F0QXN0UgdfYnNBc3RSDl9mdW5kaW5nUGVyaW9kEF9pbml0TWFyZ2luUmF0aW8EX21tchRfbGlxdWlkYXRpb25GZWVSYXRpbwRfZmVlD19iYXNlT3JhY2xlRGF0YRBfcXVvdGVPcmFjbGVEYXRhDF9jb29yZGluYXRvcgxfc3ByZWFkTGltaXQPX21heFByaWNlSW1wYWN0GF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbw9fbWF4UHJpY2VTcHJlYWQQX21heE9wZW5Ob3Rpb25hbBRfZmVlVG9TdGFrZXJzUGVyY2VudA9fbWF4T3JhY2xlRGVsYXkMX3JvbGxvdmVyRmVlDF9mdW5kaW5nTW9kZQMDAwMDAwMDAwMDAwMDAwMDAwMJAGcCAAAFB19xdEFzdFIGCQBnAgAABQdfYnNBc3RSBgkAZwIAAAUOX2Z1bmRpbmdQZXJpb2QGCQBnAgAABRBfaW5pdE1hcmdpblJhdGlvBgkAZwIAAAUEX21tcgYJAGcCAAAFFF9saXF1aWRhdGlvbkZlZVJhdGlvBgkAZwIAAAUEX2ZlZQYJAGcCAAAFDF9zcHJlYWRMaW1pdAYJAGcCAAAFD19tYXhQcmljZUltcGFjdAYJAGcCAAAFGF9wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwYJAGcCAAAFD19tYXhQcmljZVNwcmVhZAYJAGcCAAAFEF9tYXhPcGVuTm90aW9uYWwGCQBnAgAABRRfZmVlVG9TdGFrZXJzUGVyY2VudAYJAGYCBRRfZmVlVG9TdGFrZXJzUGVyY2VudAUMREVDSU1BTF9VTklUBgkAZwIAAAUPX21heE9yYWNsZURlbGF5BgkAZwIAAAUMX3JvbGxvdmVyRmVlBgMJAQIhPQIFDF9mdW5kaW5nTW9kZQURRlVORElOR19TWU1NRVRSSUMJAQIhPQIFDF9mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDBwYJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAh1JbnZhbGlkIGluaXRpYWxpemUgcGFyYW1ldGVycwkAzggCCQDOCAIJAM4IAgkAzggCCQEJdXBkYXRlQW1tCAUHX3F0QXN0UgUHX2JzQXN0UgAAAAAAAAAAAAAAAAkBDnVwZGF0ZVNldHRpbmdzDgUQX2luaXRNYXJnaW5SYXRpbwUEX21tcgUUX2xpcXVpZGF0aW9uRmVlUmF0aW8FDl9mdW5kaW5nUGVyaW9kBQRfZmVlBQxfc3ByZWFkTGltaXQFD19tYXhQcmljZUltcGFjdAUYX3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvBQ9fbWF4UHJpY2VTcHJlYWQFEF9tYXhPcGVuTm90aW9uYWwFFF9mZWVUb1N0YWtlcnNQZXJjZW50BQ9fbWF4T3JhY2xlRGVsYXkFDF9yb2xsb3ZlckZlZQUMX2Z1bmRpbmdNb2RlCQENdXBkYXRlRnVuZGluZwUJAGQCCQENbGFzdFRpbWVzdGFtcAAFDl9mdW5kaW5nUGVyaW9kAAAAAAAAAAAJAQ11cGRhdGVCYWxhbmNlAQAACQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rX2luaXRpYWxpemVkBgkAzAgCCQELU3RyaW5nRW50cnkCBQxrX2Jhc2VPcmFjbGUFD19iYXNlT3JhY2xlRGF0YQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rX3F1b3RlT3JhY2xlBRBfcXVvdGVPcmFjbGVEYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzCQClCAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDF9jb29yZGluYXRvcgUDbmlsAWkBEGluY3JlYXNlUG9zaXRpb24ECl9kaXJlY3Rpb24JX2xldmVyYWdlE19taW5CYXNlQXNzZXRBbW91bnQIX3JlZkxpbmsEBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQEPZ2V0QWN0dWFsQ2FsbGVyAQUBaQQKX3Jhd0Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMDAwMDCQECIT0CBQpfZGlyZWN0aW9uBQhESVJfTE9ORwkBAiE9AgUKX2RpcmVjdGlvbgUJRElSX1NIT1JUBwYJAGcCAAAFCl9yYXdBbW91bnQGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEBIQEFDGlzUXVvdGVBc3NldAYJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DCQEEZGl2ZAIFDERFQ0lNQUxfVU5JVAUJX2xldmVyYWdlCQEPaW5pdE1hcmdpblJhdGlvAAYGCQEGcGF1c2VkAAYJAQljbG9zZU9ubHkABgkBDmlzTWFya2V0Q2xvc2VkAAkAAgECI0ludmFsaWQgaW5jcmVhc2VQb3NpdGlvbiBwYXJhbWV0ZXJzBA0kdDA1ODU0ODU4Njk3CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgkBDWdldEFydGlmYWN0SWQBBQFpBAthZGp1c3RlZEZlZQgFDSR0MDU4NTQ4NTg2OTcCXzEEDGJ1cm5BcnRpZmFjdAgFDSR0MDU4NTQ4NTg2OTcCXzIEB19hbW91bnQJAQRkaXZkAgUKX3Jhd0Ftb3VudAkAZAIJAQRtdWxkAgULYWRqdXN0ZWRGZWUFCV9sZXZlcmFnZQUMREVDSU1BTF9VTklUBBNkaXN0cmlidXRlRmVlQW1vdW50CQBlAgUKX3Jhd0Ftb3VudAUHX2Ftb3VudAQOcmVmZXJyZXJGZWVBbnkJAPwHBAkBD3JlZmVycmFsQWRkcmVzcwACFWFjY2VwdFBheW1lbnRXaXRoTGluawkAzAgCBQdfdHJhZGVyCQDMCAIFCF9yZWZMaW5rBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUTZGlzdHJpYnV0ZUZlZUFtb3VudAUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUECWZlZUFtb3VudAkAZQIFE2Rpc3RyaWJ1dGVGZWVBbW91bnQFC3JlZmVycmVyRmVlBA0kdDA1OTE5MzU5MzczCQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA1OTE5MzU5MzczAl8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDU5MTkzNTkzNzMCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTkxOTM1OTM3MwJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA1OTE5MzU5MzczAl80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDU5MTkzNTkzNzMCXzUEDWlzTmV3UG9zaXRpb24JAAACBQ9vbGRQb3NpdGlvblNpemUAAAQPaXNTYW1lRGlyZWN0aW9uAwkAZgIFD29sZFBvc2l0aW9uU2l6ZQAACQAAAgUKX2RpcmVjdGlvbgUIRElSX0xPTkcJAAACBQpfZGlyZWN0aW9uBQlESVJfU0hPUlQEDmV4cGFuZEV4aXN0aW5nAwkBASEBBQ1pc05ld1Bvc2l0aW9uBQ9pc1NhbWVEaXJlY3Rpb24HBAVpc0FkZAkAAAIFCl9kaXJlY3Rpb24FCERJUl9MT05HBA0kdDA1OTY2MjYyNzk1AwMFDWlzTmV3UG9zaXRpb24GBQ5leHBhbmRFeGlzdGluZwQMb3Blbk5vdGlvbmFsCQEEbXVsZAIFB19hbW91bnQFCV9sZXZlcmFnZQQNJHQwNjAxNzE2MDM0NAkBCXN3YXBJbnB1dAIFBWlzQWRkBQxvcGVuTm90aW9uYWwEFWFtb3VudEJhc2VBc3NldEJvdWdodAgFDSR0MDYwMTcxNjAzNDQCXzEEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2MDE3MTYwMzQ0Al8yBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA2MDE3MTYwMzQ0Al8zBBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNjAxNzE2MDM0NAJfNAMDCQECIT0CBRNfbWluQmFzZUFzc2V0QW1vdW50AAAJAGYCBRNfbWluQmFzZUFzc2V0QW1vdW50CQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BwkAAgEJAKwCAgkArAICCQCsAgICDUxpbWl0IGVycm9yOiAJAKQDAQkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAIDIDwgCQCkAwEFE19taW5CYXNlQXNzZXRBbW91bnQED25ld1Bvc2l0aW9uU2l6ZQkAZAIFD29sZFBvc2l0aW9uU2l6ZQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARBvcGVuSW50ZXJlc3RMb25nAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAUMb3Blbk5vdGlvbmFsAAAEG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAZAIJARFvcGVuSW50ZXJlc3RTaG9ydAADCQBmAgAABQ9uZXdQb3NpdGlvblNpemUFDG9wZW5Ob3Rpb25hbAAABA0kdDA2MDg5MDYxMTY1CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUPb2xkUG9zaXRpb25TaXplBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25Mc3RVcGRDUEYFFG9sZFBvc2l0aW9uVGltZXN0YW1wBQdfYW1vdW50BAxyZW1haW5NYXJnaW4IBQ0kdDA2MDg5MDYxMTY1Al8xBAJ4MQgFDSR0MDYwODkwNjExNjUCXzIEAngyCAUNJHQwNjA4OTA2MTE2NQJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA2MDg5MDYxMTY1Al80AwkBASEBCQEZcmVxdWlyZU5vdE92ZXJTcHJlYWRMaW1pdAIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgkAAgECFU92ZXIgbWF4IHNwcmVhZCBsaW1pdAMJAQEhAQkBHXJlcXVpcmVOb3RPdmVyTWF4T3Blbk5vdGlvbmFsAgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkAAgECFk92ZXIgbWF4IG9wZW4gbm90aW9uYWwJAKAKDgUPbmV3UG9zaXRpb25TaXplBQxyZW1haW5NYXJnaW4JAGQCBRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQEfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFD25ld1Bvc2l0aW9uU2l6ZQkBDWxhc3RUaW1lc3RhbXAABRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIJAGQCCQEUb3BlbkludGVyZXN0Tm90aW9uYWwABQxvcGVuTm90aW9uYWwJAGQCCQEVdG90YWxMb25nUG9zaXRpb25TaXplAAMJAGYCBQ9uZXdQb3NpdGlvblNpemUAAAkBA2FicwEFFWFtb3VudEJhc2VBc3NldEJvdWdodAAACQBkAgkBFnRvdGFsU2hvcnRQb3NpdGlvblNpemUAAwkAZgIAAAUPbmV3UG9zaXRpb25TaXplCQEDYWJzAQUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0AAAFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIFC3JvbGxvdmVyRmVlBAxvcGVuTm90aW9uYWwJAQRtdWxkAgUHX2Ftb3VudAUJX2xldmVyYWdlBA0kdDA2MjQ4MzYyNjExCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwDCQClCAEIBQFpBmNhbGxlcgUKX2RpcmVjdGlvbgUPUE5MX09QVElPTl9TUE9UBBNvbGRQb3NpdGlvbk5vdGlvbmFsCAUNJHQwNjI0ODM2MjYxMQJfMQQNdW5yZWFsaXplZFBubAgFDSR0MDYyNDgzNjI2MTECXzIDCQBmAgUTb2xkUG9zaXRpb25Ob3Rpb25hbAUMb3Blbk5vdGlvbmFsCQACAQIuVXNlIGRlY3JlYXNlUG9zaXRpb24gdG8gZGVjcmVhc2UgcG9zaXRpb24gc2l6ZQkAAgECFENsb3NlIHBvc2l0aW9uIGZpcnN0BA9uZXdQb3NpdGlvblNpemUIBQ0kdDA1OTY2MjYyNzk1Al8xBBduZXdQb3NpdGlvblJlbWFpbk1hcmdpbggFDSR0MDU5NjYyNjI3OTUCXzIEF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNTk2NjI2Mjc5NQJfMwQUbmV3UG9zaXRpb25MYXRlc3RDUEYIBQ0kdDA1OTY2MjYyNzk1Al80BBRuZXdQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDU5NjYyNjI3OTUCXzUEFWJhc2VBc3NldFJlc2VydmVBZnRlcggFDSR0MDU5NjYyNjI3OTUCXzYEFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIIBQ0kdDA1OTY2MjYyNzk1Al83BBZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyCAUNJHQwNTk2NjI2Mjc5NQJfOAQZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcggFDSR0MDU5NjYyNjI3OTUCXzkEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNTk2NjI2Mjc5NQNfMTAED3RvdGFsU2hvcnRBZnRlcggFDSR0MDU5NjYyNjI3OTUDXzExBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDU5NjYyNjI3OTUDXzEyBBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA1OTY2MjYyNzk1A18xMwQLcm9sbG92ZXJGZWUIBQ0kdDA1OTY2MjYyNzk1A18xNAQNJHQwNjI4MDE2Mjg3MgkBDWRpc3RyaWJ1dGVGZWUBCQBkAgUJZmVlQW1vdW50BQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjI4MDE2Mjg3MgJfMQQKZmVlVG9WYXVsdAgFDSR0MDYyODAxNjI4NzICXzIEBXN0YWtlAwkAZwIFB19hbW91bnQFC3JvbGxvdmVyRmVlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAglhZGRMb2NrZWQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQBlAgUHX2Ftb3VudAULcm9sbG92ZXJGZWUFA25pbAkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgkAZQIFC3JvbGxvdmVyRmVlBQdfYW1vdW50BQNuaWwFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgUJZmVlQW1vdW50BQNuaWwFA25pbAMJAAACBQlub3RpZnlGZWUFCW5vdGlmeUZlZQQObm90aWZ5Tm90aW9uYWwJAPwHBAkBDG1pbmVyQWRkcmVzcwACDm5vdGlmeU5vdGlvbmFsCQDMCAIFB190cmFkZXIJAMwIAgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFA25pbAUDbmlsAwkAAAIFDm5vdGlmeU5vdGlvbmFsBQ5ub3RpZnlOb3Rpb25hbAkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRduZXdQb3NpdGlvblJlbWFpbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTGF0ZXN0Q1BGBRRuZXdQb3NpdGlvblRpbWVzdGFtcAkBH2luY3JlbWVudFBvc2l0aW9uU2VxdWVuY2VOdW1iZXIDBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyBQpfZGlyZWN0aW9uCQERdXBkYXRlUG9zaXRpb25GZWUEBQ1pc05ld1Bvc2l0aW9uBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQthZGp1c3RlZEZlZQkBCXVwZGF0ZUFtbQgFFnF1b3RlQXNzZXRSZXNlcnZlQWZ0ZXIFFWJhc2VBc3NldFJlc2VydmVBZnRlcgUWdG90YWxQb3NpdGlvblNpemVBZnRlcgUZb3BlbkludGVyZXN0Tm90aW9uYWxBZnRlcgUOdG90YWxMb25nQWZ0ZXIFD3RvdGFsU2hvcnRBZnRlcgUadG90YWxMb25nT3BlbkludGVyZXN0QWZ0ZXIFG3RvdGFsU2hvcnRPcGVuSW50ZXJlc3RBZnRlcgkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQENdXBkYXRlQmFsYW5jZQEJAGUCCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUJAQ5kb0J1cm5BcnRpZmFjdAIFDGJ1cm5BcnRpZmFjdAUBaQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRNYXJnaW4BCl9kaXJlY3Rpb24EBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgQHX2Ftb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQECF9hc3NldElkCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC19hc3NldElkU3RyCQDYBAEJAQV2YWx1ZQEFCF9hc3NldElkBAxpc1F1b3RlQXNzZXQJAAACBQhfYXNzZXRJZAkBCnF1b3RlQXNzZXQAAwMDAwMJAQEhAQUMaXNRdW90ZUFzc2V0BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgIJAKUIAQgFAWkGY2FsbGVyBQpfZGlyZWN0aW9uBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQIcSW52YWxpZCBhZGRNYXJnaW4gcGFyYW1ldGVycwQNJHQwNjUxMTk2NTI5OQkBC2dldFBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgQPb2xkUG9zaXRpb25TaXplCAUNJHQwNjUxMTk2NTI5OQJfMQQRb2xkUG9zaXRpb25NYXJnaW4IBQ0kdDA2NTExOTY1Mjk5Al8yBBdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAgFDSR0MDY1MTE5NjUyOTkCXzMEFG9sZFBvc2l0aW9uTHN0VXBkQ1BGCAUNJHQwNjUxMTk2NTI5OQJfNAQUb2xkUG9zaXRpb25UaW1lc3RhbXAIBQ0kdDA2NTExOTY1Mjk5Al81BAVzdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIJYWRkTG9ja2VkBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQpxdW90ZUFzc2V0AAUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQQLcm9sbG92ZXJGZWUJAQ9jYWxjUm9sbG92ZXJGZWUCBRFvbGRQb3NpdGlvbk1hcmdpbgUUb2xkUG9zaXRpb25UaW1lc3RhbXAEFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMDCQBmAgULcm9sbG92ZXJGZWUAAAQNJHQwNjU1ODQ2NTY0MwkBDWRpc3RyaWJ1dGVGZWUBBQtyb2xsb3ZlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNjU1ODQ2NTY0MwJfMQQKZmVlVG9WYXVsdAgFDSR0MDY1NTg0NjU2NDMCXzIEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFDGZlZVRvU3Rha2VycwUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQLbG9ja0JhZERlYnQJAPwHBAkBDHZhdWx0QWRkcmVzcwACFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAkAzAgCCQEBLQEFCmZlZVRvVmF1bHQFA25pbAUDbmlsAwkAAAIFC2xvY2tCYWREZWJ0BQtsb2NrQmFkRGVidAkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwUWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwkAzggCCQDOCAIJAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD29sZFBvc2l0aW9uU2l6ZQkAZAIJAGUCBRFvbGRQb3NpdGlvbk1hcmdpbgULcm9sbG92ZXJGZWUFB19hbW91bnQFF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsBRRvbGRQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQENdXBkYXRlQmFsYW5jZQEJAGUCCQBkAgkBCGNiYWxhbmNlAAUHX2Ftb3VudAULcm9sbG92ZXJGZWUFFmRvVHJhbnNmZXJGZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMcmVtb3ZlTWFyZ2luAgdfYW1vdW50Cl9kaXJlY3Rpb24EBHN5bmMJAPwHBAUEdGhpcwIZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQUDbmlsBQNuaWwDCQAAAgUEc3luYwUEc3luYwQQZW5zdXJlQ2FsbGVkT25jZQkA/AcEBQR0aGlzAhBlbnN1cmVDYWxsZWRPbmNlBQNuaWwFA25pbAMJAAACBRBlbnN1cmVDYWxsZWRPbmNlBRBlbnN1cmVDYWxsZWRPbmNlBAdfdHJhZGVyCQClCAEIBQFpBmNhbGxlcgMDAwMDCQBnAgAABQdfYW1vdW50BgkBASEBCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24GCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAh9JbnZhbGlkIHJlbW92ZU1hcmdpbiBwYXJhbWV0ZXJzBA0kdDA2NzA0NzY3MjI3CQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBA9vbGRQb3NpdGlvblNpemUIBQ0kdDA2NzA0NzY3MjI3Al8xBBFvbGRQb3NpdGlvbk1hcmdpbggFDSR0MDY3MDQ3NjcyMjcCXzIEF29sZFBvc2l0aW9uT3Blbk5vdGlvbmFsCAUNJHQwNjcwNDc2NzIyNwJfMwQUb2xkUG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA2NzA0NzY3MjI3Al80BBRvbGRQb3NpdGlvblRpbWVzdGFtcAgFDSR0MDY3MDQ3NjcyMjcCXzUEDSR0MDY3MjMzNjc0ODIJATBjYWxjUmVtYWluTWFyZ2luV2l0aEZ1bmRpbmdQYXltZW50QW5kUm9sbG92ZXJGZWUFBQ9vbGRQb3NpdGlvblNpemUFEW9sZFBvc2l0aW9uTWFyZ2luBRRvbGRQb3NpdGlvbkxzdFVwZENQRgUUb2xkUG9zaXRpb25UaW1lc3RhbXAJAQEtAQUHX2Ftb3VudAQMcmVtYWluTWFyZ2luCAUNJHQwNjcyMzM2NzQ4MgJfMQQHYmFkRGVidAgFDSR0MDY3MjMzNjc0ODICXzIEDmZ1bmRpbmdQYXltZW50CAUNJHQwNjcyMzM2NzQ4MgJfMwQLcm9sbG92ZXJGZWUIBQ0kdDA2NzIzMzY3NDgyAl80AwkBAiE9AgUHYmFkRGVidAAACQACAQIdSW52YWxpZCByZW1vdmVkIG1hcmdpbiBhbW91bnQEC21hcmdpblJhdGlvCQEPY2FsY01hcmdpblJhdGlvAwUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BRdvbGRQb3NpdGlvbk9wZW5Ob3Rpb25hbAMJAQEhAQkBFnJlcXVpcmVNb3JlTWFyZ2luUmF0aW8DBQttYXJnaW5SYXRpbwkBD2luaXRNYXJnaW5SYXRpbwAGCQACAQkArAICCQCsAgIJAKwCAgIZVG9vIG11Y2ggbWFyZ2luIHJlbW92ZWQ6IAkApAMBBQttYXJnaW5SYXRpbwIDIDwgCQCkAwEJAQ9pbml0TWFyZ2luUmF0aW8ABA0kdDA2Nzg2ODY3OTI3CQENZGlzdHJpYnV0ZUZlZQEFC3JvbGxvdmVyRmVlBAxmZWVUb1N0YWtlcnMIBQ0kdDA2Nzg2ODY3OTI3Al8xBApmZWVUb1ZhdWx0CAUNJHQwNjc4Njg2NzkyNwJfMgQWZG9UcmFuc2ZlckZlZVRvU3Rha2VycwMJAGYCBQtyb2xsb3ZlckZlZQAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUKZmVlVG9WYXVsdAUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0CQELdHJhbnNmZXJGZWUBBQxmZWVUb1N0YWtlcnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzBAd1bnN0YWtlCQD8BwQJAQx2YXVsdEFkZHJlc3MAAg53aXRoZHJhd0xvY2tlZAkAzAgCCQBkAgUHX2Ftb3VudAUMZmVlVG9TdGFrZXJzBQNuaWwFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQDOCAIJAM4IAgkAzggCCQEOdXBkYXRlUG9zaXRpb24GBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUFDHJlbWFpbk1hcmdpbgUXb2xkUG9zaXRpb25PcGVuTm90aW9uYWwJAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAQUPb2xkUG9zaXRpb25TaXplCQENbGFzdFRpbWVzdGFtcAAJAQh3aXRoZHJhdwIIBQFpBmNhbGxlcgUHX2Ftb3VudAkBDXVwZGF0ZUJhbGFuY2UBCQBlAgkAZQIJAQhjYmFsYW5jZQAFB19hbW91bnQFC3JvbGxvdmVyRmVlBRZkb1RyYW5zZmVyRmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNsb3NlUG9zaXRpb24EBV9zaXplCl9kaXJlY3Rpb24UX21pblF1b3RlQXNzZXRBbW91bnQMX2FkZFRvTWFyZ2luBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEEGVuc3VyZUNhbGxlZE9uY2UJAPwHBAUEdGhpcwIQZW5zdXJlQ2FsbGVkT25jZQUDbmlsBQNuaWwDCQAAAgUQZW5zdXJlQ2FsbGVkT25jZQUQZW5zdXJlQ2FsbGVkT25jZQQHX3RyYWRlcgkBD2dldEFjdHVhbENhbGxlcgEFAWkEDl90cmFkZXJBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUHX3RyYWRlcgIOSW52YWxpZCBjYWxsZXIEC3Bvc2l0aW9uRmVlCQEOZ2V0UG9zaXRpb25GZWUCBQdfdHJhZGVyBQpfZGlyZWN0aW9uAwMDAwMDCQEBIQEJARNyZXF1aXJlT3BlblBvc2l0aW9uAgUHX3RyYWRlcgUKX2RpcmVjdGlvbgYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQZwYXVzZWQABgkAZwIAAAUFX3NpemUGCQBmAgAABRRfbWluUXVvdGVBc3NldEFtb3VudAYJAQ5pc01hcmtldENsb3NlZAAJAAIBAiBJbnZhbGlkIGNsb3NlUG9zaXRpb24gcGFyYW1ldGVycwQUb2xkUG9zaXRpb25UaW1lc3RhbXAICQELZ2V0UG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uAl81BA0kdDA3MDE1NTcwNzU4CQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uCAUHX3RyYWRlcgUKX2RpcmVjdGlvbgUFX3NpemUFC3Bvc2l0aW9uRmVlBRRfbWluUXVvdGVBc3NldEFtb3VudAUMX2FkZFRvTWFyZ2luBgYED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDcwMTU1NzA3NTgCXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNzAxNTU3MDc1OAJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA3MDE1NTcwNzU4Al8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDcwMTU1NzA3NTgCXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDcwMTU1NzA3NTgCXzUEC3JlYWxpemVkUG5sCAUNJHQwNzAxNTU3MDc1OAJfNgQObWFyZ2luVG9UcmFkZXIIBQ0kdDA3MDE1NTcwNzU4Al83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzAxNTU3MDc1OAJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzAxNTU3MDc1OAJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDcwMTU1NzA3NTgDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNzAxNTU3MDc1OANfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzAxNTU3MDc1OANfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDcwMTU1NzA3NTgDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDcwMTU1NzA3NTgDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3MDE1NTcwNzU4A18xNQQLcmVhbGl6ZWRGZWUIBQ0kdDA3MDE1NTcwNzU4A18xNgMJAGYCBQ9wb3NpdGlvbkJhZERlYnQAAAkAAgECKkludmFsaWQgY2xvc2VQb3NpdGlvbiBwYXJhbWV0ZXJzOiBiYWQgZGVidAMJAGcCBRRvbGRQb3NpdGlvblRpbWVzdGFtcAkBDWxhc3RUaW1lc3RhbXAACQACAQJTSW52YWxpZCBjbG9zZVBvc2l0aW9uIHBhcmFtZXRlcnM6IHdhaXQgYXQgbGVhc3QgMSBibG9jayBiZWZvcmUgY2xvc2luZyB0aGUgcG9zaXRpb24EDmlzUGFydGlhbENsb3NlCQECIT0CBQ9uZXdQb3NpdGlvblNpemUAAAQOd2l0aGRyYXdBbW91bnQJAGQCBQ5tYXJnaW5Ub1RyYWRlcgULcmVhbGl6ZWRGZWUECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABQ53aXRoZHJhd0Ftb3VudAQNYW1tTmV3QmFsYW5jZQMJAGYCAAAFCmFtbUJhbGFuY2UAAAUKYW1tQmFsYW5jZQQHdW5zdGFrZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIOd2l0aGRyYXdMb2NrZWQJAMwIAgUOd2l0aGRyYXdBbW91bnQFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UEDnJlZmVycmVyRmVlQW55CQD8BwQJAQ9yZWZlcnJhbEFkZHJlc3MAAg1hY2NlcHRQYXltZW50CQDMCAIFB190cmFkZXIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQABQtyZWFsaXplZEZlZQUDbmlsAwkAAAIFDnJlZmVycmVyRmVlQW55BQ5yZWZlcnJlckZlZUFueQQLcmVmZXJyZXJGZWUEByRtYXRjaDAFDnJlZmVycmVyRmVlQW55AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECE0ludmFsaWQgcmVmZXJyZXJGZWUEDSR0MDcxNzMwNzE4MDMJAQ1kaXN0cmlidXRlRmVlAQkAZQIFC3JlYWxpemVkRmVlBQtyZWZlcnJlckZlZQQMZmVlVG9TdGFrZXJzCAUNJHQwNzE3MzA3MTgwMwJfMQQKZmVlVG9WYXVsdAgFDSR0MDcxNzMwNzE4MDMCXzIEDGRlcG9zaXRWYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBQxkZXBvc2l0VmF1bHQFDGRlcG9zaXRWYXVsdAQJbm90aWZ5RmVlCQD8BwQJAQxtaW5lckFkZHJlc3MAAgpub3RpZnlGZWVzCQDMCAIFB190cmFkZXIJAMwIAgULcmVhbGl6ZWRGZWUFA25pbAUDbmlsAwkAAAIFCW5vdGlmeUZlZQUJbm90aWZ5RmVlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCCQDOCAIDBQ5pc1BhcnRpYWxDbG9zZQkBDnVwZGF0ZVBvc2l0aW9uBgUHX3RyYWRlcgUPbmV3UG9zaXRpb25TaXplBRFuZXdQb3NpdGlvbk1hcmdpbgUXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwFFG5ld1Bvc2l0aW9uTHN0VXBkQ1BGCQENbGFzdFRpbWVzdGFtcAAJAQ5kZWxldGVQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24JAQl1cGRhdGVBbW0IBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBRViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIFFnRvdGFsUG9zaXRpb25TaXplQWZ0ZXIFGW9wZW5JbnRlcmVzdE5vdGlvbmFsQWZ0ZXIFDnRvdGFsTG9uZ0FmdGVyBQ90b3RhbFNob3J0QWZ0ZXIFGnRvdGFsTG9uZ09wZW5JbnRlcmVzdEFmdGVyBRt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIDCQBmAgUObWFyZ2luVG9UcmFkZXIAAAkBCHdpdGhkcmF3AgUOX3RyYWRlckFkZHJlc3MFDm1hcmdpblRvVHJhZGVyBQNuaWwJAQ11cGRhdGVCYWxhbmNlAQUNYW1tTmV3QmFsYW5jZQkBC3RyYW5zZmVyRmVlAQUMZmVlVG9TdGFrZXJzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWxpcXVpZGF0ZQIHX3RyYWRlcgpfZGlyZWN0aW9uBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMED3Nwb3RNYXJnaW5SYXRpbwkBFmdldE1hcmdpblJhdGlvQnlPcHRpb24DBQdfdHJhZGVyBQpfZGlyZWN0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8DCQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAAEEW9yYWNsZU1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgMFB190cmFkZXIFCl9kaXJlY3Rpb24FEVBOTF9PUFRJT05fT1JBQ0xFCQEEdm1heAIFD3Nwb3RNYXJnaW5SYXRpbwURb3JhY2xlTWFyZ2luUmF0aW8FD3Nwb3RNYXJnaW5SYXRpbwMDAwMDCQEBIQEJARZyZXF1aXJlTW9yZU1hcmdpblJhdGlvAwUWbGlxdWlkYXRpb25NYXJnaW5SYXRpbwkBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8ABwYJAQEhAQkBE3JlcXVpcmVPcGVuUG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uBgkBASEBCQELaW5pdGlhbGl6ZWQABgkBBnBhdXNlZAAGCQEOaXNNYXJrZXRDbG9zZWQACQACAQITVW5hYmxlIHRvIGxpcXVpZGF0ZQQUaXNQYXJ0aWFsTGlxdWlkYXRpb24DAwkAZgIFD3Nwb3RNYXJnaW5SYXRpbwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8ACQBmAgkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAAABwkAZgIFDERFQ0lNQUxfVU5JVAkBF3BhcnRpYWxMaXF1aWRhdGlvblJhdGlvAAcED29sZFBvc2l0aW9uU2l6ZQgJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24CXzEED3Bvc2l0aW9uU2l6ZUFicwkBA2FicwEFD29sZFBvc2l0aW9uU2l6ZQQNJHQwNzQzMDE3NDYyNAMFFGlzUGFydGlhbExpcXVpZGF0aW9uBA9saXF1aWRhdGlvblNpemUJARtnZXRQYXJ0aWFsTGlxdWlkYXRpb25BbW91bnQCBQdfdHJhZGVyBQ9vbGRQb3NpdGlvblNpemUEEGxpcXVpZGF0aW9uUmF0aW8JAQRkaXZkAgkBA2FicwEFD2xpcXVpZGF0aW9uU2l6ZQUPcG9zaXRpb25TaXplQWJzCQCUCgIFEGxpcXVpZGF0aW9uUmF0aW8JAQNhYnMBBQ9saXF1aWRhdGlvblNpemUJAJQKAgAABQ9wb3NpdGlvblNpemVBYnMEEGxpcXVpZGF0aW9uUmF0aW8IBQ0kdDA3NDMwMTc0NjI0Al8xBA9saXF1aWRhdGlvblNpemUIBQ0kdDA3NDMwMTc0NjI0Al8yBA0kdDA3NDYzMDc1Mjg2CQEVaW50ZXJuYWxDbG9zZVBvc2l0aW9uCAUHX3RyYWRlcgUKX2RpcmVjdGlvbgMFFGlzUGFydGlhbExpcXVpZGF0aW9uBQ9saXF1aWRhdGlvblNpemUFD3Bvc2l0aW9uU2l6ZUFicwkBE2xpcXVpZGF0aW9uRmVlUmF0aW8AAAAGBwYED25ld1Bvc2l0aW9uU2l6ZQgFDSR0MDc0NjMwNzUyODYCXzEEEW5ld1Bvc2l0aW9uTWFyZ2luCAUNJHQwNzQ2MzA3NTI4NgJfMgQXbmV3UG9zaXRpb25PcGVuTm90aW9uYWwIBQ0kdDA3NDYzMDc1Mjg2Al8zBBRuZXdQb3NpdGlvbkxzdFVwZENQRggFDSR0MDc0NjMwNzUyODYCXzQED3Bvc2l0aW9uQmFkRGVidAgFDSR0MDc0NjMwNzUyODYCXzUEC3JlYWxpemVkUG5sCAUNJHQwNzQ2MzA3NTI4NgJfNgQObWFyZ2luVG9UcmFkZXIIBQ0kdDA3NDYzMDc1Mjg2Al83BBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzQ2MzA3NTI4NgJfOAQVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyCAUNJHQwNzQ2MzA3NTI4NgJfOQQWdG90YWxQb3NpdGlvblNpemVBZnRlcggFDSR0MDc0NjMwNzUyODYDXzEwBBlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyCAUNJHQwNzQ2MzA3NTI4NgNfMTEEDnRvdGFsTG9uZ0FmdGVyCAUNJHQwNzQ2MzA3NTI4NgNfMTIED3RvdGFsU2hvcnRBZnRlcggFDSR0MDc0NjMwNzUyODYDXzEzBBp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcggFDSR0MDc0NjMwNzUyODYDXzE0BBt0b3RhbFNob3J0T3BlbkludGVyZXN0QWZ0ZXIIBQ0kdDA3NDYzMDc1Mjg2A18xNQQSbGlxdWlkYXRpb25QZW5hbHR5CAUNJHQwNzQ2MzA3NTI4NgNfMTYED2ZlZVRvTGlxdWlkYXRvcgkAaQIFEmxpcXVpZGF0aW9uUGVuYWx0eQACBApmZWVUb1ZhdWx0CQBlAgUSbGlxdWlkYXRpb25QZW5hbHR5BQ9mZWVUb0xpcXVpZGF0b3IECmFtbUJhbGFuY2UJAGUCCQEIY2JhbGFuY2UABRJsaXF1aWRhdGlvblBlbmFsdHkEDW5ld0FtbUJhbGFuY2UDCQBmAgAABQphbW1CYWxhbmNlAAAFCmFtbUJhbGFuY2UEC2xvY2tCYWREZWJ0AwkAZgIFD3Bvc2l0aW9uQmFkRGVidAAABAtsb2NrQmFkRGVidAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAGQCBQ9wb3NpdGlvbkJhZERlYnQFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgULbG9ja0JhZERlYnQFC2xvY2tCYWREZWJ0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQtsb2NrQmFkRGVidAULbG9ja0JhZERlYnQEB3Vuc3Rha2UJAPwHBAkBDHZhdWx0QWRkcmVzcwACDndpdGhkcmF3TG9ja2VkCQDMCAIFEmxpcXVpZGF0aW9uUGVuYWx0eQUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQQQZGVwb3NpdEluc3VyYW5jZQkA/AcECQEMdmF1bHRBZGRyZXNzAAIHYWRkRnJlZQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKcXVvdGVBc3NldAAFCmZlZVRvVmF1bHQFA25pbAMJAAACBRBkZXBvc2l0SW5zdXJhbmNlBRBkZXBvc2l0SW5zdXJhbmNlBA5ub3RpZnlOb3Rpb25hbAkA/AcECQEMbWluZXJBZGRyZXNzAAIObm90aWZ5Tm90aW9uYWwJAMwIAgUHX3RyYWRlcgkAzAgCBRduZXdQb3NpdGlvbk9wZW5Ob3Rpb25hbAUDbmlsBQNuaWwDCQAAAgUObm90aWZ5Tm90aW9uYWwFDm5vdGlmeU5vdGlvbmFsCQDOCAIJAM4IAgkAzggCAwUUaXNQYXJ0aWFsTGlxdWlkYXRpb24JAQ51cGRhdGVQb3NpdGlvbgYFB190cmFkZXIFD25ld1Bvc2l0aW9uU2l6ZQURbmV3UG9zaXRpb25NYXJnaW4FF25ld1Bvc2l0aW9uT3Blbk5vdGlvbmFsBRRuZXdQb3NpdGlvbkxzdFVwZENQRgkBDWxhc3RUaW1lc3RhbXAACQEOZGVsZXRlUG9zaXRpb24CBQdfdHJhZGVyBQpfZGlyZWN0aW9uCQEJdXBkYXRlQW1tCAUWcXVvdGVBc3NldFJlc2VydmVBZnRlcgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBRZ0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyBRlvcGVuSW50ZXJlc3ROb3Rpb25hbEFmdGVyBQ50b3RhbExvbmdBZnRlcgUPdG90YWxTaG9ydEFmdGVyBRp0b3RhbExvbmdPcGVuSW50ZXJlc3RBZnRlcgUbdG90YWxTaG9ydE9wZW5JbnRlcmVzdEFmdGVyCQEId2l0aGRyYXcCCAUBaQZjYWxsZXIFD2ZlZVRvTGlxdWlkYXRvcgkBDXVwZGF0ZUJhbGFuY2UBBQ1uZXdBbW1CYWxhbmNlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnBheUZ1bmRpbmcABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBGW5leHRGdW5kaW5nQmxvY2tUaW1lc3RhbXAAAwMDCQBmAgUVZnVuZGluZ0Jsb2NrVGltZXN0YW1wCQENbGFzdFRpbWVzdGFtcAAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEGcGF1c2VkAAkAAgEJAKwCAgkArAICCQCsAgICIUludmFsaWQgZnVuZGluZyBibG9jayB0aW1lc3RhbXA6IAkApAMBCQENbGFzdFRpbWVzdGFtcAACAyA8IAkApAMBBRVmdW5kaW5nQmxvY2tUaW1lc3RhbXAED3VuZGVybHlpbmdQcmljZQkBDmdldE9yYWNsZVByaWNlAAQNJHQwNzc0MTE3NzQ4OQkBCmdldEZ1bmRpbmcABBRzaG9ydFByZW1pdW1GcmFjdGlvbggFDSR0MDc3NDExNzc0ODkCXzEEE2xvbmdQcmVtaXVtRnJhY3Rpb24IBQ0kdDA3NzQxMTc3NDg5Al8yBA5wcmVtaXVtVG9WYXVsdAgFDSR0MDc3NDExNzc0ODkCXzMEE2RvUGF5RnVuZGluZ1RvVmF1bHQDCQBmAgUOcHJlbWl1bVRvVmF1bHQAAAQTZG9QYXlGdW5kaW5nVG9WYXVsdAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIJAQEtAQUOcHJlbWl1bVRvVmF1bHQFA25pbAUDbmlsAwkAAAIFE2RvUGF5RnVuZGluZ1RvVmF1bHQFE2RvUGF5RnVuZGluZ1RvVmF1bHQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFE2RvUGF5RnVuZGluZ1RvVmF1bHQFE2RvUGF5RnVuZGluZ1RvVmF1bHQJAQ11cGRhdGVGdW5kaW5nBQkAZAIFFWZ1bmRpbmdCbG9ja1RpbWVzdGFtcAkBFGZ1bmRpbmdQZXJpb2RTZWNvbmRzAAkAZAIJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgAFE2xvbmdQcmVtaXVtRnJhY3Rpb24JAGQCCQEkbGF0ZXN0U2hvcnRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAAUUc2hvcnRQcmVtaXVtRnJhY3Rpb24JAQRkaXZkAgUTbG9uZ1ByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQEEZGl2ZAIFFHNob3J0UHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEZc3luY1Rlcm1pbmFsUHJpY2VUb09yYWNsZQAEB19xdEFzdFIJAQZxdEFzdFIABAdfYnNBc3RSCQEGYnNBc3RSAAQNJHQwNzg1NDI3ODkwOAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwkBDmdldE9yYWNsZVByaWNlAAUHX3F0QXN0UgUHX2JzQXN0UgQTbmV3UXVvdGVBc3NldFdlaWdodAgFDSR0MDc4NTQyNzg5MDgCXzEEEm5ld0Jhc2VBc3NldFdlaWdodAgFDSR0MDc4NTQyNzg5MDgCXzIEDW1hcmdpblRvVmF1bHQIBQ0kdDA3ODU0Mjc4OTA4Al8zBBBtYXJnaW5Ub1ZhdWx0QWRqAwMJAGYCAAAFDW1hcmdpblRvVmF1bHQJAGYCCQEDYWJzAQUNbWFyZ2luVG9WYXVsdAkBCGNiYWxhbmNlAAcJAQEtAQkBCGNiYWxhbmNlAAUNbWFyZ2luVG9WYXVsdAQNZG9FeGNoYW5nZVBuTAMJAQIhPQIFEG1hcmdpblRvVmF1bHRBZGoAAAQNZG9FeGNoYW5nZVBuTAkA/AcECQEMdmF1bHRBZGRyZXNzAAIVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkCQDMCAIFEG1hcmdpblRvVmF1bHRBZGoFA25pbAUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFDWRvRXhjaGFuZ2VQbkwFDWRvRXhjaGFuZ2VQbkwJAM4IAgkBDXVwZGF0ZUJhbGFuY2UBCQBkAgkBCGNiYWxhbmNlAAUQbWFyZ2luVG9WYXVsdEFkagkBEHVwZGF0ZUFtbVdlaWdodHMCBRNuZXdRdW90ZUFzc2V0V2VpZ2h0BRJuZXdCYXNlQXNzZXRXZWlnaHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEQZW5zdXJlQ2FsbGVkT25jZQADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAiJJbnZhbGlkIHNhdmVDdXJyZW50VHhJZCBwYXJhbWV0ZXJzBAR0eElkCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQhrX2xhc3RUeAIAAwkBAiE9AgUGbGFzdFR4BQR0eElkCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGtfbGFzdFR4BQR0eElkBQNuaWwJAAIBAilDYW4gbm90IGNhbGwgdkFNTSBtZXRob2RzIHR3aWNlIGluIG9uZSB0eAFpAQ9taWdyYXRlUG9zaXRpb24BB190cmFkZXIED3Bvc2l0aW9uU2l6ZU9wdAkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgMDCQEJaXNEZWZpbmVkAQUPcG9zaXRpb25TaXplT3B0CQEJaXNEZWZpbmVkAQkApggBBQdfdHJhZGVyBwQFcFNpemUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQdfdHJhZGVyBAdwTWFyZ2luCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyBAlwTm90aW9uYWwJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFB190cmFkZXIECXBGcmFjdGlvbgkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgQKcFRpbWVzdGFtcAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFB190cmFkZXIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBARwRmVlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFB190cmFkZXIJAQNmZWUABAlwU2VxdWVuY2UJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMJAQ50b0NvbXBvc2l0ZUtleQIFEmtfcG9zaXRpb25TZXF1ZW5jZQUHX3RyYWRlcgQKcERpcmVjdGlvbgkBDGdldERpcmVjdGlvbgEFBXBTaXplBAtwb3NpdGlvbktleQkArAICCQCsAgIFB190cmFkZXICAV8JAKQDAQUKcERpcmVjdGlvbgkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFB190cmFkZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFB190cmFkZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDnRvQ29tcG9zaXRlS2V5AgUNa19wb3NpdGlvbkZlZQUHX3RyYWRlcgkAzAgCCQELRGVsZXRlRW50cnkBCQEOdG9Db21wb3NpdGVLZXkCBRJrX3Bvc2l0aW9uU2VxdWVuY2UFB190cmFkZXIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDmtfcG9zaXRpb25TaXplBQtwb3NpdGlvbktleQUFcFNpemUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfcG9zaXRpb25NYXJnaW4FC3Bvc2l0aW9uS2V5BQdwTWFyZ2luCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRZrX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBQtwb3NpdGlvbktleQUJcE5vdGlvbmFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBS5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBQtwb3NpdGlvbktleQUJcEZyYWN0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFC3Bvc2l0aW9uS2V5BQpwVGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ1rX3Bvc2l0aW9uRmVlBQtwb3NpdGlvbktleQUEcEZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUSa19wb3NpdGlvblNlcXVlbmNlBQtwb3NpdGlvbktleQUJcFNlcXVlbmNlBQNuaWwJAAIBCQCsAgICF05vdGhpbmcgdG8gbWlncmF0ZSBmb3IgBQdfdHJhZGVyAWkBJ3ZpZXdfY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudAIHX3RyYWRlcgpfZGlyZWN0aW9uBARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEDSR0MDgyNTk5ODI3MzUJAQtnZXRQb3NpdGlvbgIFB190cmFkZXIFCl9kaXJlY3Rpb24EDHBvc2l0aW9uU2l6ZQgFDSR0MDgyNTk5ODI3MzUCXzEEDnBvc2l0aW9uTWFyZ2luCAUNJHQwODI1OTk4MjczNQJfMgQDcG9uCAUNJHQwODI1OTk4MjczNQJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQ0kdDA4MjU5OTgyNzM1Al80BBFwb3NpdGlvblRpbWVzdGFtcAgFDSR0MDgyNTk5ODI3MzUCXzUEDSR0MDgyNzM4ODI4NTEJASNnZXRQb3NpdGlvbk5vdGlvbmFsQW5kVW5yZWFsaXplZFBubAMFB190cmFkZXIFCl9kaXJlY3Rpb24FD1BOTF9PUFRJT05fU1BPVAQQcG9zaXRpb25Ob3Rpb25hbAgFDSR0MDgyNzM4ODI4NTECXzEEDXVucmVhbGl6ZWRQbmwIBQ0kdDA4MjczODgyODUxAl8yBA0kdDA4Mjg1NDgzMDc4CQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBQUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgURcG9zaXRpb25Mc3RVcGRDUEYFEXBvc2l0aW9uVGltZXN0YW1wBQ11bnJlYWxpemVkUG5sBAxyZW1haW5NYXJnaW4IBQ0kdDA4Mjg1NDgzMDc4Al8xBAdiYWREZWJ0CAUNJHQwODI4NTQ4MzA3OAJfMgQOZnVuZGluZ1BheW1lbnQIBQ0kdDA4Mjg1NDgzMDc4Al8zBAtyb2xsb3ZlckZlZQgFDSR0MDgyODU0ODMwNzgCXzQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFDHJlbWFpbk1hcmdpbgkBAXMBBQ5mdW5kaW5nUGF5bWVudAkBAXMBCQEOZ2V0TWFyZ2luUmF0aW8CBQdfdHJhZGVyBQpfZGlyZWN0aW9uCQEBcwEFDXVucmVhbGl6ZWRQbmwJAQFzAQUHYmFkRGVidAkBAXMBBRBwb3NpdGlvbk5vdGlvbmFsCQEBcwEFC3JvbGxvdmVyRmVlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFXZpZXdfZ2V0UGVnQWRqdXN0Q29zdAEGX3ByaWNlBAdfcXRBc3RSCQEGcXRBc3RSAAQHX2JzQXN0UgkBBmJzQXN0UgAEBnJlc3VsdAkBFGdldFN5bmNUZXJtaW5hbFByaWNlAwUGX3ByaWNlBQdfcXRBc3RSBQdfYnNBc3RSCQACAQkApAMBCAUGcmVzdWx0Al8zAWkBGHZpZXdfZ2V0VGVybWluYWxBbW1QcmljZQAEDSR0MDgzODEzODM4OTQJARNnZXRUZXJtaW5hbEFtbVN0YXRlAAQZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQgFDSR0MDgzODEzODM4OTQCXzEEGHRlcm1pbmFsQmFzZUFzc2V0UmVzZXJ2ZQgFDSR0MDgzODEzODM4OTQCXzIEBXByaWNlCQEEZGl2ZAIJAQRtdWxkAgUZdGVybWluYWxRdW90ZUFzc2V0UmVzZXJ2ZQkBBnF0QXN0VwAJAQRtdWxkAgUYdGVybWluYWxCYXNlQXNzZXRSZXNlcnZlCQEGYnNBc3RXAAkAAgEJAKQDAQUFcHJpY2UBaQEPdmlld19nZXRGdW5kaW5nAAQEc3luYwkA/AcEBQR0aGlzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA91bmRlcmx5aW5nUHJpY2UJAQ5nZXRPcmFjbGVQcmljZQAEDSR0MDg0NDUzODQ1MzEJAQpnZXRGdW5kaW5nAAQUc2hvcnRQcmVtaXVtRnJhY3Rpb24IBQ0kdDA4NDQ1Mzg0NTMxAl8xBBNsb25nUHJlbWl1bUZyYWN0aW9uCAUNJHQwODQ0NTM4NDUzMQJfMgQOcHJlbWl1bVRvVmF1bHQIBQ0kdDA4NDQ1Mzg0NTMxAl8zBAtsb25nRnVuZGluZwkBBGRpdmQCBRNsb25nUHJlbWl1bUZyYWN0aW9uBQ91bmRlcmx5aW5nUHJpY2UEDHNob3J0RnVuZGluZwkBBGRpdmQCBRRzaG9ydFByZW1pdW1GcmFjdGlvbgUPdW5kZXJseWluZ1ByaWNlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQEBcwEFC2xvbmdGdW5kaW5nCQEBcwEFDHNob3J0RnVuZGluZwkBAXMBCQEMZ2V0U3BvdFByaWNlAAkBAXMBCQEOZ2V0T3JhY2xlUHJpY2UACQEBcwEFDnByZW1pdW1Ub1ZhdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEGNvbXB1dGVTcG90UHJpY2UABARzeW5jCQD8BwQFBHRoaXMCGXN5bmNUZXJtaW5hbFByaWNlVG9PcmFjbGUFA25pbAUDbmlsAwkAAAIFBHN5bmMFBHN5bmMEBnJlc3VsdAkBDGdldFNwb3RQcmljZQAJAJQKAgUDbmlsBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfY29tcHV0ZUZlZUZvclRyYWRlcldpdGhBcnRpZmFjdAIHX3RyYWRlcgtfYXJ0aWZhY3RJZAQGcmVzdWx0CQEYZ2V0Rm9yVHJhZGVyV2l0aEFydGlmYWN0AgUHX3RyYWRlcgULX2FydGlmYWN0SWQJAJQKAgUDbmlsBQZyZXN1bHQBAnR4AQZ2ZXJpZnkABA5jb29yZGluYXRvclN0cgkAnQgCBQR0aGlzBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwMJAQlpc0RlZmluZWQBBQ5jb29yZGluYXRvclN0cgQFYWRtaW4JAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUOY29vcmRpbmF0b3JTdHIFD2tfYWRtaW5fYWRkcmVzcwMJAQlpc0RlZmluZWQBBQVhZG1pbgkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBCQEFdmFsdWUBBQVhZG1pbgkArAICCQCsAgIJAKwCAgIHc3RhdHVzXwkApQgBBQR0aGlzAgFfCQDYBAEIBQJ0eAJpZAcJAAIBAi51bmFibGUgdG8gdmVyaWZ5OiBhZG1pbiBub3Qgc2V0IGluIGNvb3JkaW5hdG9yCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5ok7MVQ==", "height": 2554086, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: BpiEY6rsMhGhvFnGbbw8BCEqCrA2XNzgrgP5VdCGbZE3 Next: 9jPyGpEfNY87b8iuvDQQQhBpHyTHjcazBTCpj9a5uWEo Diff:
OldNewDifferences
345345 else DIR_LONG
346346
347347
348-func getPositionFee (_trader) = {
349- let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
348+func getPositionFee (_trader,_direction) = {
349+ let positionKey = ((_trader + "_") + toString(_direction))
350+ let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, positionKey))
350351 match positionFeeOpt {
351352 case positionFee: Int =>
352353 positionFee
424425 let amountBaseAssetBought = if (_isAdd)
425426 then amountBaseAssetBoughtAbs
426427 else -(amountBaseAssetBoughtAbs)
427- let $t01550515675 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
428- let quoteAssetReserveAfter1 = $t01550515675._1
429- let baseAssetReserveAfter1 = $t01550515675._2
430- let totalPositionSizeAfter1 = $t01550515675._3
428+ let $t01558615756 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
429+ let quoteAssetReserveAfter1 = $t01558615756._1
430+ let baseAssetReserveAfter1 = $t01558615756._2
431+ let totalPositionSizeAfter1 = $t01558615756._3
431432 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
432433 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
433434 let priceDiff = abs((priceBefore - marketPrice))
455456 else 0
456457 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
457458 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
458- let $t01834218469 = if ((0 > signedMargin))
459+ let $t01842318550 = if ((0 > signedMargin))
459460 then $Tuple2(0, abs(signedMargin))
460461 else $Tuple2(abs(signedMargin), 0)
461- let remainMargin = $t01834218469._1
462- let badDebt = $t01834218469._2
462+ let remainMargin = $t01842318550._1
463+ let badDebt = $t01842318550._2
463464 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
464465 }
465466
477478 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
478479 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
479480 let maxPriceImpactValue = maxPriceImpact()
480- let $t01973119893 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
481- let quoteAssetReserveAfter1 = $t01973119893._1
482- let baseAssetReserveAfter1 = $t01973119893._2
483- let totalPositionSizeAfter1 = $t01973119893._3
481+ let $t01981219974 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
482+ let quoteAssetReserveAfter1 = $t01981219974._1
483+ let baseAssetReserveAfter1 = $t01981219974._2
484+ let totalPositionSizeAfter1 = $t01981219974._3
484485 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
485486 let priceDiff = abs((priceBefore - marketPrice))
486487 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
615616
616617
617618 func getPositionNotionalAndUnrealizedPnl (_trader,_direction,_option) = {
618- let $t02778827928 = getPosition(_trader, _direction)
619- let positionSize = $t02778827928._1
620- let positionMargin = $t02778827928._2
621- let positionOpenNotional = $t02778827928._3
622- let positionLstUpdCPF = $t02778827928._4
619+ let $t02786928009 = getPosition(_trader, _direction)
620+ let positionSize = $t02786928009._1
621+ let positionMargin = $t02786928009._2
622+ let positionOpenNotional = $t02786928009._3
623+ let positionLstUpdCPF = $t02786928009._4
623624 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
624625 }
625626
628629
629630
630631 func getMarginRatioByOption (_trader,_direction,_option) = {
631- let $t02846028613 = getPosition(_trader, _direction)
632- let positionSize = $t02846028613._1
633- let positionMargin = $t02846028613._2
634- let pon = $t02846028613._3
635- let positionLastUpdatedCPF = $t02846028613._4
636- let positionTimestamp = $t02846028613._5
637- let $t02861928724 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, _option)
638- let positionNotional = $t02861928724._1
639- let unrealizedPnl = $t02861928724._2
640- let $t02872928941 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
641- let remainMargin = $t02872928941._1
642- let badDebt = $t02872928941._2
632+ let $t02854128694 = getPosition(_trader, _direction)
633+ let positionSize = $t02854128694._1
634+ let positionMargin = $t02854128694._2
635+ let pon = $t02854128694._3
636+ let positionLastUpdatedCPF = $t02854128694._4
637+ let positionTimestamp = $t02854128694._5
638+ let $t02870028805 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, _option)
639+ let positionNotional = $t02870028805._1
640+ let unrealizedPnl = $t02870028805._2
641+ let $t02881029022 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
642+ let remainMargin = $t02881029022._1
643+ let badDebt = $t02881029022._2
643644 calcMarginRatio(remainMargin, badDebt, positionNotional)
644645 }
645646
660661
661662
662663 func internalClosePosition (_trader,_direction,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
663- let $t03010430272 = getPosition(_trader, _direction)
664- let oldPositionSize = $t03010430272._1
665- let oldPositionMargin = $t03010430272._2
666- let oldPositionOpenNotional = $t03010430272._3
667- let oldPositionLstUpdCPF = $t03010430272._4
668- let oldPositionTimestamp = $t03010430272._5
664+ let $t03018530353 = getPosition(_trader, _direction)
665+ let oldPositionSize = $t03018530353._1
666+ let oldPositionMargin = $t03018530353._2
667+ let oldPositionOpenNotional = $t03018530353._3
668+ let oldPositionLstUpdCPF = $t03018530353._4
669+ let oldPositionTimestamp = $t03018530353._5
669670 let isLongPosition = (oldPositionSize > 0)
670671 let absOldPositionSize = abs(oldPositionSize)
671672 if (if ((absOldPositionSize >= _size))
673674 else false)
674675 then {
675676 let isPartialClose = (absOldPositionSize > _size)
676- let $t03056431015 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
677- let exchangedQuoteAssetAmount = $t03056431015._1
678- let quoteAssetReserveAfter = $t03056431015._2
679- let baseAssetReserveAfter = $t03056431015._3
680- let totalPositionSizeAfter = $t03056431015._4
677+ let $t03064531096 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
678+ let exchangedQuoteAssetAmount = $t03064531096._1
679+ let quoteAssetReserveAfter = $t03064531096._2
680+ let baseAssetReserveAfter = $t03064531096._3
681+ let totalPositionSizeAfter = $t03064531096._4
681682 let exchangedPositionSize = if ((oldPositionSize > 0))
682683 then -(_size)
683684 else _size
684- let $t03123031454 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
685- let oldPositionNotional = $t03123031454._1
686- let unrealizedPnl = $t03123031454._2
685+ let $t03131131535 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
686+ let oldPositionNotional = $t03131131535._1
687+ let unrealizedPnl = $t03131131535._2
687688 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
688689 let realizedPnl = muld(unrealizedPnl, realizedRatio)
689- let $t03179532041 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
690- let remainMarginBefore = $t03179532041._1
691- let x1 = $t03179532041._2
692- let x2 = $t03179532041._3
693- let rolloverFee = $t03179532041._4
690+ let $t03187632122 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
691+ let remainMarginBefore = $t03187632122._1
692+ let x1 = $t03187632122._2
693+ let x2 = $t03187632122._3
694+ let rolloverFee = $t03187632122._4
694695 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
695696 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
696697 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
698699 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
699700 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
700701 let newPositionSize = (oldPositionSize + exchangedPositionSize)
701- let $t03344733833 = if ((newPositionSize == 0))
702+ let $t03352833914 = if ((newPositionSize == 0))
702703 then $Tuple2(0, 0)
703704 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
704- let newPositionOpenNotional = $t03344733833._1
705- let newPositionLstUpdCPF = $t03344733833._2
705+ let newPositionOpenNotional = $t03352833914._1
706+ let newPositionLstUpdCPF = $t03352833914._2
706707 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
707708 let marginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
708709 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
745746 then $Tuple2(qtAstR(), bsAstR())
746747 else {
747748 let direction = (_positionSize > 0)
748- let $t03708037259 = swapOutput(direction, abs(_positionSize), false)
749- let currentNetMarketValue = $t03708037259._1
750- let terminalQuoteAssetReserve = $t03708037259._2
751- let terminalBaseAssetReserve = $t03708037259._3
749+ let $t03716137340 = swapOutput(direction, abs(_positionSize), false)
750+ let currentNetMarketValue = $t03716137340._1
751+ let terminalQuoteAssetReserve = $t03716137340._2
752+ let terminalBaseAssetReserve = $t03716137340._3
752753 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
753754 }
754755 }
831832 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
832833 let baseFeeRaw = fee()
833834 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
834- let $t04183442329 = if ((_artifactId != ""))
835+ let $t04191542410 = if ((_artifactId != ""))
835836 then {
836837 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
837838 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
843844 else throw("Invalid attached artifact")
844845 }
845846 else $Tuple2(baseFee, false)
846- let adjustedFee = $t04183442329._1
847- let burnArtifact = $t04183442329._2
847+ let adjustedFee = $t04191542410._1
848+ let burnArtifact = $t04191542410._2
848849 $Tuple2(adjustedFee, burnArtifact)
849850 }
850851
859860 case _ =>
860861 throw("Invalid computeFeeDiscount result")
861862 }
862- let $t04267542749 = getAdjustedFee(_artifactId, feeDiscount)
863- let adjustedFee = $t04267542749._1
864- let burnArtifact = $t04267542749._2
863+ let $t04275642830 = getAdjustedFee(_artifactId, feeDiscount)
864+ let adjustedFee = $t04275642830._1
865+ let burnArtifact = $t04275642830._2
865866 $Tuple2(adjustedFee, burnArtifact)
866867 }
867868 else throw("Strict value is not equal to itself.")
883884 }
884885
885886
886-func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread), IntegerEntry(k_maxOpenNotional, _maxOpenNotional), IntegerEntry(k_feeToStakersPercent, _feeToStakersPercent), IntegerEntry(k_maxOracleDelay, _feeToStakersPercent), IntegerEntry(k_rolloverFee, _rolloverFee), IntegerEntry(k_fundingMode, _fundingMode)]
887+func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread), IntegerEntry(k_maxOpenNotional, _maxOpenNotional), IntegerEntry(k_feeToStakersPercent, _feeToStakersPercent), IntegerEntry(k_maxOracleDelay, _maxOracleDelay), IntegerEntry(k_rolloverFee, _rolloverFee), IntegerEntry(k_fundingMode, _fundingMode)]
887888
888889
889890 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)]
9991000 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10001001 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10011002 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1002- let $t05100451155 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1003- let newQuoteAssetWeight = $t05100451155._1
1004- let newBaseAssetWeight = $t05100451155._2
1005- let marginToVault = $t05100451155._3
1003+ let $t05108051231 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1004+ let newQuoteAssetWeight = $t05108051231._1
1005+ let newBaseAssetWeight = $t05108051231._2
1006+ let marginToVault = $t05108051231._3
10061007 let doExchangePnL = if ((marginToVault != 0))
10071008 then {
10081009 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10321033 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10331034 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
10341035 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1035- let $t05225152402 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1036- let newQuoteAssetWeight = $t05225152402._1
1037- let newBaseAssetWeight = $t05225152402._2
1038- let marginToVault = $t05225152402._3
1036+ let $t05232752478 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1037+ let newQuoteAssetWeight = $t05232752478._1
1038+ let newBaseAssetWeight = $t05232752478._2
1039+ let marginToVault = $t05232752478._3
10391040 let doExchangePnL = if ((marginToVault != 0))
10401041 then {
10411042 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
11691170 else isMarketClosed())
11701171 then throw("Invalid increasePosition parameters")
11711172 else {
1172- let $t05847258621 = getForTraderWithArtifact(_trader, getArtifactId(i))
1173- let adjustedFee = $t05847258621._1
1174- let burnArtifact = $t05847258621._2
1173+ let $t05854858697 = getForTraderWithArtifact(_trader, getArtifactId(i))
1174+ let adjustedFee = $t05854858697._1
1175+ let burnArtifact = $t05854858697._2
11751176 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
11761177 let distributeFeeAmount = (_rawAmount - _amount)
11771178 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
11841185 throw("Invalid referrerFee")
11851186 }
11861187 let feeAmount = (distributeFeeAmount - referrerFee)
1187- let $t05911759297 = getPosition(_trader, _direction)
1188- let oldPositionSize = $t05911759297._1
1189- let oldPositionMargin = $t05911759297._2
1190- let oldPositionOpenNotional = $t05911759297._3
1191- let oldPositionLstUpdCPF = $t05911759297._4
1192- let oldPositionTimestamp = $t05911759297._5
1188+ let $t05919359373 = getPosition(_trader, _direction)
1189+ let oldPositionSize = $t05919359373._1
1190+ let oldPositionMargin = $t05919359373._2
1191+ let oldPositionOpenNotional = $t05919359373._3
1192+ let oldPositionLstUpdCPF = $t05919359373._4
1193+ let oldPositionTimestamp = $t05919359373._5
11931194 let isNewPosition = (oldPositionSize == 0)
11941195 let isSameDirection = if ((oldPositionSize > 0))
11951196 then (_direction == DIR_LONG)
11981199 then isSameDirection
11991200 else false
12001201 let isAdd = (_direction == DIR_LONG)
1201- let $t05958662719 = if (if (isNewPosition)
1202+ let $t05966262795 = if (if (isNewPosition)
12021203 then true
12031204 else expandExisting)
12041205 then {
12051206 let openNotional = muld(_amount, _leverage)
1206- let $t06009560268 = swapInput(isAdd, openNotional)
1207- let amountBaseAssetBought = $t06009560268._1
1208- let quoteAssetReserveAfter = $t06009560268._2
1209- let baseAssetReserveAfter = $t06009560268._3
1210- let totalPositionSizeAfter = $t06009560268._4
1207+ let $t06017160344 = swapInput(isAdd, openNotional)
1208+ let amountBaseAssetBought = $t06017160344._1
1209+ let quoteAssetReserveAfter = $t06017160344._2
1210+ let baseAssetReserveAfter = $t06017160344._3
1211+ let totalPositionSizeAfter = $t06017160344._4
12111212 if (if ((_minBaseAssetAmount != 0))
12121213 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12131214 else false)
12201221 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12211222 then openNotional
12221223 else 0))
1223- let $t06081461089 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1224- let remainMargin = $t06081461089._1
1225- let x1 = $t06081461089._2
1226- let x2 = $t06081461089._3
1227- let rolloverFee = $t06081461089._4
1224+ let $t06089061165 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1225+ let remainMargin = $t06089061165._1
1226+ let x1 = $t06089061165._2
1227+ let x2 = $t06089061165._3
1228+ let rolloverFee = $t06089061165._4
12281229 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12291230 then throw("Over max spread limit")
12301231 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12381239 }
12391240 else {
12401241 let openNotional = muld(_amount, _leverage)
1241- let $t06240762535 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1242- let oldPositionNotional = $t06240762535._1
1243- let unrealizedPnl = $t06240762535._2
1242+ let $t06248362611 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1243+ let oldPositionNotional = $t06248362611._1
1244+ let unrealizedPnl = $t06248362611._2
12441245 if ((oldPositionNotional > openNotional))
12451246 then throw("Use decreasePosition to decrease position size")
12461247 else throw("Close position first")
12471248 }
1248- let newPositionSize = $t05958662719._1
1249- let newPositionRemainMargin = $t05958662719._2
1250- let newPositionOpenNotional = $t05958662719._3
1251- let newPositionLatestCPF = $t05958662719._4
1252- let newPositionTimestamp = $t05958662719._5
1253- let baseAssetReserveAfter = $t05958662719._6
1254- let quoteAssetReserveAfter = $t05958662719._7
1255- let totalPositionSizeAfter = $t05958662719._8
1256- let openInterestNotionalAfter = $t05958662719._9
1257- let totalLongAfter = $t05958662719._10
1258- let totalShortAfter = $t05958662719._11
1259- let totalLongOpenInterestAfter = $t05958662719._12
1260- let totalShortOpenInterestAfter = $t05958662719._13
1261- let rolloverFee = $t05958662719._14
1262- let $t06272562796 = distributeFee((feeAmount + rolloverFee))
1263- let feeToStakers = $t06272562796._1
1264- let feeToVault = $t06272562796._2
1249+ let newPositionSize = $t05966262795._1
1250+ let newPositionRemainMargin = $t05966262795._2
1251+ let newPositionOpenNotional = $t05966262795._3
1252+ let newPositionLatestCPF = $t05966262795._4
1253+ let newPositionTimestamp = $t05966262795._5
1254+ let baseAssetReserveAfter = $t05966262795._6
1255+ let quoteAssetReserveAfter = $t05966262795._7
1256+ let totalPositionSizeAfter = $t05966262795._8
1257+ let openInterestNotionalAfter = $t05966262795._9
1258+ let totalLongAfter = $t05966262795._10
1259+ let totalShortAfter = $t05966262795._11
1260+ let totalLongOpenInterestAfter = $t05966262795._12
1261+ let totalShortOpenInterestAfter = $t05966262795._13
1262+ let rolloverFee = $t05966262795._14
1263+ let $t06280162872 = distributeFee((feeAmount + rolloverFee))
1264+ let feeToStakers = $t06280162872._1
1265+ let feeToVault = $t06280162872._2
12651266 let stake = if ((_amount >= rolloverFee))
12661267 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
12671268 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
13181319 else isMarketClosed())
13191320 then throw("Invalid addMargin parameters")
13201321 else {
1321- let $t06504365223 = getPosition(_trader, _direction)
1322- let oldPositionSize = $t06504365223._1
1323- let oldPositionMargin = $t06504365223._2
1324- let oldPositionOpenNotional = $t06504365223._3
1325- let oldPositionLstUpdCPF = $t06504365223._4
1326- let oldPositionTimestamp = $t06504365223._5
1322+ let $t06511965299 = getPosition(_trader, _direction)
1323+ let oldPositionSize = $t06511965299._1
1324+ let oldPositionMargin = $t06511965299._2
1325+ let oldPositionOpenNotional = $t06511965299._3
1326+ let oldPositionLstUpdCPF = $t06511965299._4
1327+ let oldPositionTimestamp = $t06511965299._5
13271328 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13281329 if ((stake == stake))
13291330 then {
13301331 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13311332 let doTransferFeeToStakers = if ((rolloverFee > 0))
13321333 then {
1333- let $t06550865567 = distributeFee(rolloverFee)
1334- let feeToStakers = $t06550865567._1
1335- let feeToVault = $t06550865567._2
1334+ let $t06558465643 = distributeFee(rolloverFee)
1335+ let feeToStakers = $t06558465643._1
1336+ let feeToVault = $t06558465643._2
13361337 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13371338 if ((unstake == unstake))
13381339 then {
13781379 else isMarketClosed())
13791380 then throw("Invalid removeMargin parameters")
13801381 else {
1381- let $t06697167151 = getPosition(_trader, _direction)
1382- let oldPositionSize = $t06697167151._1
1383- let oldPositionMargin = $t06697167151._2
1384- let oldPositionOpenNotional = $t06697167151._3
1385- let oldPositionLstUpdCPF = $t06697167151._4
1386- let oldPositionTimestamp = $t06697167151._5
1387- let $t06715767406 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1388- let remainMargin = $t06715767406._1
1389- let badDebt = $t06715767406._2
1390- let fundingPayment = $t06715767406._3
1391- let rolloverFee = $t06715767406._4
1382+ let $t06704767227 = getPosition(_trader, _direction)
1383+ let oldPositionSize = $t06704767227._1
1384+ let oldPositionMargin = $t06704767227._2
1385+ let oldPositionOpenNotional = $t06704767227._3
1386+ let oldPositionLstUpdCPF = $t06704767227._4
1387+ let oldPositionTimestamp = $t06704767227._5
1388+ let $t06723367482 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1389+ let remainMargin = $t06723367482._1
1390+ let badDebt = $t06723367482._2
1391+ let fundingPayment = $t06723367482._3
1392+ let rolloverFee = $t06723367482._4
13921393 if ((badDebt != 0))
13931394 then throw("Invalid removed margin amount")
13941395 else {
13961397 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
13971398 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
13981399 else {
1399- let $t06779267851 = distributeFee(rolloverFee)
1400- let feeToStakers = $t06779267851._1
1401- let feeToVault = $t06779267851._2
1400+ let $t06786867927 = distributeFee(rolloverFee)
1401+ let feeToStakers = $t06786867927._1
1402+ let feeToVault = $t06786867927._2
14021403 let doTransferFeeToStakers = if ((rolloverFee > 0))
14031404 then {
14041405 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14361437 then {
14371438 let _trader = getActualCaller(i)
14381439 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1439- let positionFee = getPositionFee(_trader)
1440+ let positionFee = getPositionFee(_trader, _direction)
14401441 if (if (if (if (if (if (!(requireOpenPosition(_trader, _direction)))
14411442 then true
14421443 else !(initialized()))
14511452 then throw("Invalid closePosition parameters")
14521453 else {
14531454 let oldPositionTimestamp = getPosition(_trader, _direction)._5
1454- let $t07006770670 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1455- let newPositionSize = $t07006770670._1
1456- let newPositionMargin = $t07006770670._2
1457- let newPositionOpenNotional = $t07006770670._3
1458- let newPositionLstUpdCPF = $t07006770670._4
1459- let positionBadDebt = $t07006770670._5
1460- let realizedPnl = $t07006770670._6
1461- let marginToTrader = $t07006770670._7
1462- let quoteAssetReserveAfter = $t07006770670._8
1463- let baseAssetReserveAfter = $t07006770670._9
1464- let totalPositionSizeAfter = $t07006770670._10
1465- let openInterestNotionalAfter = $t07006770670._11
1466- let totalLongAfter = $t07006770670._12
1467- let totalShortAfter = $t07006770670._13
1468- let totalLongOpenInterestAfter = $t07006770670._14
1469- let totalShortOpenInterestAfter = $t07006770670._15
1470- let realizedFee = $t07006770670._16
1455+ let $t07015570758 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1456+ let newPositionSize = $t07015570758._1
1457+ let newPositionMargin = $t07015570758._2
1458+ let newPositionOpenNotional = $t07015570758._3
1459+ let newPositionLstUpdCPF = $t07015570758._4
1460+ let positionBadDebt = $t07015570758._5
1461+ let realizedPnl = $t07015570758._6
1462+ let marginToTrader = $t07015570758._7
1463+ let quoteAssetReserveAfter = $t07015570758._8
1464+ let baseAssetReserveAfter = $t07015570758._9
1465+ let totalPositionSizeAfter = $t07015570758._10
1466+ let openInterestNotionalAfter = $t07015570758._11
1467+ let totalLongAfter = $t07015570758._12
1468+ let totalShortAfter = $t07015570758._13
1469+ let totalLongOpenInterestAfter = $t07015570758._14
1470+ let totalShortOpenInterestAfter = $t07015570758._15
1471+ let realizedFee = $t07015570758._16
14711472 if ((positionBadDebt > 0))
14721473 then throw("Invalid closePosition parameters: bad debt")
14731474 else if ((oldPositionTimestamp >= lastTimestamp()))
14911492 case _ =>
14921493 throw("Invalid referrerFee")
14931494 }
1494- let $t07164271715 = distributeFee((realizedFee - referrerFee))
1495- let feeToStakers = $t07164271715._1
1496- let feeToVault = $t07164271715._2
1495+ let $t07173071803 = distributeFee((realizedFee - referrerFee))
1496+ let feeToStakers = $t07173071803._1
1497+ let feeToVault = $t07173071803._2
14971498 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
14981499 if ((depositVault == depositVault))
14991500 then {
15561557 else false
15571558 let oldPositionSize = getPosition(_trader, _direction)._1
15581559 let positionSizeAbs = abs(oldPositionSize)
1559- let $t07421374536 = if (isPartialLiquidation)
1560+ let $t07430174624 = if (isPartialLiquidation)
15601561 then {
15611562 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
15621563 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
15631564 $Tuple2(liquidationRatio, abs(liquidationSize))
15641565 }
15651566 else $Tuple2(0, positionSizeAbs)
1566- let liquidationRatio = $t07421374536._1
1567- let liquidationSize = $t07421374536._2
1568- let $t07454275198 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
1567+ let liquidationRatio = $t07430174624._1
1568+ let liquidationSize = $t07430174624._2
1569+ let $t07463075286 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
15691570 then liquidationSize
15701571 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1571- let newPositionSize = $t07454275198._1
1572- let newPositionMargin = $t07454275198._2
1573- let newPositionOpenNotional = $t07454275198._3
1574- let newPositionLstUpdCPF = $t07454275198._4
1575- let positionBadDebt = $t07454275198._5
1576- let realizedPnl = $t07454275198._6
1577- let marginToTrader = $t07454275198._7
1578- let quoteAssetReserveAfter = $t07454275198._8
1579- let baseAssetReserveAfter = $t07454275198._9
1580- let totalPositionSizeAfter = $t07454275198._10
1581- let openInterestNotionalAfter = $t07454275198._11
1582- let totalLongAfter = $t07454275198._12
1583- let totalShortAfter = $t07454275198._13
1584- let totalLongOpenInterestAfter = $t07454275198._14
1585- let totalShortOpenInterestAfter = $t07454275198._15
1586- let liquidationPenalty = $t07454275198._16
1572+ let newPositionSize = $t07463075286._1
1573+ let newPositionMargin = $t07463075286._2
1574+ let newPositionOpenNotional = $t07463075286._3
1575+ let newPositionLstUpdCPF = $t07463075286._4
1576+ let positionBadDebt = $t07463075286._5
1577+ let realizedPnl = $t07463075286._6
1578+ let marginToTrader = $t07463075286._7
1579+ let quoteAssetReserveAfter = $t07463075286._8
1580+ let baseAssetReserveAfter = $t07463075286._9
1581+ let totalPositionSizeAfter = $t07463075286._10
1582+ let openInterestNotionalAfter = $t07463075286._11
1583+ let totalLongAfter = $t07463075286._12
1584+ let totalShortAfter = $t07463075286._13
1585+ let totalLongOpenInterestAfter = $t07463075286._14
1586+ let totalShortOpenInterestAfter = $t07463075286._15
1587+ let liquidationPenalty = $t07463075286._16
15871588 let feeToLiquidator = (liquidationPenalty / 2)
15881589 let feeToVault = (liquidationPenalty - feeToLiquidator)
15891590 let ammBalance = (cbalance() - liquidationPenalty)
16391640 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16401641 else {
16411642 let underlyingPrice = getOraclePrice()
1642- let $t07732377401 = getFunding()
1643- let shortPremiumFraction = $t07732377401._1
1644- let longPremiumFraction = $t07732377401._2
1645- let premiumToVault = $t07732377401._3
1643+ let $t07741177489 = getFunding()
1644+ let shortPremiumFraction = $t07741177489._1
1645+ let longPremiumFraction = $t07741177489._2
1646+ let premiumToVault = $t07741177489._3
16461647 let doPayFundingToVault = if ((premiumToVault > 0))
16471648 then {
16481649 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
16651666 func syncTerminalPriceToOracle () = {
16661667 let _qtAstR = qtAstR()
16671668 let _bsAstR = bsAstR()
1668- let $t07845478820 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1669- let newQuoteAssetWeight = $t07845478820._1
1670- let newBaseAssetWeight = $t07845478820._2
1671- let marginToVault = $t07845478820._3
1669+ let $t07854278908 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1670+ let newQuoteAssetWeight = $t07854278908._1
1671+ let newBaseAssetWeight = $t07854278908._2
1672+ let marginToVault = $t07854278908._3
16721673 let marginToVaultAdj = if (if ((0 > marginToVault))
16731674 then (abs(marginToVault) > cbalance())
16741675 else false)
17301731 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17311732 if ((sync == sync))
17321733 then {
1733- let $t08251182647 = getPosition(_trader, _direction)
1734- let positionSize = $t08251182647._1
1735- let positionMargin = $t08251182647._2
1736- let pon = $t08251182647._3
1737- let positionLstUpdCPF = $t08251182647._4
1738- let positionTimestamp = $t08251182647._5
1739- let $t08265082763 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1740- let positionNotional = $t08265082763._1
1741- let unrealizedPnl = $t08265082763._2
1742- let $t08276682990 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1743- let remainMargin = $t08276682990._1
1744- let badDebt = $t08276682990._2
1745- let fundingPayment = $t08276682990._3
1746- let rolloverFee = $t08276682990._4
1734+ let $t08259982735 = getPosition(_trader, _direction)
1735+ let positionSize = $t08259982735._1
1736+ let positionMargin = $t08259982735._2
1737+ let pon = $t08259982735._3
1738+ let positionLstUpdCPF = $t08259982735._4
1739+ let positionTimestamp = $t08259982735._5
1740+ let $t08273882851 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1741+ let positionNotional = $t08273882851._1
1742+ let unrealizedPnl = $t08273882851._2
1743+ let $t08285483078 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1744+ let remainMargin = $t08285483078._1
1745+ let badDebt = $t08285483078._2
1746+ let fundingPayment = $t08285483078._3
1747+ let rolloverFee = $t08285483078._4
17471748 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader, _direction))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17481749 }
17491750 else throw("Strict value is not equal to itself.")
17631764
17641765 @Callable(i)
17651766 func view_getTerminalAmmPrice () = {
1766- let $t08372583806 = getTerminalAmmState()
1767- let terminalQuoteAssetReserve = $t08372583806._1
1768- let terminalBaseAssetReserve = $t08372583806._2
1767+ let $t08381383894 = getTerminalAmmState()
1768+ let terminalQuoteAssetReserve = $t08381383894._1
1769+ let terminalBaseAssetReserve = $t08381383894._2
17691770 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17701771 throw(toString(price))
17711772 }
17781779 if ((sync == sync))
17791780 then {
17801781 let underlyingPrice = getOraclePrice()
1781- let $t08436584443 = getFunding()
1782- let shortPremiumFraction = $t08436584443._1
1783- let longPremiumFraction = $t08436584443._2
1784- let premiumToVault = $t08436584443._3
1782+ let $t08445384531 = getFunding()
1783+ let shortPremiumFraction = $t08445384531._1
1784+ let longPremiumFraction = $t08445384531._2
1785+ let premiumToVault = $t08445384531._3
17851786 let longFunding = divd(longPremiumFraction, underlyingPrice)
17861787 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17871788 throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_baseOracle = "k_baseOracle"
55
66 let k_quoteOracle = "k_quoteOracle"
77
88 let k_balance = "k_balance"
99
1010 let k_sequence = "k_sequence"
1111
1212 let k_positionSize = "k_positionSize"
1313
1414 let k_positionMargin = "k_positionMargin"
1515
1616 let k_positionOpenNotional = "k_positionOpenNotional"
1717
1818 let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
1919
2020 let k_positionSequence = "k_positionSequence"
2121
2222 let k_positionFee = "k_positionFee"
2323
2424 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2525
2626 let k_initialized = "k_initialized"
2727
2828 let k_paused = "k_paused"
2929
3030 let k_closeOnly = "k_closeOnly"
3131
3232 let k_fee = "k_fee"
3333
3434 let k_rolloverFee = "k_rollover_fee"
3535
3636 let k_fundingPeriod = "k_fundingPeriod"
3737
3838 let k_initMarginRatio = "k_initMarginRatio"
3939
4040 let k_maintenanceMarginRatio = "k_mmr"
4141
4242 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4343
4444 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4545
4646 let k_spreadLimit = "k_spreadLimit"
4747
4848 let k_maxPriceImpact = "k_maxPriceImpact"
4949
5050 let k_maxPriceSpread = "k_maxPriceSpread"
5151
5252 let k_maxOpenNotional = "k_maxOpenNotional"
5353
5454 let k_feeToStakersPercent = "k_feeToStakersPercent"
5555
5656 let k_maxOracleDelay = "k_maxOracleDelay"
5757
5858 let k_fundingMode = "k_fundingMode"
5959
6060 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
6161
6262 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
6363
6464 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
6565
6666 let k_longFundingRate = "k_longFundingRate"
6767
6868 let k_shortFundingRate = "k_shortFundingRate"
6969
7070 let k_quoteAssetReserve = "k_qtAstR"
7171
7272 let k_baseAssetReserve = "k_bsAstR"
7373
7474 let k_quoteAssetWeight = "k_qtAstW"
7575
7676 let k_baseAssetWeight = "k_bsAstW"
7777
7878 let k_totalPositionSize = "k_totalPositionSize"
7979
8080 let k_totalLongPositionSize = "k_totalLongPositionSize"
8181
8282 let k_totalShortPositionSize = "k_totalShortPositionSize"
8383
8484 let k_openInterestNotional = "k_openInterestNotional"
8585
8686 let k_openInterestShort = "k_openInterestShort"
8787
8888 let k_openInterestLong = "k_openInterestLong"
8989
9090 let k_lastTx = "k_lastTx"
9191
9292 let k_coordinatorAddress = "k_coordinatorAddress"
9393
9494 let k_vault_address = "k_vault_address"
9595
9696 let k_admin_address = "k_admin_address"
9797
9898 let k_quote_asset = "k_quote_asset"
9999
100100 let k_staking_address = "k_staking_address"
101101
102102 let k_miner_address = "k_miner_address"
103103
104104 let k_orders_address = "k_orders_address"
105105
106106 let k_referral_address = "k_referral_address"
107107
108108 let k_nft_manager_address = "k_nft_manager_address"
109109
110110 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
111111
112112
113113 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
114114
115115
116116 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
117117
118118
119119 func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
120120
121121
122122 func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Staking not set")
123123
124124
125125 func vaultAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_vault_address)), "Vault not set")
126126
127127
128128 func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Miner not set")
129129
130130
131131 func ordersAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_orders_address)), "Orders not set")
132132
133133
134134 func referralAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_referral_address)), "Referral not set")
135135
136136
137137 func nftManagerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_nft_manager_address)), "NFT Manager not set")
138138
139139
140140 let k_token_param = "k_token_param"
141141
142142 let k_token_type = "k_token_type"
143143
144144 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
145145
146146 let DIR_LONG = 1
147147
148148 let DIR_SHORT = 2
149149
150150 let SECONDS = 1000
151151
152152 let DECIMAL_NUMBERS = 6
153153
154154 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
155155
156156 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
157157
158158 let ONE_DAY = (86400 * DECIMAL_UNIT)
159159
160160 let PNL_OPTION_SPOT = 1
161161
162162 let PNL_OPTION_ORACLE = 2
163163
164164 let FUNDING_ASYMMETRIC = 1
165165
166166 let FUNDING_SYMMETRIC = 2
167167
168168 func s (_x) = (toString(_x) + ",")
169169
170170
171171 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
172172
173173
174174 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
175175
176176
177177 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
178178
179179
180180 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
181181
182182
183183 func abs (_x) = if ((_x > 0))
184184 then _x
185185 else -(_x)
186186
187187
188188 func vmax (_x,_y) = if ((_x >= _y))
189189 then _x
190190 else _y
191191
192192
193193 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
194194
195195
196196 func intOr (k,def) = valueOrElse(getInteger(this, k), def)
197197
198198
199199 func strA (_address,_key) = {
200200 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
201201 val
202202 }
203203
204204
205205 func intA (_address,_key) = {
206206 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
207207 val
208208 }
209209
210210
211211 func cbalance () = int(k_balance)
212212
213213
214214 func fee () = int(k_fee)
215215
216216
217217 func rolloverFeeRate () = int(k_rolloverFee)
218218
219219
220220 func initMarginRatio () = int(k_initMarginRatio)
221221
222222
223223 func qtAstR () = int(k_quoteAssetReserve)
224224
225225
226226 func bsAstR () = int(k_baseAssetReserve)
227227
228228
229229 func qtAstW () = intOr(k_quoteAssetWeight, DECIMAL_UNIT)
230230
231231
232232 func bsAstW () = intOr(k_baseAssetWeight, DECIMAL_UNIT)
233233
234234
235235 func totalPositionSize () = int(k_totalPositionSize)
236236
237237
238238 func openInterestNotional () = int(k_openInterestNotional)
239239
240240
241241 func openInterestShort () = int(k_openInterestShort)
242242
243243
244244 func openInterestLong () = int(k_openInterestLong)
245245
246246
247247 func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
248248
249249
250250 func fundingPeriodRaw () = int(k_fundingPeriod)
251251
252252
253253 func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
254254
255255
256256 func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
257257
258258
259259 func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
260260
261261
262262 func liquidationFeeRatio () = int(k_liquidationFeeRatio)
263263
264264
265265 func partialLiquidationRatio () = int(k_partialLiquidationRatio)
266266
267267
268268 func spreadLimit () = int(k_spreadLimit)
269269
270270
271271 func maxPriceImpact () = int(k_maxPriceImpact)
272272
273273
274274 func maxPriceSpread () = int(k_maxPriceSpread)
275275
276276
277277 func maxOpenNotional () = int(k_maxOpenNotional)
278278
279279
280280 func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
281281
282282
283283 func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
284284
285285
286286 func totalShortPositionSize () = int(k_totalShortPositionSize)
287287
288288
289289 func totalLongPositionSize () = int(k_totalLongPositionSize)
290290
291291
292292 func lastSequence () = intOr(k_sequence, 0)
293293
294294
295295 func feeToStakersPercent () = int(k_feeToStakersPercent)
296296
297297
298298 func maxOracleDelay () = int(k_maxOracleDelay)
299299
300300
301301 func fundingMode () = intOr(k_fundingMode, FUNDING_ASYMMETRIC)
302302
303303
304304 func lastTimestamp () = lastBlock.timestamp
305305
306306
307307 func getActualCaller (i) = valueOrElse(getString(ordersAddress(), "k_sender"), toString(i.caller))
308308
309309
310310 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
311311 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
312312 if (if (_largerThanOrEqualTo)
313313 then (0 > remainingMarginRatio)
314314 else false)
315315 then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
316316 else if (if (!(_largerThanOrEqualTo))
317317 then (remainingMarginRatio >= 0)
318318 else false)
319319 then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
320320 else true
321321 }
322322
323323
324324 func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
325325 then throw("Should not be called with _positionSize == 0")
326326 else if ((_positionSize > 0))
327327 then latestLongCumulativePremiumFraction()
328328 else latestShortCumulativePremiumFraction()
329329
330330
331331 func getPosition (_trader,_direction) = {
332332 let positionKey = ((_trader + "_") + toString(_direction))
333333 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, positionKey))
334334 match positionSizeOpt {
335335 case positionSize: Int =>
336336 $Tuple5(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, positionKey)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, positionKey)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedTimestamp, positionKey)))
337337 case _ =>
338338 $Tuple5(0, 0, 0, 0, 0)
339339 }
340340 }
341341
342342
343343 func getDirection (_positionSize) = if ((0 > _positionSize))
344344 then DIR_SHORT
345345 else DIR_LONG
346346
347347
348-func getPositionFee (_trader) = {
349- let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, _trader))
348+func getPositionFee (_trader,_direction) = {
349+ let positionKey = ((_trader + "_") + toString(_direction))
350+ let positionFeeOpt = getInteger(this, toCompositeKey(k_positionFee, positionKey))
350351 match positionFeeOpt {
351352 case positionFee: Int =>
352353 positionFee
353354 case _ =>
354355 fee()
355356 }
356357 }
357358
358359
359360 func requireOpenPosition (_trader,_direction) = if ((getPosition(_trader, _direction)._1 == 0))
360361 then throw("No open position")
361362 else true
362363
363364
364365 func getOracleData (key) = {
365366 let oracleDataStr = getString(this, key)
366367 if (if (isDefined(oracleDataStr))
367368 then (value(oracleDataStr) != "")
368369 else false)
369370 then {
370371 let oracleData = split(value(oracleDataStr), ",")
371372 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
372373 let priceKey = oracleData[1]
373374 let blockKey = oracleData[2]
374375 let openKey = oracleData[3]
375376 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
376377 }
377378 else unit
378379 }
379380
380381
381382 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
382383
383384
384385 func paused () = valueOrElse(getBoolean(this, k_paused), false)
385386
386387
387388 func closeOnly () = valueOrElse(getBoolean(this, k_closeOnly), false)
388389
389390
390391 func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
391392 then {
392393 let newBase = (bsAstR() - _baseAssetAmount)
393394 if ((0 >= newBase))
394395 then throw("Tx lead to base asset reserve <= 0, revert")
395396 else $Tuple3((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount))
396397 }
397398 else {
398399 let newQuote = (qtAstR() - _quoteAssetAmount)
399400 if ((0 >= newQuote))
400401 then throw("Tx lead to base quote reserve <= 0, revert")
401402 else $Tuple3(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount))
402403 }
403404
404405
405406 func calcInvariant (_qtAstR,_bsAstR) = {
406407 let bqtAstR = toBigInt(_qtAstR)
407408 let bbsAstR = toBigInt(_bsAstR)
408409 bmuld(bqtAstR, bbsAstR)
409410 }
410411
411412
412413 func swapInput (_isAdd,_quoteAssetAmount) = {
413414 let _qtAstR = qtAstR()
414415 let _bsAstR = bsAstR()
415416 let _qtAstW = qtAstW()
416417 let _bsAstW = bsAstW()
417418 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
418419 let k = calcInvariant(_qtAstR, _bsAstR)
419420 let quoteAssetReserveAfter = if (_isAdd)
420421 then (_qtAstR + quoteAssetAmountAdjusted)
421422 else (_qtAstR - quoteAssetAmountAdjusted)
422423 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
423424 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
424425 let amountBaseAssetBought = if (_isAdd)
425426 then amountBaseAssetBoughtAbs
426427 else -(amountBaseAssetBoughtAbs)
427- let $t01550515675 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
428- let quoteAssetReserveAfter1 = $t01550515675._1
429- let baseAssetReserveAfter1 = $t01550515675._2
430- let totalPositionSizeAfter1 = $t01550515675._3
428+ let $t01558615756 = updateReserve(_isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
429+ let quoteAssetReserveAfter1 = $t01558615756._1
430+ let baseAssetReserveAfter1 = $t01558615756._2
431+ let totalPositionSizeAfter1 = $t01558615756._3
431432 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
432433 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
433434 let priceDiff = abs((priceBefore - marketPrice))
434435 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
435436 let maxPriceImpactValue = maxPriceImpact()
436437 if ((priceImpact > maxPriceImpactValue))
437438 then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_qtAstR)) + " before base asset: ") + toString(_bsAstR)) + " quote asset amount to exchange: ") + toString(_quoteAssetAmount)) + " price before: ") + toString(priceBefore)) + " marketPrice: ") + toString(marketPrice)))
438439 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
439440 }
440441
441442
442443 func calcRolloverFee (_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
443444 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
444445 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate()), MINUTES_IN_YEAR)
445446 rolloverFee
446447 }
447448
448449
449450 func calcRemainMarginWithFundingPaymentAndRolloverFee (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
450451 let fundingPayment = if ((_oldPositionSize != 0))
451452 then {
452453 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
453454 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
454455 }
455456 else 0
456457 let rolloverFee = calcRolloverFee(_oldPositionMargin, _oldPositionLastUpdatedTimestamp)
457458 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
458- let $t01834218469 = if ((0 > signedMargin))
459+ let $t01842318550 = if ((0 > signedMargin))
459460 then $Tuple2(0, abs(signedMargin))
460461 else $Tuple2(abs(signedMargin), 0)
461- let remainMargin = $t01834218469._1
462- let badDebt = $t01834218469._2
462+ let remainMargin = $t01842318550._1
463+ let badDebt = $t01842318550._2
463464 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
464465 }
465466
466467
467468 func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
468469 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
469470 if ((_baseAssetAmount == 0))
470471 then throw("Invalid base asset amount")
471472 else {
472473 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
473474 let baseAssetPoolAmountAfter = if (_isAdd)
474475 then (_baseAssetReserve + _baseAssetAmount)
475476 else (_baseAssetReserve - _baseAssetAmount)
476477 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
477478 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
478479 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
479480 let maxPriceImpactValue = maxPriceImpact()
480- let $t01973119893 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
481- let quoteAssetReserveAfter1 = $t01973119893._1
482- let baseAssetReserveAfter1 = $t01973119893._2
483- let totalPositionSizeAfter1 = $t01973119893._3
481+ let $t01981219974 = updateReserve(!(_isAdd), quoteAssetDelta, _baseAssetAmount)
482+ let quoteAssetReserveAfter1 = $t01981219974._1
483+ let baseAssetReserveAfter1 = $t01981219974._2
484+ let totalPositionSizeAfter1 = $t01981219974._3
484485 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
485486 let priceDiff = abs((priceBefore - marketPrice))
486487 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
487488 if (if ((priceImpact > maxPriceImpactValue))
488489 then _checkMaxPriceImpact
489490 else false)
490491 then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_quoteAssetReserve)) + " before base asset: ") + toString(_baseAssetReserve)) + " base asset amount to exchange: ") + toString(_baseAssetAmount)) + " price before: ") + toString(priceBefore)) + " market price: ") + toString(marketPrice)))
491492 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize() - (if (_isAdd)
492493 then abs(_baseAssetAmount)
493494 else 0)), (totalShortPositionSize() - (if (!(_isAdd))
494495 then abs(_baseAssetAmount)
495496 else 0)), priceImpact)
496497 }
497498 }
498499
499500
500501 func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), qtAstW(), bsAstR(), bsAstW())
501502
502503
503504 func getOraclePriceValue (oracle,priceKey,blockKey) = {
504505 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
505506 if ((blockKey != ""))
506507 then {
507508 let currentBlock = lastBlock.height
508509 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
509510 if (((currentBlock - lastOracleBlock) > maxOracleDelay()))
510511 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
511512 else lastValue
512513 }
513514 else lastValue
514515 }
515516
516517
517518 func getOraclePrice () = {
518519 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
519520 let baseOraclePrice = getOraclePriceValue(baseOracle._1, baseOracle._2, baseOracle._3)
520521 let quoteOracle = getOracleData(k_quoteOracle)
521522 let quoteOraclePrice = if (isDefined(quoteOracle))
522523 then {
523524 let quoteOracleV = value(quoteOracle)
524525 getOraclePriceValue(quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
525526 }
526527 else DECIMAL_UNIT
527528 divd(baseOraclePrice, quoteOraclePrice)
528529 }
529530
530531
531532 func isMarketClosed () = {
532533 let baseOracle = valueOrErrorMessage(getOracleData(k_baseOracle), "No base asset oracle data")
533534 let oracle = baseOracle._1
534535 let openKey = baseOracle._4
535536 if ((openKey != ""))
536537 then {
537538 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
538539 !(isOpen)
539540 }
540541 else false
541542 }
542543
543544
544545 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
545546 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
546547 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
547548 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
548549 absPriceDiff
549550 }
550551
551552
552553 func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
553554 let oraclePrice = getOraclePrice()
554555 let _qtAstW = qtAstW()
555556 let _bsAstW = bsAstW()
556557 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(), bsAstR(), _qtAstW, _bsAstW)
557558 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
558559 if (if ((absPriceDiffAfter > maxPriceSpread()))
559560 then (absPriceDiffAfter > absPriceDiffBefore)
560561 else false)
561562 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread())))
562563 else true
563564 }
564565
565566
566567 func requireNotOverMaxOpenNotional (_longOpenNotional,_shortOpenNotional) = {
567568 let _maxOpenNotional = maxOpenNotional()
568569 if ((_longOpenNotional > _maxOpenNotional))
569570 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
570571 else if ((_shortOpenNotional > _maxOpenNotional))
571572 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
572573 else true
573574 }
574575
575576
576577 func getSpotPrice () = {
577578 let _quoteAssetReserve = qtAstR()
578579 let _baseAssetReserve = bsAstR()
579580 let _qtAstW = qtAstW()
580581 let _bsAstW = bsAstW()
581582 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
582583 }
583584
584585
585586 func isOverFluctuationLimit () = {
586587 let oraclePrice = getOraclePrice()
587588 let currentPrice = getSpotPrice()
588589 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
589590 }
590591
591592
592593 func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
593594 let positionSizeAbs = abs(_positionSize)
594595 let isShort = (0 > _positionSize)
595596 let positionNotional = if ((_option == PNL_OPTION_SPOT))
596597 then {
597598 let outPositionNotional = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
598599 outPositionNotional
599600 }
600601 else muld(positionSizeAbs, getOraclePrice())
601602 positionNotional
602603 }
603604
604605
605606 func getPositionNotionalAndUnrealizedPnlByValues (_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
606607 then throw("Invalid position size")
607608 else {
608609 let isShort = (0 > _positionSize)
609610 let positionNotional = getPositionAdjustedOpenNotional(_positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
610611 let unrealizedPnl = if (isShort)
611612 then (_positionOpenNotional - positionNotional)
612613 else (positionNotional - _positionOpenNotional)
613614 $Tuple2(positionNotional, unrealizedPnl)
614615 }
615616
616617
617618 func getPositionNotionalAndUnrealizedPnl (_trader,_direction,_option) = {
618- let $t02778827928 = getPosition(_trader, _direction)
619- let positionSize = $t02778827928._1
620- let positionMargin = $t02778827928._2
621- let positionOpenNotional = $t02778827928._3
622- let positionLstUpdCPF = $t02778827928._4
619+ let $t02786928009 = getPosition(_trader, _direction)
620+ let positionSize = $t02786928009._1
621+ let positionMargin = $t02786928009._2
622+ let positionOpenNotional = $t02786928009._3
623+ let positionLstUpdCPF = $t02786928009._4
623624 getPositionNotionalAndUnrealizedPnlByValues(positionSize, positionOpenNotional, qtAstR(), qtAstW(), bsAstR(), bsAstW(), _option)
624625 }
625626
626627
627628 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
628629
629630
630631 func getMarginRatioByOption (_trader,_direction,_option) = {
631- let $t02846028613 = getPosition(_trader, _direction)
632- let positionSize = $t02846028613._1
633- let positionMargin = $t02846028613._2
634- let pon = $t02846028613._3
635- let positionLastUpdatedCPF = $t02846028613._4
636- let positionTimestamp = $t02846028613._5
637- let $t02861928724 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, _option)
638- let positionNotional = $t02861928724._1
639- let unrealizedPnl = $t02861928724._2
640- let $t02872928941 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
641- let remainMargin = $t02872928941._1
642- let badDebt = $t02872928941._2
632+ let $t02854128694 = getPosition(_trader, _direction)
633+ let positionSize = $t02854128694._1
634+ let positionMargin = $t02854128694._2
635+ let pon = $t02854128694._3
636+ let positionLastUpdatedCPF = $t02854128694._4
637+ let positionTimestamp = $t02854128694._5
638+ let $t02870028805 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, _option)
639+ let positionNotional = $t02870028805._1
640+ let unrealizedPnl = $t02870028805._2
641+ let $t02881029022 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
642+ let remainMargin = $t02881029022._1
643+ let badDebt = $t02881029022._2
643644 calcMarginRatio(remainMargin, badDebt, positionNotional)
644645 }
645646
646647
647648 func getMarginRatio (_trader,_direction) = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
648649
649650
650651 func getPartialLiquidationAmount (_trader,_positionSize) = {
651652 let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader, getDirection(_positionSize)), maintenanceMarginRatio())))
652653 let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
653654 let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
654655 let maxExchangedQuoteAssetAmount = swapResult._1
655656 let priceImpact = swapResult._7
656657 if ((maxPriceImpact() > priceImpact))
657658 then maxExchangedPositionSize
658659 else muld(abs(_positionSize), partialLiquidationRatio())
659660 }
660661
661662
662663 func internalClosePosition (_trader,_direction,_size,_fee,_minQuoteAssetAmount,_addToMargin,_checkMaxPriceImpact,_liquidate) = {
663- let $t03010430272 = getPosition(_trader, _direction)
664- let oldPositionSize = $t03010430272._1
665- let oldPositionMargin = $t03010430272._2
666- let oldPositionOpenNotional = $t03010430272._3
667- let oldPositionLstUpdCPF = $t03010430272._4
668- let oldPositionTimestamp = $t03010430272._5
664+ let $t03018530353 = getPosition(_trader, _direction)
665+ let oldPositionSize = $t03018530353._1
666+ let oldPositionMargin = $t03018530353._2
667+ let oldPositionOpenNotional = $t03018530353._3
668+ let oldPositionLstUpdCPF = $t03018530353._4
669+ let oldPositionTimestamp = $t03018530353._5
669670 let isLongPosition = (oldPositionSize > 0)
670671 let absOldPositionSize = abs(oldPositionSize)
671672 if (if ((absOldPositionSize >= _size))
672673 then (_size > 0)
673674 else false)
674675 then {
675676 let isPartialClose = (absOldPositionSize > _size)
676- let $t03056431015 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
677- let exchangedQuoteAssetAmount = $t03056431015._1
678- let quoteAssetReserveAfter = $t03056431015._2
679- let baseAssetReserveAfter = $t03056431015._3
680- let totalPositionSizeAfter = $t03056431015._4
677+ let $t03064531096 = swapOutput((oldPositionSize > 0), _size, _checkMaxPriceImpact)
678+ let exchangedQuoteAssetAmount = $t03064531096._1
679+ let quoteAssetReserveAfter = $t03064531096._2
680+ let baseAssetReserveAfter = $t03064531096._3
681+ let totalPositionSizeAfter = $t03064531096._4
681682 let exchangedPositionSize = if ((oldPositionSize > 0))
682683 then -(_size)
683684 else _size
684- let $t03123031454 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
685- let oldPositionNotional = $t03123031454._1
686- let unrealizedPnl = $t03123031454._2
685+ let $t03131131535 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
686+ let oldPositionNotional = $t03131131535._1
687+ let unrealizedPnl = $t03131131535._2
687688 let realizedRatio = divd(abs(exchangedPositionSize), absOldPositionSize)
688689 let realizedPnl = muld(unrealizedPnl, realizedRatio)
689- let $t03179532041 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
690- let remainMarginBefore = $t03179532041._1
691- let x1 = $t03179532041._2
692- let x2 = $t03179532041._3
693- let rolloverFee = $t03179532041._4
690+ let $t03187632122 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, unrealizedPnl)
691+ let remainMarginBefore = $t03187632122._1
692+ let x1 = $t03187632122._2
693+ let x2 = $t03187632122._3
694+ let rolloverFee = $t03187632122._4
694695 let positionBadDebt = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, realizedPnl)._2
695696 let realizedCloseFee = muld(muld(oldPositionNotional, realizedRatio), _fee)
696697 let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
697698 let remainOpenNotional = if ((oldPositionSize > 0))
698699 then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
699700 else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
700701 let newPositionSize = (oldPositionSize + exchangedPositionSize)
701- let $t03344733833 = if ((newPositionSize == 0))
702+ let $t03352833914 = if ((newPositionSize == 0))
702703 then $Tuple2(0, 0)
703704 else $Tuple2(abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize))
704- let newPositionOpenNotional = $t03344733833._1
705- let newPositionLstUpdCPF = $t03344733833._2
705+ let newPositionOpenNotional = $t03352833914._1
706+ let newPositionLstUpdCPF = $t03352833914._2
706707 let openNotionalDelta = (oldPositionOpenNotional - newPositionOpenNotional)
707708 let marginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
708709 let newPositionMarginWithSameRatio = if ((oldPositionSize > 0))
709710 then (muld((newPositionOpenNotional + unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
710711 else (muld((newPositionOpenNotional - unrealizedPnlAfter), marginRatio) - unrealizedPnlAfter)
711712 let marginToTraderRaw = ((remainMarginBefore - (newPositionMarginWithSameRatio + unrealizedPnlAfter)) - realizedCloseFee)
712713 let marginToTrader = if ((0 > marginToTraderRaw))
713714 then if (_liquidate)
714715 then 0
715716 else throw("Invalid internalClosePosition params: unable to pay fee")
716717 else marginToTraderRaw
717718 let newPositionMargin = if (_addToMargin)
718719 then (newPositionMarginWithSameRatio + marginToTrader)
719720 else newPositionMarginWithSameRatio
720721 if (if ((_minQuoteAssetAmount != 0))
721722 then (_minQuoteAssetAmount > exchangedQuoteAssetAmount)
722723 else false)
723724 then throw(((("Limit error: " + toString(exchangedQuoteAssetAmount)) + " < ") + toString(_minQuoteAssetAmount)))
724725 else $Tuple17(newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, positionBadDebt, realizedPnl, if (if (_addToMargin)
725726 then isPartialClose
726727 else false)
727728 then 0
728729 else marginToTrader, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() - openNotionalDelta), (totalLongPositionSize() - (if (isLongPosition)
729730 then abs(exchangedPositionSize)
730731 else 0)), (totalShortPositionSize() - (if (!(isLongPosition))
731732 then abs(exchangedPositionSize)
732733 else 0)), (openInterestLong() - (if (isLongPosition)
733734 then openNotionalDelta
734735 else 0)), (openInterestShort() - (if (!(isLongPosition))
735736 then openNotionalDelta
736737 else 0)), (realizedCloseFee + rolloverFee), exchangedQuoteAssetAmount)
737738 }
738739 else throw(((("Invalid internalClosePosition params: invalid position size: " + toString(_size)) + " max: ") + toString(absOldPositionSize)))
739740 }
740741
741742
742743 func getTerminalAmmState () = {
743744 let _positionSize = totalPositionSize()
744745 if ((_positionSize == 0))
745746 then $Tuple2(qtAstR(), bsAstR())
746747 else {
747748 let direction = (_positionSize > 0)
748- let $t03708037259 = swapOutput(direction, abs(_positionSize), false)
749- let currentNetMarketValue = $t03708037259._1
750- let terminalQuoteAssetReserve = $t03708037259._2
751- let terminalBaseAssetReserve = $t03708037259._3
749+ let $t03716137340 = swapOutput(direction, abs(_positionSize), false)
750+ let currentNetMarketValue = $t03716137340._1
751+ let terminalQuoteAssetReserve = $t03716137340._2
752+ let terminalBaseAssetReserve = $t03716137340._3
752753 $Tuple2(terminalQuoteAssetReserve, terminalBaseAssetReserve)
753754 }
754755 }
755756
756757
757758 func getQuoteAssetWeight (baseAssetReserve,totalPositionSize,quoteAssetReserve,targetPrice) = {
758759 let b = toBigInt(baseAssetReserve)
759760 let sz = toBigInt(totalPositionSize)
760761 let q = toBigInt(quoteAssetReserve)
761762 let p = toBigInt(targetPrice)
762763 let k = bmuld(q, b)
763764 let newB = (b + sz)
764765 let newQ = bdivd(k, newB)
765766 let z = bdivd(newQ, newB)
766767 let result = bdivd(p, z)
767768 toInt(result)
768769 }
769770
770771
771772 func getSyncTerminalPrice (_terminalPrice,_qtAstR,_bsAstR) = {
772773 let _positionSize = totalPositionSize()
773774 if ((_positionSize == 0))
774775 then {
775776 let newQtAstW = divd(muld(_terminalPrice, _bsAstR), _qtAstR)
776777 $Tuple3(newQtAstW, DECIMAL_UNIT, 0)
777778 }
778779 else {
779780 let direction = (_positionSize > 0)
780781 let currentNetMarketValue = swapOutput(direction, abs(_positionSize), false)._1
781782 let newQtAstW = getQuoteAssetWeight(_bsAstR, _positionSize, _qtAstR, _terminalPrice)
782783 let newBsAstW = DECIMAL_UNIT
783784 let marginToVault = getPositionNotionalAndUnrealizedPnlByValues(_positionSize, currentNetMarketValue, _qtAstR, newQtAstW, _bsAstR, newBsAstW, PNL_OPTION_SPOT)._2
784785 $Tuple3(newQtAstW, newBsAstW, marginToVault)
785786 }
786787 }
787788
788789
789790 func getFunding () = {
790791 let underlyingPrice = getOraclePrice()
791792 let spotPrice = getSpotPrice()
792793 let premium = (spotPrice - underlyingPrice)
793794 if (if (if ((totalShortPositionSize() == 0))
794795 then true
795796 else (totalLongPositionSize() == 0))
796797 then true
797798 else isMarketClosed())
798799 then $Tuple3(0, 0, 0)
799800 else if ((0 > premium))
800801 then {
801802 let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
802803 if ((fundingMode() == FUNDING_ASYMMETRIC))
803804 then {
804805 let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
805806 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
806807 }
807808 else {
808809 let shortTotalPremiumFraction = abs(muld(shortPremiumFraction, totalShortPositionSize()))
809810 let longTotalPremiumFraction = abs(muld(shortPremiumFraction, totalLongPositionSize()))
810811 let premiumToVault = (shortTotalPremiumFraction - longTotalPremiumFraction)
811812 $Tuple3(shortPremiumFraction, shortPremiumFraction, premiumToVault)
812813 }
813814 }
814815 else {
815816 let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
816817 if ((fundingMode() == FUNDING_ASYMMETRIC))
817818 then {
818819 let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
819820 $Tuple3(shortPremiumFraction, longPremiumFraction, 0)
820821 }
821822 else {
822823 let longTotalPremiumFraction = abs(muld(longPremiumFraction, totalLongPositionSize()))
823824 let shortTotalPremiumFraction = abs(muld(longPremiumFraction, totalShortPositionSize()))
824825 let premiumToVault = (longTotalPremiumFraction - shortTotalPremiumFraction)
825826 $Tuple3(longPremiumFraction, longPremiumFraction, premiumToVault)
826827 }
827828 }
828829 }
829830
830831
831832 func getAdjustedFee (_artifactId,_baseFeeDiscount) = {
832833 let baseFeeRaw = fee()
833834 let baseFee = muld(baseFeeRaw, _baseFeeDiscount)
834- let $t04183442329 = if ((_artifactId != ""))
835+ let $t04191542410 = if ((_artifactId != ""))
835836 then {
836837 let artifactKind = strA(nftManagerAddress(), toCompositeKey(k_token_type, _artifactId))
837838 if ((artifactKind == FEE_REDUCTION_TOKEN_TYPE))
838839 then {
839840 let reduction = intA(nftManagerAddress(), toCompositeKey(k_token_param, _artifactId))
840841 let adjustedFee = muld(baseFee, reduction)
841842 $Tuple2(adjustedFee, true)
842843 }
843844 else throw("Invalid attached artifact")
844845 }
845846 else $Tuple2(baseFee, false)
846- let adjustedFee = $t04183442329._1
847- let burnArtifact = $t04183442329._2
847+ let adjustedFee = $t04191542410._1
848+ let burnArtifact = $t04191542410._2
848849 $Tuple2(adjustedFee, burnArtifact)
849850 }
850851
851852
852853 func getForTraderWithArtifact (_trader,_artifactId) = {
853854 let doGetFeeDiscount = invoke(minerAddress(), "computeFeeDiscount", [_trader], nil)
854855 if ((doGetFeeDiscount == doGetFeeDiscount))
855856 then {
856857 let feeDiscount = match doGetFeeDiscount {
857858 case x: Int =>
858859 x
859860 case _ =>
860861 throw("Invalid computeFeeDiscount result")
861862 }
862- let $t04267542749 = getAdjustedFee(_artifactId, feeDiscount)
863- let adjustedFee = $t04267542749._1
864- let burnArtifact = $t04267542749._2
863+ let $t04275642830 = getAdjustedFee(_artifactId, feeDiscount)
864+ let adjustedFee = $t04275642830._1
865+ let burnArtifact = $t04275642830._2
865866 $Tuple2(adjustedFee, burnArtifact)
866867 }
867868 else throw("Strict value is not equal to itself.")
868869 }
869870
870871
871872 func getArtifactId (i) = {
872873 let artifactId = if ((size(i.payments) > 1))
873874 then toBase58String(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifactId"))
874875 else ""
875876 artifactId
876877 }
877878
878879
879880 func distributeFee (_feeAmount) = {
880881 let feeToStakers = muld(_feeAmount, feeToStakersPercent())
881882 let feeToVault = (_feeAmount - feeToStakers)
882883 $Tuple2(feeToStakers, feeToVault)
883884 }
884885
885886
886-func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread), IntegerEntry(k_maxOpenNotional, _maxOpenNotional), IntegerEntry(k_feeToStakersPercent, _feeToStakersPercent), IntegerEntry(k_maxOracleDelay, _feeToStakersPercent), IntegerEntry(k_rolloverFee, _rolloverFee), IntegerEntry(k_fundingMode, _fundingMode)]
887+func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread), IntegerEntry(k_maxOpenNotional, _maxOpenNotional), IntegerEntry(k_feeToStakersPercent, _feeToStakersPercent), IntegerEntry(k_maxOracleDelay, _maxOracleDelay), IntegerEntry(k_rolloverFee, _rolloverFee), IntegerEntry(k_fundingMode, _fundingMode)]
887888
888889
889890 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)]
890891
891892
892893 func incrementPositionSequenceNumber (_isNewPosition,_trader,_direction) = {
893894 let positionKey = ((_trader + "_") + toString(_direction))
894895 if (_isNewPosition)
895896 then {
896897 let currentSequence = lastSequence()
897898 [IntegerEntry(toCompositeKey(k_positionSequence, positionKey), (currentSequence + 1)), IntegerEntry(k_sequence, (currentSequence + 1))]
898899 }
899900 else nil
900901 }
901902
902903
903904 func updatePositionFee (_isNewPosition,_trader,_direction,_fee) = {
904905 let positionKey = ((_trader + "_") + toString(_direction))
905906 if (_isNewPosition)
906907 then [IntegerEntry(toCompositeKey(k_positionFee, positionKey), _fee)]
907908 else nil
908909 }
909910
910911
911912 func updatePosition (_trader,_size,_margin,_openNotional,_latestCumulativePremiumFraction,_latestTimestamp) = {
912913 let direction = getDirection(_size)
913914 let positionKey = ((_trader + "_") + toString(direction))
914915 [IntegerEntry(toCompositeKey(k_positionSize, positionKey), _size), IntegerEntry(toCompositeKey(k_positionMargin, positionKey), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, positionKey), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey), _latestCumulativePremiumFraction), IntegerEntry(toCompositeKey(k_positionLastUpdatedTimestamp, positionKey), _latestTimestamp)]
915916 }
916917
917918
918919 func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
919920
920921
921922 func updateAmmWeights (_qtAstW,_bsAstW) = [IntegerEntry(k_quoteAssetWeight, _qtAstW), IntegerEntry(k_baseAssetWeight, _bsAstW)]
922923
923924
924925 func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize,_totalLongOpenNotional,_totalShortOpenNotional) = {
925926 let _qtAstW = qtAstW()
926927 let _bsAstW = bsAstW()
927928 if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
928929 then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
929930 else (updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize), IntegerEntry(k_openInterestLong, _totalLongOpenNotional), IntegerEntry(k_openInterestShort, _totalShortOpenNotional)])
930931 }
931932
932933
933934 func deletePosition (_trader,_direction) = {
934935 let positionKey = ((_trader + "_") + toString(_direction))
935936 [DeleteEntry(toCompositeKey(k_positionSize, positionKey)), DeleteEntry(toCompositeKey(k_positionMargin, positionKey)), DeleteEntry(toCompositeKey(k_positionOpenNotional, positionKey)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey)), DeleteEntry(toCompositeKey(k_positionFee, positionKey)), DeleteEntry(toCompositeKey(k_positionLastUpdatedTimestamp, positionKey))]
936937 }
937938
938939
939940 func withdraw (_address,_amount) = {
940941 let balance = assetBalance(this, quoteAsset())
941942 if ((_amount > balance))
942943 then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
943944 else [ScriptTransfer(_address, _amount, quoteAsset())]
944945 }
945946
946947
947948 func updateBalance (i) = if ((0 > i))
948949 then throw("Balance")
949950 else [IntegerEntry(k_balance, i)]
950951
951952
952953 func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
953954
954955
955956 func doBurnArtifact (_burnArtifact,i) = if (_burnArtifact)
956957 then [Burn(valueOrErrorMessage(i.payments[1].assetId, "Invalid artifact"), 1)]
957958 else nil
958959
959960
960961 @Callable(i)
961962 func pause () = if ((i.caller != adminAddress()))
962963 then throw("Invalid pause params")
963964 else [BooleanEntry(k_paused, true)]
964965
965966
966967
967968 @Callable(i)
968969 func unpause () = if ((i.caller != adminAddress()))
969970 then throw("Invalid unpause params")
970971 else [BooleanEntry(k_paused, false)]
971972
972973
973974
974975 @Callable(i)
975976 func setCloseOnly () = if ((i.caller != adminAddress()))
976977 then throw("Invalid setCloseOnly params")
977978 else [BooleanEntry(k_closeOnly, true)]
978979
979980
980981
981982 @Callable(i)
982983 func unsetCloseOnly () = if ((i.caller != adminAddress()))
983984 then throw("Invalid unsetCloseOnly params")
984985 else [BooleanEntry(k_closeOnly, false)]
985986
986987
987988
988989 @Callable(i)
989990 func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
990991 then true
991992 else (0 >= _quoteAssetAmount))
992993 then throw("Invalid addLiquidity params")
993994 else {
994995 let _qtAstR = qtAstR()
995996 let _bsAstR = bsAstR()
996997 let _qtAstW = qtAstW()
997998 let _bsAstW = bsAstW()
998999 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
9991000 let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
10001001 let baseAssetAmountToAdd = (divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR)
10011002 let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
1002- let $t05100451155 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1003- let newQuoteAssetWeight = $t05100451155._1
1004- let newBaseAssetWeight = $t05100451155._2
1005- let marginToVault = $t05100451155._3
1003+ let $t05108051231 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1004+ let newQuoteAssetWeight = $t05108051231._1
1005+ let newBaseAssetWeight = $t05108051231._2
1006+ let marginToVault = $t05108051231._3
10061007 let doExchangePnL = if ((marginToVault != 0))
10071008 then {
10081009 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10091010 if ((doExchangePnL == doExchangePnL))
10101011 then nil
10111012 else throw("Strict value is not equal to itself.")
10121013 }
10131014 else nil
10141015 if ((doExchangePnL == doExchangePnL))
10151016 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10161017 else throw("Strict value is not equal to itself.")
10171018 }
10181019
10191020
10201021
10211022 @Callable(i)
10221023 func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
10231024 then true
10241025 else (_quoteAssetAmount >= 0))
10251026 then throw("Invalid removeLiquidity params")
10261027 else {
10271028 let _qtAstR = qtAstR()
10281029 let _bsAstR = bsAstR()
10291030 let _qtAstW = qtAstW()
10301031 let _bsAstW = bsAstW()
10311032 let price = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
10321033 let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
10331034 let baseAssetAmountToRemove = abs((divd(muld(qtAstRAfter, _qtAstW), price) - _bsAstR))
10341035 let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
1035- let $t05225152402 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1036- let newQuoteAssetWeight = $t05225152402._1
1037- let newBaseAssetWeight = $t05225152402._2
1038- let marginToVault = $t05225152402._3
1036+ let $t05232752478 = getSyncTerminalPrice(getOraclePrice(), qtAstRAfter, bsAstRAfter)
1037+ let newQuoteAssetWeight = $t05232752478._1
1038+ let newBaseAssetWeight = $t05232752478._2
1039+ let marginToVault = $t05232752478._3
10391040 let doExchangePnL = if ((marginToVault != 0))
10401041 then {
10411042 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVault], nil)
10421043 if ((doExchangePnL == doExchangePnL))
10431044 then nil
10441045 else throw("Strict value is not equal to itself.")
10451046 }
10461047 else nil
10471048 if ((doExchangePnL == doExchangePnL))
10481049 then (updateAmmReserves(qtAstRAfter, bsAstRAfter) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
10491050 else throw("Strict value is not equal to itself.")
10501051 }
10511052
10521053
10531054
10541055 @Callable(i)
10551056 func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _fundingPeriod))
10561057 then true
10571058 else (0 >= _initMarginRatio))
10581059 then true
10591060 else (0 >= _mmr))
10601061 then true
10611062 else (0 >= _liquidationFeeRatio))
10621063 then true
10631064 else (0 >= _fee))
10641065 then true
10651066 else (0 >= _spreadLimit))
10661067 then true
10671068 else (0 >= _maxPriceImpact))
10681069 then true
10691070 else (0 >= _partialLiquidationRatio))
10701071 then true
10711072 else (0 >= _maxPriceSpread))
10721073 then true
10731074 else (0 >= _maxOpenNotional))
10741075 then true
10751076 else (0 >= _feeToStakersPercent))
10761077 then true
10771078 else (_feeToStakersPercent > DECIMAL_UNIT))
10781079 then true
10791080 else (0 >= _maxOracleDelay))
10801081 then true
10811082 else (0 >= _rolloverFee))
10821083 then true
10831084 else if ((_fundingMode != FUNDING_SYMMETRIC))
10841085 then (_fundingMode != FUNDING_ASYMMETRIC)
10851086 else false)
10861087 then true
10871088 else !(initialized()))
10881089 then true
10891090 else (i.caller != adminAddress()))
10901091 then throw("Invalid changeSettings params")
10911092 else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)
10921093
10931094
10941095
10951096 @Callable(i)
10961097 func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_baseOracleData,_quoteOracleData,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread,_maxOpenNotional,_feeToStakersPercent,_maxOracleDelay,_rolloverFee,_fundingMode) = if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
10971098 then true
10981099 else (0 >= _bsAstR))
10991100 then true
11001101 else (0 >= _fundingPeriod))
11011102 then true
11021103 else (0 >= _initMarginRatio))
11031104 then true
11041105 else (0 >= _mmr))
11051106 then true
11061107 else (0 >= _liquidationFeeRatio))
11071108 then true
11081109 else (0 >= _fee))
11091110 then true
11101111 else (0 >= _spreadLimit))
11111112 then true
11121113 else (0 >= _maxPriceImpact))
11131114 then true
11141115 else (0 >= _partialLiquidationRatio))
11151116 then true
11161117 else (0 >= _maxPriceSpread))
11171118 then true
11181119 else (0 >= _maxOpenNotional))
11191120 then true
11201121 else (0 >= _feeToStakersPercent))
11211122 then true
11221123 else (_feeToStakersPercent > DECIMAL_UNIT))
11231124 then true
11241125 else (0 >= _maxOracleDelay))
11251126 then true
11261127 else (0 >= _rolloverFee))
11271128 then true
11281129 else if ((_fundingMode != FUNDING_SYMMETRIC))
11291130 then (_fundingMode != FUNDING_ASYMMETRIC)
11301131 else false)
11311132 then true
11321133 else initialized())
11331134 then true
11341135 else (i.caller != this))
11351136 then throw("Invalid initialize parameters")
11361137 else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread, _maxOpenNotional, _feeToStakersPercent, _maxOracleDelay, _rolloverFee, _fundingMode)) ++ updateFunding((lastTimestamp() + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_baseOracle, _baseOracleData), StringEntry(k_quoteOracle, _quoteOracleData), StringEntry(k_coordinatorAddress, toString(addressFromStringValue(_coordinator)))])
11371138
11381139
11391140
11401141 @Callable(i)
11411142 func increasePosition (_direction,_leverage,_minBaseAssetAmount,_refLink) = {
11421143 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
11431144 if ((sync == sync))
11441145 then {
11451146 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
11461147 if ((ensureCalledOnce == ensureCalledOnce))
11471148 then {
11481149 let _trader = getActualCaller(i)
11491150 let _rawAmount = i.payments[0].amount
11501151 let _assetId = i.payments[0].assetId
11511152 let _assetIdStr = toBase58String(value(_assetId))
11521153 let isQuoteAsset = (_assetId == quoteAsset())
11531154 if (if (if (if (if (if (if (if (if ((_direction != DIR_LONG))
11541155 then (_direction != DIR_SHORT)
11551156 else false)
11561157 then true
11571158 else (0 >= _rawAmount))
11581159 then true
11591160 else !(initialized()))
11601161 then true
11611162 else !(isQuoteAsset))
11621163 then true
11631164 else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
11641165 then true
11651166 else paused())
11661167 then true
11671168 else closeOnly())
11681169 then true
11691170 else isMarketClosed())
11701171 then throw("Invalid increasePosition parameters")
11711172 else {
1172- let $t05847258621 = getForTraderWithArtifact(_trader, getArtifactId(i))
1173- let adjustedFee = $t05847258621._1
1174- let burnArtifact = $t05847258621._2
1173+ let $t05854858697 = getForTraderWithArtifact(_trader, getArtifactId(i))
1174+ let adjustedFee = $t05854858697._1
1175+ let burnArtifact = $t05854858697._2
11751176 let _amount = divd(_rawAmount, (muld(adjustedFee, _leverage) + DECIMAL_UNIT))
11761177 let distributeFeeAmount = (_rawAmount - _amount)
11771178 let referrerFeeAny = invoke(referralAddress(), "acceptPaymentWithLink", [_trader, _refLink], [AttachedPayment(quoteAsset(), distributeFeeAmount)])
11781179 if ((referrerFeeAny == referrerFeeAny))
11791180 then {
11801181 let referrerFee = match referrerFeeAny {
11811182 case x: Int =>
11821183 x
11831184 case _ =>
11841185 throw("Invalid referrerFee")
11851186 }
11861187 let feeAmount = (distributeFeeAmount - referrerFee)
1187- let $t05911759297 = getPosition(_trader, _direction)
1188- let oldPositionSize = $t05911759297._1
1189- let oldPositionMargin = $t05911759297._2
1190- let oldPositionOpenNotional = $t05911759297._3
1191- let oldPositionLstUpdCPF = $t05911759297._4
1192- let oldPositionTimestamp = $t05911759297._5
1188+ let $t05919359373 = getPosition(_trader, _direction)
1189+ let oldPositionSize = $t05919359373._1
1190+ let oldPositionMargin = $t05919359373._2
1191+ let oldPositionOpenNotional = $t05919359373._3
1192+ let oldPositionLstUpdCPF = $t05919359373._4
1193+ let oldPositionTimestamp = $t05919359373._5
11931194 let isNewPosition = (oldPositionSize == 0)
11941195 let isSameDirection = if ((oldPositionSize > 0))
11951196 then (_direction == DIR_LONG)
11961197 else (_direction == DIR_SHORT)
11971198 let expandExisting = if (!(isNewPosition))
11981199 then isSameDirection
11991200 else false
12001201 let isAdd = (_direction == DIR_LONG)
1201- let $t05958662719 = if (if (isNewPosition)
1202+ let $t05966262795 = if (if (isNewPosition)
12021203 then true
12031204 else expandExisting)
12041205 then {
12051206 let openNotional = muld(_amount, _leverage)
1206- let $t06009560268 = swapInput(isAdd, openNotional)
1207- let amountBaseAssetBought = $t06009560268._1
1208- let quoteAssetReserveAfter = $t06009560268._2
1209- let baseAssetReserveAfter = $t06009560268._3
1210- let totalPositionSizeAfter = $t06009560268._4
1207+ let $t06017160344 = swapInput(isAdd, openNotional)
1208+ let amountBaseAssetBought = $t06017160344._1
1209+ let quoteAssetReserveAfter = $t06017160344._2
1210+ let baseAssetReserveAfter = $t06017160344._3
1211+ let totalPositionSizeAfter = $t06017160344._4
12111212 if (if ((_minBaseAssetAmount != 0))
12121213 then (_minBaseAssetAmount > abs(amountBaseAssetBought))
12131214 else false)
12141215 then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
12151216 else {
12161217 let newPositionSize = (oldPositionSize + amountBaseAssetBought)
12171218 let totalLongOpenInterestAfter = (openInterestLong() + (if ((newPositionSize > 0))
12181219 then openNotional
12191220 else 0))
12201221 let totalShortOpenInterestAfter = (openInterestShort() + (if ((0 > newPositionSize))
12211222 then openNotional
12221223 else 0))
1223- let $t06081461089 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1224- let remainMargin = $t06081461089._1
1225- let x1 = $t06081461089._2
1226- let x2 = $t06081461089._3
1227- let rolloverFee = $t06081461089._4
1224+ let $t06089061165 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, _amount)
1225+ let remainMargin = $t06089061165._1
1226+ let x1 = $t06089061165._2
1227+ let x2 = $t06089061165._3
1228+ let rolloverFee = $t06089061165._4
12281229 if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
12291230 then throw("Over max spread limit")
12301231 else if (!(requireNotOverMaxOpenNotional(totalLongOpenInterestAfter, totalShortOpenInterestAfter)))
12311232 then throw("Over max open notional")
12321233 else $Tuple14(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), lastTimestamp(), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
12331234 then abs(amountBaseAssetBought)
12341235 else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
12351236 then abs(amountBaseAssetBought)
12361237 else 0)), totalLongOpenInterestAfter, totalShortOpenInterestAfter, rolloverFee)
12371238 }
12381239 }
12391240 else {
12401241 let openNotional = muld(_amount, _leverage)
1241- let $t06240762535 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1242- let oldPositionNotional = $t06240762535._1
1243- let unrealizedPnl = $t06240762535._2
1242+ let $t06248362611 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), _direction, PNL_OPTION_SPOT)
1243+ let oldPositionNotional = $t06248362611._1
1244+ let unrealizedPnl = $t06248362611._2
12441245 if ((oldPositionNotional > openNotional))
12451246 then throw("Use decreasePosition to decrease position size")
12461247 else throw("Close position first")
12471248 }
1248- let newPositionSize = $t05958662719._1
1249- let newPositionRemainMargin = $t05958662719._2
1250- let newPositionOpenNotional = $t05958662719._3
1251- let newPositionLatestCPF = $t05958662719._4
1252- let newPositionTimestamp = $t05958662719._5
1253- let baseAssetReserveAfter = $t05958662719._6
1254- let quoteAssetReserveAfter = $t05958662719._7
1255- let totalPositionSizeAfter = $t05958662719._8
1256- let openInterestNotionalAfter = $t05958662719._9
1257- let totalLongAfter = $t05958662719._10
1258- let totalShortAfter = $t05958662719._11
1259- let totalLongOpenInterestAfter = $t05958662719._12
1260- let totalShortOpenInterestAfter = $t05958662719._13
1261- let rolloverFee = $t05958662719._14
1262- let $t06272562796 = distributeFee((feeAmount + rolloverFee))
1263- let feeToStakers = $t06272562796._1
1264- let feeToVault = $t06272562796._2
1249+ let newPositionSize = $t05966262795._1
1250+ let newPositionRemainMargin = $t05966262795._2
1251+ let newPositionOpenNotional = $t05966262795._3
1252+ let newPositionLatestCPF = $t05966262795._4
1253+ let newPositionTimestamp = $t05966262795._5
1254+ let baseAssetReserveAfter = $t05966262795._6
1255+ let quoteAssetReserveAfter = $t05966262795._7
1256+ let totalPositionSizeAfter = $t05966262795._8
1257+ let openInterestNotionalAfter = $t05966262795._9
1258+ let totalLongAfter = $t05966262795._10
1259+ let totalShortAfter = $t05966262795._11
1260+ let totalLongOpenInterestAfter = $t05966262795._12
1261+ let totalShortOpenInterestAfter = $t05966262795._13
1262+ let rolloverFee = $t05966262795._14
1263+ let $t06280162872 = distributeFee((feeAmount + rolloverFee))
1264+ let feeToStakers = $t06280162872._1
1265+ let feeToVault = $t06280162872._2
12651266 let stake = if ((_amount >= rolloverFee))
12661267 then invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), (_amount - rolloverFee))])
12671268 else invoke(vaultAddress(), "withdrawLocked", [(rolloverFee - _amount)], nil)
12681269 if ((stake == stake))
12691270 then {
12701271 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
12711272 if ((depositVault == depositVault))
12721273 then {
12731274 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, feeAmount], nil)
12741275 if ((notifyFee == notifyFee))
12751276 then {
12761277 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
12771278 if ((notifyNotional == notifyNotional))
12781279 then ((((((updatePosition(_trader, newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF, newPositionTimestamp) ++ incrementPositionSequenceNumber(isNewPosition, _trader, _direction)) ++ updatePositionFee(isNewPosition, _trader, _direction, adjustedFee)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ transferFee(feeToStakers)) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doBurnArtifact(burnArtifact, i))
12791280 else throw("Strict value is not equal to itself.")
12801281 }
12811282 else throw("Strict value is not equal to itself.")
12821283 }
12831284 else throw("Strict value is not equal to itself.")
12841285 }
12851286 else throw("Strict value is not equal to itself.")
12861287 }
12871288 else throw("Strict value is not equal to itself.")
12881289 }
12891290 }
12901291 else throw("Strict value is not equal to itself.")
12911292 }
12921293 else throw("Strict value is not equal to itself.")
12931294 }
12941295
12951296
12961297
12971298 @Callable(i)
12981299 func addMargin (_direction) = {
12991300 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13001301 if ((sync == sync))
13011302 then {
13021303 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13031304 if ((ensureCalledOnce == ensureCalledOnce))
13041305 then {
13051306 let _trader = toString(i.caller)
13061307 let _amount = i.payments[0].amount
13071308 let _assetId = i.payments[0].assetId
13081309 let _assetIdStr = toBase58String(value(_assetId))
13091310 let isQuoteAsset = (_assetId == quoteAsset())
13101311 if (if (if (if (if (!(isQuoteAsset))
13111312 then true
13121313 else !(requireOpenPosition(toString(i.caller), _direction)))
13131314 then true
13141315 else !(initialized()))
13151316 then true
13161317 else paused())
13171318 then true
13181319 else isMarketClosed())
13191320 then throw("Invalid addMargin parameters")
13201321 else {
1321- let $t06504365223 = getPosition(_trader, _direction)
1322- let oldPositionSize = $t06504365223._1
1323- let oldPositionMargin = $t06504365223._2
1324- let oldPositionOpenNotional = $t06504365223._3
1325- let oldPositionLstUpdCPF = $t06504365223._4
1326- let oldPositionTimestamp = $t06504365223._5
1322+ let $t06511965299 = getPosition(_trader, _direction)
1323+ let oldPositionSize = $t06511965299._1
1324+ let oldPositionMargin = $t06511965299._2
1325+ let oldPositionOpenNotional = $t06511965299._3
1326+ let oldPositionLstUpdCPF = $t06511965299._4
1327+ let oldPositionTimestamp = $t06511965299._5
13271328 let stake = invoke(vaultAddress(), "addLocked", nil, [AttachedPayment(quoteAsset(), _amount)])
13281329 if ((stake == stake))
13291330 then {
13301331 let rolloverFee = calcRolloverFee(oldPositionMargin, oldPositionTimestamp)
13311332 let doTransferFeeToStakers = if ((rolloverFee > 0))
13321333 then {
1333- let $t06550865567 = distributeFee(rolloverFee)
1334- let feeToStakers = $t06550865567._1
1335- let feeToVault = $t06550865567._2
1334+ let $t06558465643 = distributeFee(rolloverFee)
1335+ let feeToStakers = $t06558465643._1
1336+ let feeToVault = $t06558465643._2
13361337 let unstake = invoke(vaultAddress(), "withdrawLocked", [feeToStakers], nil)
13371338 if ((unstake == unstake))
13381339 then {
13391340 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
13401341 if ((lockBadDebt == lockBadDebt))
13411342 then transferFee(feeToStakers)
13421343 else throw("Strict value is not equal to itself.")
13431344 }
13441345 else throw("Strict value is not equal to itself.")
13451346 }
13461347 else nil
13471348 if ((doTransferFeeToStakers == doTransferFeeToStakers))
13481349 then ((updatePosition(_trader, oldPositionSize, ((oldPositionMargin - rolloverFee) + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF, lastTimestamp()) ++ updateBalance(((cbalance() + _amount) - rolloverFee))) ++ doTransferFeeToStakers)
13491350 else throw("Strict value is not equal to itself.")
13501351 }
13511352 else throw("Strict value is not equal to itself.")
13521353 }
13531354 }
13541355 else throw("Strict value is not equal to itself.")
13551356 }
13561357 else throw("Strict value is not equal to itself.")
13571358 }
13581359
13591360
13601361
13611362 @Callable(i)
13621363 func removeMargin (_amount,_direction) = {
13631364 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
13641365 if ((sync == sync))
13651366 then {
13661367 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
13671368 if ((ensureCalledOnce == ensureCalledOnce))
13681369 then {
13691370 let _trader = toString(i.caller)
13701371 if (if (if (if (if ((0 >= _amount))
13711372 then true
13721373 else !(requireOpenPosition(_trader, _direction)))
13731374 then true
13741375 else !(initialized()))
13751376 then true
13761377 else paused())
13771378 then true
13781379 else isMarketClosed())
13791380 then throw("Invalid removeMargin parameters")
13801381 else {
1381- let $t06697167151 = getPosition(_trader, _direction)
1382- let oldPositionSize = $t06697167151._1
1383- let oldPositionMargin = $t06697167151._2
1384- let oldPositionOpenNotional = $t06697167151._3
1385- let oldPositionLstUpdCPF = $t06697167151._4
1386- let oldPositionTimestamp = $t06697167151._5
1387- let $t06715767406 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1388- let remainMargin = $t06715767406._1
1389- let badDebt = $t06715767406._2
1390- let fundingPayment = $t06715767406._3
1391- let rolloverFee = $t06715767406._4
1382+ let $t06704767227 = getPosition(_trader, _direction)
1383+ let oldPositionSize = $t06704767227._1
1384+ let oldPositionMargin = $t06704767227._2
1385+ let oldPositionOpenNotional = $t06704767227._3
1386+ let oldPositionLstUpdCPF = $t06704767227._4
1387+ let oldPositionTimestamp = $t06704767227._5
1388+ let $t06723367482 = calcRemainMarginWithFundingPaymentAndRolloverFee(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, oldPositionTimestamp, -(_amount))
1389+ let remainMargin = $t06723367482._1
1390+ let badDebt = $t06723367482._2
1391+ let fundingPayment = $t06723367482._3
1392+ let rolloverFee = $t06723367482._4
13921393 if ((badDebt != 0))
13931394 then throw("Invalid removed margin amount")
13941395 else {
13951396 let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
13961397 if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
13971398 then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
13981399 else {
1399- let $t06779267851 = distributeFee(rolloverFee)
1400- let feeToStakers = $t06779267851._1
1401- let feeToVault = $t06779267851._2
1400+ let $t06786867927 = distributeFee(rolloverFee)
1401+ let feeToStakers = $t06786867927._1
1402+ let feeToVault = $t06786867927._2
14021403 let doTransferFeeToStakers = if ((rolloverFee > 0))
14031404 then {
14041405 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(feeToVault)], nil)
14051406 if ((lockBadDebt == lockBadDebt))
14061407 then transferFee(feeToStakers)
14071408 else throw("Strict value is not equal to itself.")
14081409 }
14091410 else nil
14101411 if ((doTransferFeeToStakers == doTransferFeeToStakers))
14111412 then {
14121413 let unstake = invoke(vaultAddress(), "withdrawLocked", [(_amount + feeToStakers)], nil)
14131414 if ((unstake == unstake))
14141415 then (((updatePosition(_trader, oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize), lastTimestamp()) ++ withdraw(i.caller, _amount)) ++ updateBalance(((cbalance() - _amount) - rolloverFee))) ++ doTransferFeeToStakers)
14151416 else throw("Strict value is not equal to itself.")
14161417 }
14171418 else throw("Strict value is not equal to itself.")
14181419 }
14191420 }
14201421 }
14211422 }
14221423 else throw("Strict value is not equal to itself.")
14231424 }
14241425 else throw("Strict value is not equal to itself.")
14251426 }
14261427
14271428
14281429
14291430 @Callable(i)
14301431 func closePosition (_size,_direction,_minQuoteAssetAmount,_addToMargin) = {
14311432 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
14321433 if ((sync == sync))
14331434 then {
14341435 let ensureCalledOnce = invoke(this, "ensureCalledOnce", nil, nil)
14351436 if ((ensureCalledOnce == ensureCalledOnce))
14361437 then {
14371438 let _trader = getActualCaller(i)
14381439 let _traderAddress = valueOrErrorMessage(addressFromString(_trader), "Invalid caller")
1439- let positionFee = getPositionFee(_trader)
1440+ let positionFee = getPositionFee(_trader, _direction)
14401441 if (if (if (if (if (if (!(requireOpenPosition(_trader, _direction)))
14411442 then true
14421443 else !(initialized()))
14431444 then true
14441445 else paused())
14451446 then true
14461447 else (0 >= _size))
14471448 then true
14481449 else (0 > _minQuoteAssetAmount))
14491450 then true
14501451 else isMarketClosed())
14511452 then throw("Invalid closePosition parameters")
14521453 else {
14531454 let oldPositionTimestamp = getPosition(_trader, _direction)._5
1454- let $t07006770670 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1455- let newPositionSize = $t07006770670._1
1456- let newPositionMargin = $t07006770670._2
1457- let newPositionOpenNotional = $t07006770670._3
1458- let newPositionLstUpdCPF = $t07006770670._4
1459- let positionBadDebt = $t07006770670._5
1460- let realizedPnl = $t07006770670._6
1461- let marginToTrader = $t07006770670._7
1462- let quoteAssetReserveAfter = $t07006770670._8
1463- let baseAssetReserveAfter = $t07006770670._9
1464- let totalPositionSizeAfter = $t07006770670._10
1465- let openInterestNotionalAfter = $t07006770670._11
1466- let totalLongAfter = $t07006770670._12
1467- let totalShortAfter = $t07006770670._13
1468- let totalLongOpenInterestAfter = $t07006770670._14
1469- let totalShortOpenInterestAfter = $t07006770670._15
1470- let realizedFee = $t07006770670._16
1455+ let $t07015570758 = internalClosePosition(_trader, _direction, _size, positionFee, _minQuoteAssetAmount, _addToMargin, true, true)
1456+ let newPositionSize = $t07015570758._1
1457+ let newPositionMargin = $t07015570758._2
1458+ let newPositionOpenNotional = $t07015570758._3
1459+ let newPositionLstUpdCPF = $t07015570758._4
1460+ let positionBadDebt = $t07015570758._5
1461+ let realizedPnl = $t07015570758._6
1462+ let marginToTrader = $t07015570758._7
1463+ let quoteAssetReserveAfter = $t07015570758._8
1464+ let baseAssetReserveAfter = $t07015570758._9
1465+ let totalPositionSizeAfter = $t07015570758._10
1466+ let openInterestNotionalAfter = $t07015570758._11
1467+ let totalLongAfter = $t07015570758._12
1468+ let totalShortAfter = $t07015570758._13
1469+ let totalLongOpenInterestAfter = $t07015570758._14
1470+ let totalShortOpenInterestAfter = $t07015570758._15
1471+ let realizedFee = $t07015570758._16
14711472 if ((positionBadDebt > 0))
14721473 then throw("Invalid closePosition parameters: bad debt")
14731474 else if ((oldPositionTimestamp >= lastTimestamp()))
14741475 then throw("Invalid closePosition parameters: wait at least 1 block before closing the position")
14751476 else {
14761477 let isPartialClose = (newPositionSize != 0)
14771478 let withdrawAmount = (marginToTrader + realizedFee)
14781479 let ammBalance = (cbalance() - withdrawAmount)
14791480 let ammNewBalance = if ((0 > ammBalance))
14801481 then 0
14811482 else ammBalance
14821483 let unstake = invoke(vaultAddress(), "withdrawLocked", [withdrawAmount], nil)
14831484 if ((unstake == unstake))
14841485 then {
14851486 let referrerFeeAny = invoke(referralAddress(), "acceptPayment", [_trader], [AttachedPayment(quoteAsset(), realizedFee)])
14861487 if ((referrerFeeAny == referrerFeeAny))
14871488 then {
14881489 let referrerFee = match referrerFeeAny {
14891490 case x: Int =>
14901491 x
14911492 case _ =>
14921493 throw("Invalid referrerFee")
14931494 }
1494- let $t07164271715 = distributeFee((realizedFee - referrerFee))
1495- let feeToStakers = $t07164271715._1
1496- let feeToVault = $t07164271715._2
1495+ let $t07173071803 = distributeFee((realizedFee - referrerFee))
1496+ let feeToStakers = $t07173071803._1
1497+ let feeToVault = $t07173071803._2
14971498 let depositVault = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
14981499 if ((depositVault == depositVault))
14991500 then {
15001501 let notifyFee = invoke(minerAddress(), "notifyFees", [_trader, realizedFee], nil)
15011502 if ((notifyFee == notifyFee))
15021503 then {
15031504 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
15041505 if ((notifyNotional == notifyNotional))
15051506 then (((((if (isPartialClose)
15061507 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
15071508 else deletePosition(_trader, _direction)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ (if ((marginToTrader > 0))
15081509 then withdraw(_traderAddress, marginToTrader)
15091510 else nil)) ++ updateBalance(ammNewBalance)) ++ transferFee(feeToStakers))
15101511 else throw("Strict value is not equal to itself.")
15111512 }
15121513 else throw("Strict value is not equal to itself.")
15131514 }
15141515 else throw("Strict value is not equal to itself.")
15151516 }
15161517 else throw("Strict value is not equal to itself.")
15171518 }
15181519 else throw("Strict value is not equal to itself.")
15191520 }
15201521 }
15211522 }
15221523 else throw("Strict value is not equal to itself.")
15231524 }
15241525 else throw("Strict value is not equal to itself.")
15251526 }
15261527
15271528
15281529
15291530 @Callable(i)
15301531 func liquidate (_trader,_direction) = {
15311532 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
15321533 if ((sync == sync))
15331534 then {
15341535 let spotMarginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_SPOT)
15351536 let liquidationMarginRatio = if (isOverFluctuationLimit())
15361537 then {
15371538 let oracleMarginRatio = getMarginRatioByOption(_trader, _direction, PNL_OPTION_ORACLE)
15381539 vmax(spotMarginRatio, oracleMarginRatio)
15391540 }
15401541 else spotMarginRatio
15411542 if (if (if (if (if (!(requireMoreMarginRatio(liquidationMarginRatio, maintenanceMarginRatio(), false)))
15421543 then true
15431544 else !(requireOpenPosition(_trader, _direction)))
15441545 then true
15451546 else !(initialized()))
15461547 then true
15471548 else paused())
15481549 then true
15491550 else isMarketClosed())
15501551 then throw("Unable to liquidate")
15511552 else {
15521553 let isPartialLiquidation = if (if ((spotMarginRatio > liquidationFeeRatio()))
15531554 then (partialLiquidationRatio() > 0)
15541555 else false)
15551556 then (DECIMAL_UNIT > partialLiquidationRatio())
15561557 else false
15571558 let oldPositionSize = getPosition(_trader, _direction)._1
15581559 let positionSizeAbs = abs(oldPositionSize)
1559- let $t07421374536 = if (isPartialLiquidation)
1560+ let $t07430174624 = if (isPartialLiquidation)
15601561 then {
15611562 let liquidationSize = getPartialLiquidationAmount(_trader, oldPositionSize)
15621563 let liquidationRatio = divd(abs(liquidationSize), positionSizeAbs)
15631564 $Tuple2(liquidationRatio, abs(liquidationSize))
15641565 }
15651566 else $Tuple2(0, positionSizeAbs)
1566- let liquidationRatio = $t07421374536._1
1567- let liquidationSize = $t07421374536._2
1568- let $t07454275198 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
1567+ let liquidationRatio = $t07430174624._1
1568+ let liquidationSize = $t07430174624._2
1569+ let $t07463075286 = internalClosePosition(_trader, _direction, if (isPartialLiquidation)
15691570 then liquidationSize
15701571 else positionSizeAbs, liquidationFeeRatio(), 0, true, false, true)
1571- let newPositionSize = $t07454275198._1
1572- let newPositionMargin = $t07454275198._2
1573- let newPositionOpenNotional = $t07454275198._3
1574- let newPositionLstUpdCPF = $t07454275198._4
1575- let positionBadDebt = $t07454275198._5
1576- let realizedPnl = $t07454275198._6
1577- let marginToTrader = $t07454275198._7
1578- let quoteAssetReserveAfter = $t07454275198._8
1579- let baseAssetReserveAfter = $t07454275198._9
1580- let totalPositionSizeAfter = $t07454275198._10
1581- let openInterestNotionalAfter = $t07454275198._11
1582- let totalLongAfter = $t07454275198._12
1583- let totalShortAfter = $t07454275198._13
1584- let totalLongOpenInterestAfter = $t07454275198._14
1585- let totalShortOpenInterestAfter = $t07454275198._15
1586- let liquidationPenalty = $t07454275198._16
1572+ let newPositionSize = $t07463075286._1
1573+ let newPositionMargin = $t07463075286._2
1574+ let newPositionOpenNotional = $t07463075286._3
1575+ let newPositionLstUpdCPF = $t07463075286._4
1576+ let positionBadDebt = $t07463075286._5
1577+ let realizedPnl = $t07463075286._6
1578+ let marginToTrader = $t07463075286._7
1579+ let quoteAssetReserveAfter = $t07463075286._8
1580+ let baseAssetReserveAfter = $t07463075286._9
1581+ let totalPositionSizeAfter = $t07463075286._10
1582+ let openInterestNotionalAfter = $t07463075286._11
1583+ let totalLongAfter = $t07463075286._12
1584+ let totalShortAfter = $t07463075286._13
1585+ let totalLongOpenInterestAfter = $t07463075286._14
1586+ let totalShortOpenInterestAfter = $t07463075286._15
1587+ let liquidationPenalty = $t07463075286._16
15871588 let feeToLiquidator = (liquidationPenalty / 2)
15881589 let feeToVault = (liquidationPenalty - feeToLiquidator)
15891590 let ammBalance = (cbalance() - liquidationPenalty)
15901591 let newAmmBalance = if ((0 > ammBalance))
15911592 then 0
15921593 else ammBalance
15931594 let lockBadDebt = if ((positionBadDebt > 0))
15941595 then {
15951596 let lockBadDebt = invoke(vaultAddress(), "exchangeFreeAndLocked", [(positionBadDebt + liquidationPenalty)], nil)
15961597 if ((lockBadDebt == lockBadDebt))
15971598 then nil
15981599 else throw("Strict value is not equal to itself.")
15991600 }
16001601 else nil
16011602 if ((lockBadDebt == lockBadDebt))
16021603 then {
16031604 let unstake = invoke(vaultAddress(), "withdrawLocked", [liquidationPenalty], nil)
16041605 if ((unstake == unstake))
16051606 then {
16061607 let depositInsurance = invoke(vaultAddress(), "addFree", nil, [AttachedPayment(quoteAsset(), feeToVault)])
16071608 if ((depositInsurance == depositInsurance))
16081609 then {
16091610 let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
16101611 if ((notifyNotional == notifyNotional))
16111612 then ((((if (isPartialLiquidation)
16121613 then updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF, lastTimestamp())
16131614 else deletePosition(_trader, _direction)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter, totalLongOpenInterestAfter, totalShortOpenInterestAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
16141615 else throw("Strict value is not equal to itself.")
16151616 }
16161617 else throw("Strict value is not equal to itself.")
16171618 }
16181619 else throw("Strict value is not equal to itself.")
16191620 }
16201621 else throw("Strict value is not equal to itself.")
16211622 }
16221623 }
16231624 else throw("Strict value is not equal to itself.")
16241625 }
16251626
16261627
16271628
16281629 @Callable(i)
16291630 func payFunding () = {
16301631 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
16311632 if ((sync == sync))
16321633 then {
16331634 let fundingBlockTimestamp = nextFundingBlockTimestamp()
16341635 if (if (if ((fundingBlockTimestamp > lastTimestamp()))
16351636 then true
16361637 else !(initialized()))
16371638 then true
16381639 else paused())
16391640 then throw(((("Invalid funding block timestamp: " + toString(lastTimestamp())) + " < ") + toString(fundingBlockTimestamp)))
16401641 else {
16411642 let underlyingPrice = getOraclePrice()
1642- let $t07732377401 = getFunding()
1643- let shortPremiumFraction = $t07732377401._1
1644- let longPremiumFraction = $t07732377401._2
1645- let premiumToVault = $t07732377401._3
1643+ let $t07741177489 = getFunding()
1644+ let shortPremiumFraction = $t07741177489._1
1645+ let longPremiumFraction = $t07741177489._2
1646+ let premiumToVault = $t07741177489._3
16461647 let doPayFundingToVault = if ((premiumToVault > 0))
16471648 then {
16481649 let doPayFundingToVault = invoke(vaultAddress(), "exchangeFreeAndLocked", [-(premiumToVault)], nil)
16491650 if ((doPayFundingToVault == doPayFundingToVault))
16501651 then nil
16511652 else throw("Strict value is not equal to itself.")
16521653 }
16531654 else nil
16541655 if ((doPayFundingToVault == doPayFundingToVault))
16551656 then updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
16561657 else throw("Strict value is not equal to itself.")
16571658 }
16581659 }
16591660 else throw("Strict value is not equal to itself.")
16601661 }
16611662
16621663
16631664
16641665 @Callable(i)
16651666 func syncTerminalPriceToOracle () = {
16661667 let _qtAstR = qtAstR()
16671668 let _bsAstR = bsAstR()
1668- let $t07845478820 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1669- let newQuoteAssetWeight = $t07845478820._1
1670- let newBaseAssetWeight = $t07845478820._2
1671- let marginToVault = $t07845478820._3
1669+ let $t07854278908 = getSyncTerminalPrice(getOraclePrice(), _qtAstR, _bsAstR)
1670+ let newQuoteAssetWeight = $t07854278908._1
1671+ let newBaseAssetWeight = $t07854278908._2
1672+ let marginToVault = $t07854278908._3
16721673 let marginToVaultAdj = if (if ((0 > marginToVault))
16731674 then (abs(marginToVault) > cbalance())
16741675 else false)
16751676 then -(cbalance())
16761677 else marginToVault
16771678 let doExchangePnL = if ((marginToVaultAdj != 0))
16781679 then {
16791680 let doExchangePnL = invoke(vaultAddress(), "exchangeFreeAndLocked", [marginToVaultAdj], nil)
16801681 if ((doExchangePnL == doExchangePnL))
16811682 then nil
16821683 else throw("Strict value is not equal to itself.")
16831684 }
16841685 else nil
16851686 if ((doExchangePnL == doExchangePnL))
16861687 then (updateBalance((cbalance() + marginToVaultAdj)) ++ updateAmmWeights(newQuoteAssetWeight, newBaseAssetWeight))
16871688 else throw("Strict value is not equal to itself.")
16881689 }
16891690
16901691
16911692
16921693 @Callable(i)
16931694 func ensureCalledOnce () = if ((i.caller != this))
16941695 then throw("Invalid saveCurrentTxId parameters")
16951696 else {
16961697 let txId = toBase58String(i.transactionId)
16971698 let lastTx = valueOrElse(getString(this, k_lastTx), "")
16981699 if ((lastTx != txId))
16991700 then [StringEntry(k_lastTx, txId)]
17001701 else throw("Can not call vAMM methods twice in one tx")
17011702 }
17021703
17031704
17041705
17051706 @Callable(i)
17061707 func migratePosition (_trader) = {
17071708 let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
17081709 if (if (isDefined(positionSizeOpt))
17091710 then isDefined(addressFromString(_trader))
17101711 else false)
17111712 then {
17121713 let pSize = getIntegerValue(this, toCompositeKey(k_positionSize, _trader))
17131714 let pMargin = getIntegerValue(this, toCompositeKey(k_positionMargin, _trader))
17141715 let pNotional = getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader))
17151716 let pFraction = getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader))
17161717 let pTimestamp = valueOrElse(getInteger(this, toCompositeKey(k_positionLastUpdatedTimestamp, _trader)), lastBlock.timestamp)
17171718 let pFee = valueOrElse(getInteger(this, toCompositeKey(k_positionFee, _trader)), fee())
17181719 let pSequence = getIntegerValue(this, toCompositeKey(k_positionSequence, _trader))
17191720 let pDirection = getDirection(pSize)
17201721 let positionKey = ((_trader + "_") + toString(pDirection))
17211722 [DeleteEntry(toCompositeKey(k_positionSize, _trader)), DeleteEntry(toCompositeKey(k_positionMargin, _trader)), DeleteEntry(toCompositeKey(k_positionOpenNotional, _trader)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)), DeleteEntry(toCompositeKey(k_positionLastUpdatedTimestamp, _trader)), DeleteEntry(toCompositeKey(k_positionFee, _trader)), DeleteEntry(toCompositeKey(k_positionSequence, _trader)), IntegerEntry(toCompositeKey(k_positionSize, positionKey), pSize), IntegerEntry(toCompositeKey(k_positionMargin, positionKey), pMargin), IntegerEntry(toCompositeKey(k_positionOpenNotional, positionKey), pNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, positionKey), pFraction), IntegerEntry(toCompositeKey(k_positionLastUpdatedTimestamp, positionKey), pTimestamp), IntegerEntry(toCompositeKey(k_positionFee, positionKey), pFee), IntegerEntry(toCompositeKey(k_positionSequence, positionKey), pSequence)]
17221723 }
17231724 else throw(("Nothing to migrate for " + _trader))
17241725 }
17251726
17261727
17271728
17281729 @Callable(i)
17291730 func view_calcRemainMarginWithFundingPayment (_trader,_direction) = {
17301731 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17311732 if ((sync == sync))
17321733 then {
1733- let $t08251182647 = getPosition(_trader, _direction)
1734- let positionSize = $t08251182647._1
1735- let positionMargin = $t08251182647._2
1736- let pon = $t08251182647._3
1737- let positionLstUpdCPF = $t08251182647._4
1738- let positionTimestamp = $t08251182647._5
1739- let $t08265082763 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1740- let positionNotional = $t08265082763._1
1741- let unrealizedPnl = $t08265082763._2
1742- let $t08276682990 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1743- let remainMargin = $t08276682990._1
1744- let badDebt = $t08276682990._2
1745- let fundingPayment = $t08276682990._3
1746- let rolloverFee = $t08276682990._4
1734+ let $t08259982735 = getPosition(_trader, _direction)
1735+ let positionSize = $t08259982735._1
1736+ let positionMargin = $t08259982735._2
1737+ let pon = $t08259982735._3
1738+ let positionLstUpdCPF = $t08259982735._4
1739+ let positionTimestamp = $t08259982735._5
1740+ let $t08273882851 = getPositionNotionalAndUnrealizedPnl(_trader, _direction, PNL_OPTION_SPOT)
1741+ let positionNotional = $t08273882851._1
1742+ let unrealizedPnl = $t08273882851._2
1743+ let $t08285483078 = calcRemainMarginWithFundingPaymentAndRolloverFee(positionSize, positionMargin, positionLstUpdCPF, positionTimestamp, unrealizedPnl)
1744+ let remainMargin = $t08285483078._1
1745+ let badDebt = $t08285483078._2
1746+ let fundingPayment = $t08285483078._3
1747+ let rolloverFee = $t08285483078._4
17471748 throw(((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader, _direction))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)) + s(rolloverFee)))
17481749 }
17491750 else throw("Strict value is not equal to itself.")
17501751 }
17511752
17521753
17531754
17541755 @Callable(i)
17551756 func view_getPegAdjustCost (_price) = {
17561757 let _qtAstR = qtAstR()
17571758 let _bsAstR = bsAstR()
17581759 let result = getSyncTerminalPrice(_price, _qtAstR, _bsAstR)
17591760 throw(toString(result._3))
17601761 }
17611762
17621763
17631764
17641765 @Callable(i)
17651766 func view_getTerminalAmmPrice () = {
1766- let $t08372583806 = getTerminalAmmState()
1767- let terminalQuoteAssetReserve = $t08372583806._1
1768- let terminalBaseAssetReserve = $t08372583806._2
1767+ let $t08381383894 = getTerminalAmmState()
1768+ let terminalQuoteAssetReserve = $t08381383894._1
1769+ let terminalBaseAssetReserve = $t08381383894._2
17691770 let price = divd(muld(terminalQuoteAssetReserve, qtAstW()), muld(terminalBaseAssetReserve, bsAstW()))
17701771 throw(toString(price))
17711772 }
17721773
17731774
17741775
17751776 @Callable(i)
17761777 func view_getFunding () = {
17771778 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17781779 if ((sync == sync))
17791780 then {
17801781 let underlyingPrice = getOraclePrice()
1781- let $t08436584443 = getFunding()
1782- let shortPremiumFraction = $t08436584443._1
1783- let longPremiumFraction = $t08436584443._2
1784- let premiumToVault = $t08436584443._3
1782+ let $t08445384531 = getFunding()
1783+ let shortPremiumFraction = $t08445384531._1
1784+ let longPremiumFraction = $t08445384531._2
1785+ let premiumToVault = $t08445384531._3
17851786 let longFunding = divd(longPremiumFraction, underlyingPrice)
17861787 let shortFunding = divd(shortPremiumFraction, underlyingPrice)
17871788 throw(((((s(longFunding) + s(shortFunding)) + s(getSpotPrice())) + s(getOraclePrice())) + s(premiumToVault)))
17881789 }
17891790 else throw("Strict value is not equal to itself.")
17901791 }
17911792
17921793
17931794
17941795 @Callable(i)
17951796 func computeSpotPrice () = {
17961797 let sync = invoke(this, "syncTerminalPriceToOracle", nil, nil)
17971798 if ((sync == sync))
17981799 then {
17991800 let result = getSpotPrice()
18001801 $Tuple2(nil, result)
18011802 }
18021803 else throw("Strict value is not equal to itself.")
18031804 }
18041805
18051806
18061807
18071808 @Callable(i)
18081809 func computeFeeForTraderWithArtifact (_trader,_artifactId) = {
18091810 let result = getForTraderWithArtifact(_trader, _artifactId)
18101811 $Tuple2(nil, result)
18111812 }
18121813
18131814
18141815 @Verifier(tx)
18151816 func verify () = {
18161817 let coordinatorStr = getString(this, k_coordinatorAddress)
18171818 if (isDefined(coordinatorStr))
18181819 then {
18191820 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
18201821 if (isDefined(admin))
18211822 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
18221823 else throw("unable to verify: admin not set in coordinator")
18231824 }
18241825 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
18251826 }
18261827

github/deemru/w8io/026f985 
2392.39 ms