tx · BxLd2gxpKcBtngG9WzTXBqb8UDrB3pLvQkpxK7fUC2Rc

3PBYExCMcqwN9R8aD7Wpf3yZ4WVLqFm8zRU:  -0.02100000 Waves

2023.02.18 16:25 [3520690] smart account 3PBYExCMcqwN9R8aD7Wpf3yZ4WVLqFm8zRU > SELF 0.00000000 Waves

{ "type": 13, "id": "BxLd2gxpKcBtngG9WzTXBqb8UDrB3pLvQkpxK7fUC2Rc", "fee": 2100000, "feeAssetId": null, "timestamp": 1676726791532, "version": 1, "sender": "3PBYExCMcqwN9R8aD7Wpf3yZ4WVLqFm8zRU", "senderPublicKey": "BYoHZ4bxnPJHfn7XyY794fQz3ZecR54uS8ZKV6dn7FTZ", "proofs": [ "2Ze716VV26b9KL5C89QVs2hQirDTMceD6SwHkF6ydCGTGuAKJtvFbYwHJ9i83E3T12aN92v7fN5xS2Vj2jctCL1S" ], "script": "base64:BgICCAKmAQAMa19iYXNlT3JhY2xlAgxrX2Jhc2VPcmFjbGUADWtfcXVvdGVPcmFjbGUCDWtfcXVvdGVPcmFjbGUACWtfYmFsYW5jZQIJa19iYWxhbmNlAAprX3NlcXVlbmNlAgprX3NlcXVlbmNlAA5rX3Bvc2l0aW9uU2l6ZQIOa19wb3NpdGlvblNpemUAEGtfcG9zaXRpb25NYXJnaW4CEGtfcG9zaXRpb25NYXJnaW4AFmtfcG9zaXRpb25PcGVuTm90aW9uYWwCFmtfcG9zaXRpb25PcGVuTm90aW9uYWwALmtfcG9zaXRpb25MYXN0VXBkYXRlZEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CEmtfcG9zaXRpb25GcmFjdGlvbgASa19wb3NpdGlvblNlcXVlbmNlAhJrX3Bvc2l0aW9uU2VxdWVuY2UAD2tfcG9zaXRpb25Bc3NldAIPa19wb3NpdGlvbkFzc2V0AA1rX3Bvc2l0aW9uRmVlAg1rX3Bvc2l0aW9uRmVlAB5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXACE2tfcG9zaXRpb25UaW1lc3RhbXAADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQACGtfcGF1c2VkAghrX3BhdXNlZAALa19jbG9zZU9ubHkCC2tfY2xvc2VPbmx5AAVrX2ZlZQIFa19mZWUADWtfcm9sbG92ZXJGZWUCDmtfcm9sbG92ZXJfZmVlAA9rX2Z1bmRpbmdQZXJpb2QCD2tfZnVuZGluZ1BlcmlvZAARa19pbml0TWFyZ2luUmF0aW8CEWtfaW5pdE1hcmdpblJhdGlvABhrX21haW50ZW5hbmNlTWFyZ2luUmF0aW8CBWtfbW1yABVrX2xpcXVpZGF0aW9uRmVlUmF0aW8CFWtfbGlxdWlkYXRpb25GZWVSYXRpbwAZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwIWa19wYXJ0TGlxdWlkYXRpb25SYXRpbwANa19zcHJlYWRMaW1pdAINa19zcHJlYWRMaW1pdAAQa19tYXhQcmljZUltcGFjdAIQa19tYXhQcmljZUltcGFjdAAQa19tYXhQcmljZVNwcmVhZAIQa19tYXhQcmljZVNwcmVhZAARa19tYXhPcGVuTm90aW9uYWwCEWtfbWF4T3Blbk5vdGlvbmFsABVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQCFWtfZmVlVG9TdGFrZXJzUGVyY2VudAAQa19tYXhPcmFjbGVEZWxheQIQa19tYXhPcmFjbGVEZWxheQANa19mdW5kaW5nTW9kZQINa19mdW5kaW5nTW9kZQANa19sYXN0RGF0YVN0cgINa19sYXN0RGF0YVN0cgAOa19sYXN0TWludXRlSWQCDmtfbGFzdE1pbnV0ZUlkAB1rX3R3YXBEYXRhTGFzdEN1bXVsYXRpdmVQcmljZQIda190d2FwRGF0YUxhc3RDdW11bGF0aXZlUHJpY2UAE2tfdHdhcERhdGFMYXN0UHJpY2UCE2tfdHdhcERhdGFMYXN0UHJpY2UAGmtfdHdhcERhdGFQcmV2aW91c01pbnV0ZUlkAhprX3R3YXBEYXRhUHJldmlvdXNNaW51dGVJZAAla19sYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIba19sYXRlc3RMb25nUHJlbWl1bUZyYWN0aW9uACZrX2xhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgIca19sYXRlc3RTaG9ydFByZW1pdW1GcmFjdGlvbgASa19uZXh0RnVuZGluZ0Jsb2NrAh5rX25leHRGdW5kaW5nQmxvY2tNaW5UaW1lc3RhbXAAEWtfbG9uZ0Z1bmRpbmdSYXRlAhFrX2xvbmdGdW5kaW5nUmF0ZQASa19zaG9ydEZ1bmRpbmdSYXRlAhJrX3Nob3J0RnVuZGluZ1JhdGUAE2tfcXVvdGVBc3NldFJlc2VydmUCCGtfcXRBc3RSABJrX2Jhc2VBc3NldFJlc2VydmUCCGtfYnNBc3RSABJrX3F1b3RlQXNzZXRXZWlnaHQCCGtfcXRBc3RXABFrX2Jhc2VBc3NldFdlaWdodAIIa19ic0FzdFcAE2tfdG90YWxQb3NpdGlvblNpemUCE2tfdG90YWxQb3NpdGlvblNpemUAF2tfdG90YWxMb25nUG9zaXRpb25TaXplAhdrX3RvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQAYa190b3RhbFNob3J0UG9zaXRpb25TaXplAhhrX3RvdGFsU2hvcnRQb3NpdGlvblNpemUAFmtfb3BlbkludGVyZXN0Tm90aW9uYWwCFmtfb3BlbkludGVyZXN0Tm90aW9uYWwAE2tfb3BlbkludGVyZXN0U2hvcnQCE2tfb3BlbkludGVyZXN0U2hvcnQAEmtfb3BlbkludGVyZXN0TG9uZwISa19vcGVuSW50ZXJlc3RMb25nAAhrX2xhc3RUeAIIa19sYXN0VHgAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAPa192YXVsdF9hZGRyZXNzAg9rX3ZhdWx0X2FkZHJlc3MAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzAA1rX3F1b3RlX2Fzc2V0Ag1rX3F1b3RlX2Fzc2V0AA9rX3F1b3RlX3N0YWtpbmcCD2tfcXVvdGVfc3Rha2luZwARa19zdGFraW5nX2FkZHJlc3MCEWtfc3Rha2luZ19hZGRyZXNzAA9rX21pbmVyX2FkZHJlc3MCD2tfbWluZXJfYWRkcmVzcwAQa19vcmRlcnNfYWRkcmVzcwIQa19vcmRlcnNfYWRkcmVzcwASa19yZWZlcnJhbF9hZGRyZXNzAhJrX3JlZmVycmFsX2FkZHJlc3MAEmtfZXhjaGFuZ2VfYWRkcmVzcwISa19leGNoYW5nZV9hZGRyZXNzABVrX25mdF9tYW5hZ2VyX2FkZHJlc3MCFWtfbmZ0X21hbmFnZXJfYWRkcmVzcwEOdG9Db21wb3NpdGVLZXkCBF9rZXkIX2FkZHJlc3MJAKwCAgkArAICBQRfa2V5AgFfBQhfYWRkcmVzcwELY29vcmRpbmF0b3IBBm1hcmtldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBm1hcmtldAUUa19jb29yZGluYXRvckFkZHJlc3MCE0Nvb3JkaW5hdG9yIG5vdCBzZXQBDGFkbWluQWRkcmVzcwEGbWFya2V0CQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgEFBm1hcmtldAUPa19hZG1pbl9hZGRyZXNzAQpxdW90ZUFzc2V0AQZtYXJrZXQJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAQUGbWFya2V0BQ1rX3F1b3RlX2Fzc2V0ARFxdW90ZUFzc2V0U3Rha2luZwEGbWFya2V0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAQUGbWFya2V0BQ9rX3F1b3RlX3N0YWtpbmcCG1F1b3RlIGFzc2V0IHN0YWtpbmcgbm90IHNldAEOc3Rha2luZ0FkZHJlc3MBBm1hcmtldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgEFBm1hcmtldAURa19zdGFraW5nX2FkZHJlc3MCD1N0YWtpbmcgbm90IHNldAEMdmF1bHRBZGRyZXNzAQZtYXJrZXQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IBBQZtYXJrZXQFD2tfdmF1bHRfYWRkcmVzcwINVmF1bHQgbm90IHNldAEMbWluZXJBZGRyZXNzAQZtYXJrZXQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IBBQZtYXJrZXQFD2tfbWluZXJfYWRkcmVzcwINTWluZXIgbm90IHNldAENb3JkZXJzQWRkcmVzcwEGbWFya2V0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAQUGbWFya2V0BRBrX29yZGVyc19hZGRyZXNzAg5PcmRlcnMgbm90IHNldAEPcmVmZXJyYWxBZGRyZXNzAQZtYXJrZXQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IBBQZtYXJrZXQFEmtfcmVmZXJyYWxfYWRkcmVzcwIQUmVmZXJyYWwgbm90IHNldAERbmZ0TWFuYWdlckFkZHJlc3MBBm1hcmtldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgEFBm1hcmtldAUVa19uZnRfbWFuYWdlcl9hZGRyZXNzAhNORlQgTWFuYWdlciBub3Qgc2V0AA1rX3Rva2VuX3BhcmFtAg1rX3Rva2VuX3BhcmFtAAxrX3Rva2VuX3R5cGUCDGtfdG9rZW5fdHlwZQAYRkVFX1JFRFVDVElPTl9UT0tFTl9UWVBFAg1mZWVfcmVkdWN0aW9uAAhESVJfTE9ORwABAAlESVJfU0hPUlQAAgANVFdBUF9JTlRFUlZBTAAPAAdTRUNPTkRTAOgHAA9ERUNJTUFMX05VTUJFUlMABgAMREVDSU1BTF9VTklUCQBoAgABCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoAD01JTlVURVNfSU5fWUVBUgkAaAIAoIogBQxERUNJTUFMX1VOSVQAB09ORV9EQVkJAGgCAICjBQUMREVDSU1BTF9VTklUAA9QTkxfT1BUSU9OX1NQT1QAAQARUE5MX09QVElPTl9PUkFDTEUAAgASRlVORElOR19BU1lNTUVUUklDAAEAEUZVTkRJTkdfU1lNTUVUUklDAAIBAXMBAl94CQCsAgIJAKQDAQUCX3gCASwBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEFYmRpdmQCAl94Al95CQC9AgQFAl94CQC2AgEFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQVibXVsZAICX3gCX3kJAL0CBAUCX3gFAl95CQC2AgEFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBHZtYXgCAl94Al95AwkAZwIFAl94BQJfeQUCX3gFAl95AQlsaXN0VG9TdHIBBV9saXN0AwkAAAIJAJADAQUFX2xpc3QAAAIACQC5CQIFBV9saXN0AgEsAQlzdHJUb0xpc3QBBF9zdHIDCQAAAgUEX3N0cgIABQNuaWwJALUJAgUEX3N0cgIBLAELcHVzaFRvUXVldWUDBV9saXN0CF9tYXhTaXplBl92YWx1ZQMJAGYCCQCQAwEFBV9saXN0BQhfbWF4U2l6ZQkAzQgCCQDRCAIFBV9saXN0AAAFBl92YWx1ZQkAzQgCBQVfbGlzdAUGX3ZhbHVlAQNpbnQCBm1hcmtldAFrCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUGbWFya2V0BQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBWludE9yAwZtYXJrZXQBawNkZWYJAQt2YWx1ZU9yRWxzZQIJAJoIAgUGbWFya2V0BQFrBQNkZWYBBHN0ckECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBBGludEECCF9hZGRyZXNzBF9rZXkEA3ZhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCF9hZGRyZXNzBQRfa2V5CQCsAgICEU5vIHZhbHVlIGZvciBrZXkgBQRfa2V5BQN2YWwBCGNiYWxhbmNlAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFCWtfYmFsYW5jZQEDZmVlAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFBWtfZmVlAQ9yb2xsb3ZlckZlZVJhdGUBBm1hcmtldAkBA2ludAIFBm1hcmtldAUNa19yb2xsb3ZlckZlZQEPaW5pdE1hcmdpblJhdGlvAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFEWtfaW5pdE1hcmdpblJhdGlvAQZxdEFzdFIBBm1hcmtldAkBA2ludAIFBm1hcmtldAUTa19xdW90ZUFzc2V0UmVzZXJ2ZQEGYnNBc3RSAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFEmtfYmFzZUFzc2V0UmVzZXJ2ZQEGcXRBc3RXAQZtYXJrZXQJAQVpbnRPcgMFBm1hcmtldAUSa19xdW90ZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBBmJzQXN0VwEGbWFya2V0CQEFaW50T3IDBQZtYXJrZXQFEWtfYmFzZUFzc2V0V2VpZ2h0BQxERUNJTUFMX1VOSVQBEXRvdGFsUG9zaXRpb25TaXplAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFE2tfdG90YWxQb3NpdGlvblNpemUBFG9wZW5JbnRlcmVzdE5vdGlvbmFsAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFFmtfb3BlbkludGVyZXN0Tm90aW9uYWwBEW9wZW5JbnRlcmVzdFNob3J0AQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFE2tfb3BlbkludGVyZXN0U2hvcnQBEG9wZW5JbnRlcmVzdExvbmcBBm1hcmtldAkBA2ludAIFBm1hcmtldAUSa19vcGVuSW50ZXJlc3RMb25nARluZXh0RnVuZGluZ0Jsb2NrVGltZXN0YW1wAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFEmtfbmV4dEZ1bmRpbmdCbG9jawEQZnVuZGluZ1BlcmlvZFJhdwEGbWFya2V0CQEDaW50AgUGbWFya2V0BQ9rX2Z1bmRpbmdQZXJpb2QBFGZ1bmRpbmdQZXJpb2REZWNpbWFsAQZtYXJrZXQJAGgCCQEQZnVuZGluZ1BlcmlvZFJhdwEFBm1hcmtldAUMREVDSU1BTF9VTklUARRmdW5kaW5nUGVyaW9kU2Vjb25kcwEGbWFya2V0CQBoAgkBEGZ1bmRpbmdQZXJpb2RSYXcBBQZtYXJrZXQFB1NFQ09ORFMBFm1haW50ZW5hbmNlTWFyZ2luUmF0aW8BBm1hcmtldAkBA2ludAIFBm1hcmtldAUYa19tYWludGVuYW5jZU1hcmdpblJhdGlvARNsaXF1aWRhdGlvbkZlZVJhdGlvAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFFWtfbGlxdWlkYXRpb25GZWVSYXRpbwEXcGFydGlhbExpcXVpZGF0aW9uUmF0aW8BBm1hcmtldAkBA2ludAIFBm1hcmtldAUZa19wYXJ0aWFsTGlxdWlkYXRpb25SYXRpbwELc3ByZWFkTGltaXQBBm1hcmtldAkBA2ludAIFBm1hcmtldAUNa19zcHJlYWRMaW1pdAEObWF4UHJpY2VJbXBhY3QBBm1hcmtldAkBA2ludAIFBm1hcmtldAUQa19tYXhQcmljZUltcGFjdAEObWF4UHJpY2VTcHJlYWQBBm1hcmtldAkBA2ludAIFBm1hcmtldAUQa19tYXhQcmljZVNwcmVhZAEPbWF4T3Blbk5vdGlvbmFsAQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFEWtfbWF4T3Blbk5vdGlvbmFsASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEGbWFya2V0CQEDaW50AgUGbWFya2V0BSVrX2xhdGVzdExvbmdDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uASRsYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BBm1hcmtldAkBA2ludAIFBm1hcmtldAUma19sYXRlc3RTaG9ydEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24BFnRvdGFsU2hvcnRQb3NpdGlvblNpemUBBm1hcmtldAkBA2ludAIFBm1hcmtldAUYa190b3RhbFNob3J0UG9zaXRpb25TaXplARV0b3RhbExvbmdQb3NpdGlvblNpemUBBm1hcmtldAkBA2ludAIFBm1hcmtldAUXa190b3RhbExvbmdQb3NpdGlvblNpemUBDGxhc3RTZXF1ZW5jZQEGbWFya2V0CQEFaW50T3IDBQZtYXJrZXQFCmtfc2VxdWVuY2UAAAETZmVlVG9TdGFrZXJzUGVyY2VudAEGbWFya2V0CQEDaW50AgUGbWFya2V0BRVrX2ZlZVRvU3Rha2Vyc1BlcmNlbnQBDm1heE9yYWNsZURlbGF5AQZtYXJrZXQJAQNpbnQCBQZtYXJrZXQFEGtfbWF4T3JhY2xlRGVsYXkBC2Z1bmRpbmdNb2RlAQZtYXJrZXQJAQVpbnRPcgMFBm1hcmtldAUNa19mdW5kaW5nTW9kZQUSRlVORElOR19BU1lNTUVUUklDAQ1sYXN0VGltZXN0YW1wAAgFCWxhc3RCbG9jawl0aW1lc3RhbXABD2dldEFjdHVhbENhbGxlcgIGbWFya2V0AWkJAQt2YWx1ZU9yRWxzZQIJAJ0IAgkBDW9yZGVyc0FkZHJlc3MBBQZtYXJrZXQCCGtfc2VuZGVyCQClCAEIBQFpBmNhbGxlcgEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMMX21hcmdpblJhdGlvEF9iYXNlTWFyZ2luUmF0aW8UX2xhcmdlclRoYW5PckVxdWFsVG8EFHJlbWFpbmluZ01hcmdpblJhdGlvCQBlAgUMX21hcmdpblJhdGlvBRBfYmFzZU1hcmdpblJhdGlvAwMFFF9sYXJnZXJUaGFuT3JFcXVhbFRvCQBmAgAABRRyZW1haW5pbmdNYXJnaW5SYXRpbwcGAwMJAQEhAQUUX2xhcmdlclRoYW5PckVxdWFsVG8JAGcCBRRyZW1haW5pbmdNYXJnaW5SYXRpbwAABwYGAR9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uAgZtYXJrZXQNX3Bvc2l0aW9uU2l6ZQMJAAACBQ1fcG9zaXRpb25TaXplAAAJAAIBAixTaG91bGQgbm90IGJlIGNhbGxlZCB3aXRoIF9wb3NpdGlvblNpemUgPT0gMAMJAGYCBQ1fcG9zaXRpb25TaXplAAAJASNsYXRlc3RMb25nQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFBm1hcmtldAkBJGxhdGVzdFNob3J0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgEFBm1hcmtldAELZ2V0UG9zaXRpb24CBm1hcmtldAdfdHJhZGVyBA9wb3NpdGlvblNpemVPcHQJAJoIAgUGbWFya2V0CQEOdG9Db21wb3NpdGVLZXkCBQ5rX3Bvc2l0aW9uU2l6ZQUHX3RyYWRlcgQHJG1hdGNoMAUPcG9zaXRpb25TaXplT3B0AwkAAQIFByRtYXRjaDACA0ludAQMcG9zaXRpb25TaXplBQckbWF0Y2gwCQCXCgUFDHBvc2l0aW9uU2l6ZQkBEUBleHRyTmF0aXZlKDEwNTApAgUGbWFya2V0CQEOdG9Db21wb3NpdGVLZXkCBRBrX3Bvc2l0aW9uTWFyZ2luBQdfdHJhZGVyCQERQGV4dHJOYXRpdmUoMTA1MCkCBQZtYXJrZXQJAQ50b0NvbXBvc2l0ZUtleQIFFmtfcG9zaXRpb25PcGVuTm90aW9uYWwFB190cmFkZXIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBm1hcmtldAkBDnRvQ29tcG9zaXRlS2V5AgUua19wb3NpdGlvbkxhc3RVcGRhdGVkQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgUHX3RyYWRlcgkBEUBleHRyTmF0aXZlKDEwNTApAgUGbWFya2V0CQEOdG9Db21wb3NpdGVLZXkCBR5rX3Bvc2l0aW9uTGFzdFVwZGF0ZWRUaW1lc3RhbXAFB190cmFkZXIJAJcKBQAAAAAAAAAAAAABEGdldFBvc2l0aW9uQXNzZXQCBm1hcmtldAdfdHJhZGVyBBBwb3NpdGlvbkFzc2V0T3B0CQCdCAIFBm1hcmtldAkBDnRvQ29tcG9zaXRlS2V5AgUPa19wb3NpdGlvbkFzc2V0BQdfdHJhZGVyBAckbWF0Y2gwBRBwb3NpdGlvbkFzc2V0T3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQNcG9zaXRpb25Bc3NldAUHJG1hdGNoMAUNcG9zaXRpb25Bc3NldAkA2AQBCQEKcXVvdGVBc3NldAEFBm1hcmtldAEOZ2V0UG9zaXRpb25GZWUCBm1hcmtldAdfdHJhZGVyBA5wb3NpdGlvbkZlZU9wdAkAmggCBQZtYXJrZXQJAQ50b0NvbXBvc2l0ZUtleQIFDWtfcG9zaXRpb25GZWUFB190cmFkZXIEByRtYXRjaDAFDnBvc2l0aW9uRmVlT3B0AwkAAQIFByRtYXRjaDACA0ludAQLcG9zaXRpb25GZWUFByRtYXRjaDAFC3Bvc2l0aW9uRmVlCQEDZmVlAQUGbWFya2V0ARNyZXF1aXJlT3BlblBvc2l0aW9uAgZtYXJrZXQHX3RyYWRlcgMJAAACCAkBC2dldFBvc2l0aW9uAgUGbWFya2V0BQdfdHJhZGVyAl8xAAAHBgENZ2V0T3JhY2xlRGF0YQIGbWFya2V0A2tleQQNb3JhY2xlRGF0YVN0cgkAnQgCBQZtYXJrZXQFA2tleQMDCQEJaXNEZWZpbmVkAQUNb3JhY2xlRGF0YVN0cgkBAiE9AgkBBXZhbHVlAQUNb3JhY2xlRGF0YVN0cgIABwQKb3JhY2xlRGF0YQkAtQkCCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyAgEsBA1vcmFjbGVBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpvcmFjbGVEYXRhAAAJAKwCAgIbSW52YWxpZCBvcmFjbGUgYWRkcmVzcyBpbjogCQEFdmFsdWUBBQ1vcmFjbGVEYXRhU3RyBAhwcmljZUtleQkAkQMCBQpvcmFjbGVEYXRhAAEECGJsb2NrS2V5CQCRAwIFCm9yYWNsZURhdGEAAgQHb3BlbktleQkAkQMCBQpvcmFjbGVEYXRhAAMJAJYKBAUNb3JhY2xlQWRkcmVzcwUIcHJpY2VLZXkFCGJsb2NrS2V5BQdvcGVuS2V5BQR1bml0AQtpbml0aWFsaXplZAEGbWFya2V0CQELdmFsdWVPckVsc2UCCQCbCAIFBm1hcmtldAUNa19pbml0aWFsaXplZAcBBnBhdXNlZAEGbWFya2V0CQELdmFsdWVPckVsc2UCCQCbCAIFBm1hcmtldAUIa19wYXVzZWQHAQljbG9zZU9ubHkBBm1hcmtldAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQZtYXJrZXQFC2tfY2xvc2VPbmx5BwENdXBkYXRlUmVzZXJ2ZQQGbWFya2V0Bl9pc0FkZBFfcXVvdGVBc3NldEFtb3VudBBfYmFzZUFzc2V0QW1vdW50AwUGX2lzQWRkBAduZXdCYXNlCQBlAgkBBmJzQXN0UgEFBm1hcmtldAUQX2Jhc2VBc3NldEFtb3VudAMJAGcCAAAFB25ld0Jhc2UJAAIBAipUeCBsZWFkIHRvIGJhc2UgYXNzZXQgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwkAZAIJAQZxdEFzdFIBBQZtYXJrZXQFEV9xdW90ZUFzc2V0QW1vdW50BQduZXdCYXNlCQBkAgkBEXRvdGFsUG9zaXRpb25TaXplAQUGbWFya2V0BRBfYmFzZUFzc2V0QW1vdW50BAhuZXdRdW90ZQkAZQIJAQZxdEFzdFIBBQZtYXJrZXQFEV9xdW90ZUFzc2V0QW1vdW50AwkAZwIAAAUIbmV3UXVvdGUJAAIBAipUeCBsZWFkIHRvIGJhc2UgcXVvdGUgcmVzZXJ2ZSA8PSAwLCByZXZlcnQJAJUKAwUIbmV3UXVvdGUJAGQCCQEGYnNBc3RSAQUGbWFya2V0BRBfYmFzZUFzc2V0QW1vdW50CQBlAgkBEXRvdGFsUG9zaXRpb25TaXplAQUGbWFya2V0BRBfYmFzZUFzc2V0QW1vdW50AQ1jYWxjSW52YXJpYW50AgdfcXRBc3RSB19ic0FzdFIEB2JxdEFzdFIJALYCAQUHX3F0QXN0UgQHYmJzQXN0UgkAtgIBBQdfYnNBc3RSCQEFYm11bGQCBQdicXRBc3RSBQdiYnNBc3RSAQlzd2FwSW5wdXQDBm1hcmtldAZfaXNBZGQRX3F1b3RlQXNzZXRBbW91bnQEB19xdEFzdFIJAQZxdEFzdFIBBQZtYXJrZXQEB19ic0FzdFIJAQZic0FzdFIBBQZtYXJrZXQEB19xdEFzdFcJAQZxdEFzdFcBBQZtYXJrZXQEB19ic0FzdFcJAQZic0FzdFcBBQZtYXJrZXQEGHF1b3RlQXNzZXRBbW91bnRBZGp1c3RlZAkBBGRpdmQCBRFfcXVvdGVBc3NldEFtb3VudAUHX3F0QXN0VwQBawkBDWNhbGNJbnZhcmlhbnQCBQdfcXRBc3RSBQdfYnNBc3RSBBZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyAwUGX2lzQWRkCQBkAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkCQBlAgUHX3F0QXN0UgUYcXVvdGVBc3NldEFtb3VudEFkanVzdGVkBBViYXNlQXNzZXRSZXNlcnZlQWZ0ZXIJAKADAQkBBWJkaXZkAgUBawkAtgIBBRZxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyBBhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMJAQNhYnMBCQBlAgUVYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyBQdfYnNBc3RSBBVhbW91bnRCYXNlQXNzZXRCb3VnaHQDBQZfaXNBZGQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwkBAS0BBRhhbW91bnRCYXNlQXNzZXRCb3VnaHRBYnMEBXR1cGxlCQENdXBkYXRlUmVzZXJ2ZQQFBm1hcmtldAUGX2lzQWRkBRhxdW90ZUFzc2V0QW1vdW50QWRqdXN0ZWQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEIBQV0dXBsZQJfMQQWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFBXR1cGxlAl8yBBd0b3RhbFBvc2l0aW9uU2l6ZUFmdGVyMQgFBXR1cGxlAl8zBAtwcmljZUJlZm9yZQkBBGRpdmQCCQEEbXVsZAIFB19xdEFzdFIFB19xdEFzdFcJAQRtdWxkAgUHX2JzQXN0UgUHX2JzQXN0VwQLbWFya2V0UHJpY2UJAQRkaXZkAgURX3F1b3RlQXNzZXRBbW91bnQFGGFtb3VudEJhc2VBc3NldEJvdWdodEFicwQJcHJpY2VEaWZmCQEDYWJzAQkAZQIFC3ByaWNlQmVmb3JlBQttYXJrZXRQcmljZQQLcHJpY2VJbXBhY3QJAGUCBQxERUNJTUFMX1VOSVQJAQRkaXZkAgULcHJpY2VCZWZvcmUJAGQCBQtwcmljZUJlZm9yZQUJcHJpY2VEaWZmBBNtYXhQcmljZUltcGFjdFZhbHVlCQEObWF4UHJpY2VJbXBhY3QBBQZtYXJrZXQDCQBmAgULcHJpY2VJbXBhY3QFE21heFByaWNlSW1wYWN0VmFsdWUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBQdfcXRBc3RSAhQgYmVmb3JlIGJhc2UgYXNzZXQ6IAkApAMBBQdfYnNBc3RSAiEgcXVvdGUgYXNzZXQgYW1vdW50IHRvIGV4Y2hhbmdlOiAJAKQDAQURX3F1b3RlQXNzZXRBbW91bnQCDyBwcmljZSBiZWZvcmU6IAkApAMBBQtwcmljZUJlZm9yZQIOIG1hcmtldFByaWNlOiAJAKQDAQULbWFya2V0UHJpY2UJAJYKBAUVYW1vdW50QmFzZUFzc2V0Qm91Z2h0BRdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQUWYmFzZUFzc2V0UmVzZXJ2ZUFmdGVyMQUXdG90YWxQb3NpdGlvblNpemVBZnRlcjEBD2NhbGNSb2xsb3ZlckZlZQMGbWFya2V0El9vbGRQb3NpdGlvbk1hcmdpbiBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAQPcG9zaXRpb25NaW51dGVzCQBoAgkAaQIJAGkCCQBlAgkBDWxhc3RUaW1lc3RhbXAABSBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcADoBwA8BQxERUNJTUFMX1VOSVQEC3JvbGxvdmVyRmVlCQEEZGl2ZAIJAQRtdWxkAgkBBG11bGQCBRJfb2xkUG9zaXRpb25NYXJnaW4FD3Bvc2l0aW9uTWludXRlcwkBD3JvbGxvdmVyRmVlUmF0ZQEFBm1hcmtldAUPTUlOVVRFU19JTl9ZRUFSBQtyb2xsb3ZlckZlZQEwY2FsY1JlbWFpbk1hcmdpbldpdGhGdW5kaW5nUGF5bWVudEFuZFJvbGxvdmVyRmVlBgZtYXJrZXQQX29sZFBvc2l0aW9uU2l6ZRJfb2xkUG9zaXRpb25NYXJnaW4lX29sZFBvc2l0aW9uQ3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbiBfb2xkUG9zaXRpb25MYXN0VXBkYXRlZFRpbWVzdGFtcAxfbWFyZ2luRGVsdGEEDmZ1bmRpbmdQYXltZW50AwkBAiE9AgUQX29sZFBvc2l0aW9uU2l6ZQAABCBfbGF0ZXN0Q3VtdWxhdGl2ZVByZW1pdW1GcmFjdGlvbgkBH2xhdGVzdEN1bXVsYXRpdmVQcmVtaXVtRnJhY3Rpb24CBQZtYXJrZXQFEF9vbGRQb3NpdGlvblNpemUJAQRtdWxkAgkAZQIFIF9sYXRlc3RDdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBSVfb2xkUG9zaXRpb25DdW11bGF0aXZlUHJlbWl1bUZyYWN0aW9uBRBfb2xkUG9zaXRpb25TaXplAAAEC3JvbGxvdmVyRmVlCQEPY2FsY1JvbGxvdmVyRmVlAwUGbWFya2V0BRJfb2xkUG9zaXRpb25NYXJnaW4FIF9vbGRQb3NpdGlvbkxhc3RVcGRhdGVkVGltZXN0YW1wBAxzaWduZWRNYXJnaW4JAGQCCQBlAgkAZQIFDF9tYXJnaW5EZWx0YQULcm9sbG92ZXJGZWUFDmZ1bmRpbmdQYXltZW50BRJfb2xkUG9zaXRpb25NYXJnaW4EBXR1cGxlAwkAZgIAAAUMc2lnbmVkTWFyZ2luCQCUCgIAAAkBA2FicwEFDHNpZ25lZE1hcmdpbgkAlAoCCQEDYWJzAQUMc2lnbmVkTWFyZ2luAAAEDHJlbWFpbk1hcmdpbggFBXR1cGxlAl8xBAdiYWREZWJ0CAUFdHVwbGUCXzIJAJYKBAUMcmVtYWluTWFyZ2luBQdiYWREZWJ0BQ5mdW5kaW5nUGF5bWVudAULcm9sbG92ZXJGZWUBFnN3YXBPdXRwdXRXaXRoUmVzZXJ2ZXMIBm1hcmtldAZfaXNBZGQQX2Jhc2VBc3NldEFtb3VudBRfY2hlY2tNYXhQcmljZUltcGFjdBJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQLcHJpY2VCZWZvcmUJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0CQEEbXVsZAIFEV9iYXNlQXNzZXRSZXNlcnZlBRBfYmFzZUFzc2V0V2VpZ2h0AwkAAAIFEF9iYXNlQXNzZXRBbW91bnQAAAkAAgECGUludmFsaWQgYmFzZSBhc3NldCBhbW91bnQEAWsJAQ1jYWxjSW52YXJpYW50AgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfYmFzZUFzc2V0UmVzZXJ2ZQQYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyAwUGX2lzQWRkCQBkAgURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRBbW91bnQJAGUCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldEFtb3VudAQPcXVvdGVBc3NldEFmdGVyCQCgAwEJAQViZGl2ZAIFAWsJALYCAQUYYmFzZUFzc2V0UG9vbEFtb3VudEFmdGVyBA9xdW90ZUFzc2V0RGVsdGEJAQNhYnMBCQBlAgUPcXVvdGVBc3NldEFmdGVyBRJfcXVvdGVBc3NldFJlc2VydmUEDnF1b3RlQXNzZXRTb2xkCQEEbXVsZAIFD3F1b3RlQXNzZXREZWx0YQURX3F1b3RlQXNzZXRXZWlnaHQEE21heFByaWNlSW1wYWN0VmFsdWUJAQ5tYXhQcmljZUltcGFjdAEFBm1hcmtldAQFdHVwbGUJAQ11cGRhdGVSZXNlcnZlBAUGbWFya2V0CQEBIQEFBl9pc0FkZAUPcXVvdGVBc3NldERlbHRhBRBfYmFzZUFzc2V0QW1vdW50BBdxdW90ZUFzc2V0UmVzZXJ2ZUFmdGVyMQgFBXR1cGxlAl8xBBZiYXNlQXNzZXRSZXNlcnZlQWZ0ZXIxCAUFdHVwbGUCXzIEF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCAUFdHVwbGUCXzMEC21hcmtldFByaWNlCQEEZGl2ZAIFDnF1b3RlQXNzZXRTb2xkBRBfYmFzZUFzc2V0QW1vdW50BAlwcmljZURpZmYJAQNhYnMBCQBlAgULcHJpY2VCZWZvcmUFC21hcmtldFByaWNlBAtwcmljZUltcGFjdAkAZQIFDERFQ0lNQUxfVU5JVAkBBGRpdmQCBQtwcmljZUJlZm9yZQkAZAIFC3ByaWNlQmVmb3JlBQlwcmljZURpZmYDAwkAZgIFC3ByaWNlSW1wYWN0BRNtYXhQcmljZUltcGFjdFZhbHVlBRRfY2hlY2tNYXhQcmljZUltcGFjdAcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVByaWNlIGltcGFjdCAJAKQDAQULcHJpY2VJbXBhY3QCFCA+IG1heCBwcmljZSBpbXBhY3QgCQCkAwEFE21heFByaWNlSW1wYWN0VmFsdWUCFSBiZWZvcmUgcXVvdGUgYXNzZXQ6IAkApAMBBRJfcXVvdGVBc3NldFJlc2VydmUCFCBiZWZvcmUgYmFzZSBhc3NldDogCQCkAwEFEV9iYXNlQXNzZXRSZXNlcnZlAiAgYmFzZSBhc3NldCBhbW91bnQgdG8gZXhjaGFuZ2U6IAkApAMBBRBfYmFzZUFzc2V0QW1vdW50Ag8gcHJpY2UgYmVmb3JlOiAJAKQDAQULcHJpY2VCZWZvcmUCDyBtYXJrZXQgcHJpY2U6IAkApAMBBQttYXJrZXRQcmljZQkAmQoHBQ5xdW90ZUFzc2V0U29sZAUXcXVvdGVBc3NldFJlc2VydmVBZnRlcjEFFmJhc2VBc3NldFJlc2VydmVBZnRlcjEFF3RvdGFsUG9zaXRpb25TaXplQWZ0ZXIxCQBlAgkBFXRvdGFsTG9uZ1Bvc2l0aW9uU2l6ZQEFBm1hcmtldAMFBl9pc0FkZAkBA2FicwEFEF9iYXNlQXNzZXRBbW91bnQAAAkAZQIJARZ0b3RhbFNob3J0UG9zaXRpb25TaXplAQUGbWFya2V0AwkBASEBBQZfaXNBZGQJAQNhYnMBBRBfYmFzZUFzc2V0QW1vdW50AAAFC3ByaWNlSW1wYWN0AQpzd2FwT3V0cHV0BAZtYXJrZXQGX2lzQWRkEF9iYXNlQXNzZXRBbW91bnQUX2NoZWNrTWF4UHJpY2VJbXBhY3QJARZzd2FwT3V0cHV0V2l0aFJlc2VydmVzCAUGbWFya2V0BQZfaXNBZGQFEF9iYXNlQXNzZXRBbW91bnQFFF9jaGVja01heFByaWNlSW1wYWN0CQEGcXRBc3RSAQUGbWFya2V0CQEGcXRBc3RXAQUGbWFya2V0CQEGYnNBc3RSAQUGbWFya2V0CQEGYnNBc3RXAQUGbWFya2V0ARNnZXRPcmFjbGVQcmljZVZhbHVlBAZtYXJrZXQGb3JhY2xlCHByaWNlS2V5CGJsb2NrS2V5BAlsYXN0VmFsdWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQZvcmFjbGUFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAiJDYW4gbm90IGdldCBvcmFjbGUgcHJpY2UuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQhwcmljZUtleQMJAQIhPQIFCGJsb2NrS2V5AgAEDGN1cnJlbnRCbG9jawgFCWxhc3RCbG9jawZoZWlnaHQED2xhc3RPcmFjbGVCbG9jawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBm9yYWNsZQUIYmxvY2tLZXkJAKwCAgkArAICCQCsAgICIkNhbiBub3QgZ2V0IG9yYWNsZSBibG9jay4gT3JhY2xlOiAJAKUIAQUGb3JhY2xlAgYga2V5OiAFCGJsb2NrS2V5AwkAZgIJAGUCBQxjdXJyZW50QmxvY2sFD2xhc3RPcmFjbGVCbG9jawkBDm1heE9yYWNsZURlbGF5AQUGbWFya2V0CQACAQkArAICCQCsAgIJAKwCAgImT3JhY2xlIHN0YWxlIGRhdGEuIExhc3Qgb3JhY2xlIGJsb2NrOiAJAKQDAQUPbGFzdE9yYWNsZUJsb2NrAhAgY3VycmVudCBibG9jazogCQCkAwEFDGN1cnJlbnRCbG9jawUJbGFzdFZhbHVlBQlsYXN0VmFsdWUBDmdldE9yYWNsZVByaWNlAQZtYXJrZXQECmJhc2VPcmFjbGUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBDWdldE9yYWNsZURhdGECBQZtYXJrZXQFDGtfYmFzZU9yYWNsZQIZTm8gYmFzZSBhc3NldCBvcmFjbGUgZGF0YQQPYmFzZU9yYWNsZVByaWNlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQQFBm1hcmtldAgFCmJhc2VPcmFjbGUCXzEIBQpiYXNlT3JhY2xlAl8yCAUKYmFzZU9yYWNsZQJfMwQLcXVvdGVPcmFjbGUJAQ1nZXRPcmFjbGVEYXRhAgUGbWFya2V0BQ1rX3F1b3RlT3JhY2xlBBBxdW90ZU9yYWNsZVByaWNlAwkBCWlzRGVmaW5lZAEFC3F1b3RlT3JhY2xlBAxxdW90ZU9yYWNsZVYJAQV2YWx1ZQEFC3F1b3RlT3JhY2xlCQETZ2V0T3JhY2xlUHJpY2VWYWx1ZQQFBm1hcmtldAgFDHF1b3RlT3JhY2xlVgJfMQgFDHF1b3RlT3JhY2xlVgJfMggFDHF1b3RlT3JhY2xlVgJfMwUMREVDSU1BTF9VTklUCQEEZGl2ZAIFD2Jhc2VPcmFjbGVQcmljZQUQcXVvdGVPcmFjbGVQcmljZQEOaXNNYXJrZXRDbG9zZWQBBm1hcmtldAQKYmFzZU9yYWNsZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQENZ2V0T3JhY2xlRGF0YQIFBm1hcmtldAUMa19iYXNlT3JhY2xlAhlObyBiYXNlIGFzc2V0IG9yYWNsZSBkYXRhBAZvcmFjbGUIBQpiYXNlT3JhY2xlAl8xBAdvcGVuS2V5CAUKYmFzZU9yYWNsZQJfNAMJAQIhPQIFB29wZW5LZXkCAAQGaXNPcGVuCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJsIAgUGb3JhY2xlBQdvcGVuS2V5CQCsAgIJAKwCAgkArAICAitDYW4gbm90IGdldCBvcmFjbGUgaXMgb3Blbi9jbG9zZWQuIE9yYWNsZTogCQClCAEFBm9yYWNsZQIGIGtleTogBQdvcGVuS2V5CQEBIQEFBmlzT3BlbgcBDGFic1ByaWNlRGlmZgUMX29yYWNsZVByaWNlEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfYmFzZUFzc2V0UmVzZXJ2ZQdfcXRBc3RXB19ic0FzdFcECnByaWNlQWZ0ZXIJAQRkaXZkAgkBBG11bGQCBRJfcXVvdGVBc3NldFJlc2VydmUFB19xdEFzdFcJAQRtdWxkAgURX2Jhc2VBc3NldFJlc2VydmUFB19ic0FzdFcEDGF2ZXJhZ2VQcmljZQkBBGRpdmQCCQBkAgUMX29yYWNsZVByaWNlBQpwcmljZUFmdGVyCQBoAgACBQxERUNJTUFMX1VOSVQEDGFic1ByaWNlRGlmZgkBBGRpdmQCCQEDYWJzAQkAZQIFDF9vcmFjbGVQcmljZQUKcHJpY2VBZnRlcgUMYXZlcmFnZVByaWNlBQxhYnNQcmljZURpZmYBGXJlcXVpcmVOb3RPdmVyU3ByZWFkTGltaXQDBm1hcmtldBJfcXVvdGVBc3NldFJlc2VydmURX2Jhc2VBc3NldFJlc2VydmUEC29yYWNsZVByaWNlCQEOZ2V0T3JhY2xlUHJpY2UBBQZtYXJrZXQEB19xdEFzdFcJAQZxdEFzdFcBBQZtYXJrZXQEB19ic0FzdFcJAQZic0FzdFcBBQZtYXJrZXQEEmFic1ByaWNlRGlmZkJlZm9yZQkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlCQEGcXRBc3RSAQUGbWFya2V0CQEGYnNBc3RSAQUGbWFya2V0BQdfcXRBc3RXBQdfYnNBc3RXBBFhYnNQcmljZURpZmZBZnRlcgkBDGFic1ByaWNlRGlmZgUFC29yYWNsZVByaWNlBRJfcXVvdGVBc3NldFJlc2VydmUFEV9iYXNlQXNzZXRSZXNlcnZlBQdfcXRBc3RXBQdfYnNBc3RXAwMJAGYCBRFhYnNQcmljZURpZmZBZnRlcgkBDm1heFByaWNlU3ByZWFkAQUGbWFya2V0CQBmAgURYWJzUHJpY2VEaWZmQWZ0ZXIFEmFic1ByaWNlRGlmZkJlZm9yZQcJAAIBCQCsAgIJAKwCAgkArAICAg1QcmljZSBzcHJlYWQgCQCkAwEFEWFic1ByaWNlRGlmZkFmdGVyAhQgPiBtYXggcHJpY2Ugc3ByZWFkIAkApAMBCQEObWF4UHJpY2VTcHJlYWQBBQZtYXJrZXQGAR1yZXF1aXJlTm90T3Zlck1heE9wZW5Ob3Rpb25hbAMGbWFya2V0EV9sb25nT3Blbk5vdGlvbmFsEl9zaG9ydE9wZW5Ob3Rpb25hbAQQX21heE9wZW5Ob3Rpb25hbAkBD21heE9wZW5Ob3Rpb25hbAEFBm1hcmtldAMJAGYCBRFfbG9uZ09wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICE0xvbmcgb3BlbiBub3Rpb25hbCAJAKQDAQURX2xvbmdPcGVuTm90aW9uYWwCFSA+IG1heCBvcGVuIG5vdGlvbmFsIAkApAMBBRBfbWF4T3Blbk5vdGlvbmFsAwkAZgIFEl9zaG9ydE9wZW5Ob3Rpb25hbAUQX21heE9wZW5Ob3Rpb25hbAkAAgEJAKwCAgkArAICCQCsAgICFFNob3J0IG9wZW4gbm90aW9uYWwgCQCkAwEFEl9zaG9ydE9wZW5Ob3Rpb25hbAIVID4gbWF4IG9wZW4gbm90aW9uYWwgCQCkAwEFEF9tYXhPcGVuTm90aW9uYWwGAQxnZXRTcG90UHJpY2UBBm1hcmtldAQSX3F1b3RlQXNzZXRSZXNlcnZlCQEGcXRBc3RSAQUGbWFya2V0BBFfYmFzZUFzc2V0UmVzZXJ2ZQkBBmJzQXN0UgEFBm1hcmtldAQHX3F0QXN0VwkBBnF0QXN0VwEFBm1hcmtldAQHX2JzQXN0VwkBBmJzQXN0VwEFBm1hcmtldAkBBGRpdmQCCQEEbXVsZAIFEl9xdW90ZUFzc2V0UmVzZXJ2ZQUHX3F0QXN0VwkBBG11bGQCBRFfYmFzZUFzc2V0UmVzZXJ2ZQUHX2JzQXN0VwEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAEGbWFya2V0BAtvcmFjbGVQcmljZQkBDmdldE9yYWNsZVByaWNlAQUGbWFya2V0BAxjdXJyZW50UHJpY2UJAQxnZXRTcG90UHJpY2UBBQZtYXJrZXQJAGYCCQEEZGl2ZAIJAQNhYnMBCQBlAgULb3JhY2xlUHJpY2UFDGN1cnJlbnRQcmljZQULb3JhY2xlUHJpY2UJAQtzcHJlYWRMaW1pdAEFBm1hcmtldAEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAcGbWFya2V0DV9wb3NpdGlvblNpemUHX29wdGlvbhJfcXVvdGVBc3NldFJlc2VydmURX3F1b3RlQXNzZXRXZWlnaHQRX2Jhc2VBc3NldFJlc2VydmUQX2Jhc2VBc3NldFdlaWdodAQPcG9zaXRpb25TaXplQWJzCQEDYWJzAQUNX3Bvc2l0aW9uU2l6ZQQHaXNTaG9ydAkAZgIAAAUNX3Bvc2l0aW9uU2l6ZQQQcG9zaXRpb25Ob3Rpb25hbAMJAAACBQdfb3B0aW9uBQ9QTkxfT1BUSU9OX1NQT1QEE291dFBvc2l0aW9uTm90aW9uYWwICQEWc3dhcE91dHB1dFdpdGhSZXNlcnZlcwgFBm1hcmtldAkBASEBBQdpc1Nob3J0BQ9wb3NpdGlvblNpemVBYnMHBRJfcXVvdGVBc3NldFJlc2VydmUFEV9xdW90ZUFzc2V0V2VpZ2h0BRFfYmFzZUFzc2V0UmVzZXJ2ZQUQX2Jhc2VBc3NldFdlaWdodAJfMQUTb3V0UG9zaXRpb25Ob3Rpb25hbAkBBG11bGQCBQ9wb3NpdGlvblNpemVBYnMJAQ5nZXRPcmFjbGVQcmljZQEFBm1hcmtldAUQcG9zaXRpb25Ob3Rpb25hbAErZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmxCeVZhbHVlcwgGbWFya2V0DV9wb3NpdGlvblNpemUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsEl9xdW90ZUFzc2V0UmVzZXJ2ZRFfcXVvdGVBc3NldFdlaWdodBFfYmFzZUFzc2V0UmVzZXJ2ZRBfYmFzZUFzc2V0V2VpZ2h0B19vcHRpb24DCQAAAgUNX3Bvc2l0aW9uU2l6ZQAACQACAQIVSW52YWxpZCBwb3NpdGlvbiBzaXplBAdpc1Nob3J0CQBmAgAABQ1fcG9zaXRpb25TaXplBBBwb3NpdGlvbk5vdGlvbmFsCQEfZ2V0UG9zaXRpb25BZGp1c3RlZE9wZW5Ob3Rpb25hbAcFBm1hcmtldAUNX3Bvc2l0aW9uU2l6ZQUHX29wdGlvbgUSX3F1b3RlQXNzZXRSZXNlcnZlBRFfcXVvdGVBc3NldFdlaWdodAURX2Jhc2VBc3NldFJlc2VydmUFEF9iYXNlQXNzZXRXZWlnaHQEDXVucmVhbGl6ZWRQbmwDBQdpc1Nob3J0CQBlAgUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsBRBwb3NpdGlvbk5vdGlvbmFsCQBlAgUQcG9zaXRpb25Ob3Rpb25hbAUVX3Bvc2l0aW9uT3Blbk5vdGlvbmFsCQCUCgIFEHBvc2l0aW9uTm90aW9uYWwFDXVucmVhbGl6ZWRQbmwBI2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sAwZtYXJrZXQHX3RyYWRlcgdfb3B0aW9uBAV0dXBsZQkBC2dldFBvc2l0aW9uAgUGbWFya2V0BQdfdHJhZGVyBAxwb3NpdGlvblNpemUIBQV0dXBsZQJfMQQOcG9zaXRpb25NYXJnaW4IBQV0dXBsZQJfMgQUcG9zaXRpb25PcGVuTm90aW9uYWwIBQV0dXBsZQJfMwQRcG9zaXRpb25Mc3RVcGRDUEYIBQV0dXBsZQJfNAkBK2dldFBvc2l0aW9uTm90aW9uYWxBbmRVbnJlYWxpemVkUG5sQnlWYWx1ZXMIBQZtYXJrZXQFDHBvc2l0aW9uU2l6ZQUUcG9zaXRpb25PcGVuTm90aW9uYWwJAQZxdEFzdFIBBQZtYXJrZXQJAQZxdEFzdFcBBQZtYXJrZXQJAQZic0FzdFIBBQZtYXJrZXQJAQZic0FzdFcBBQZtYXJrZXQFB19vcHRpb24BD2NhbGNNYXJnaW5SYXRpbwMNX3JlbWFpbk1hcmdpbghfYmFkRGVidBFfcG9zaXRpb25Ob3Rpb25hbAkBBGRpdmQCCQBlAgUNX3JlbWFpbk1hcmdpbgUIX2JhZERlYnQFEV9wb3NpdGlvbk5vdGlvbmFsARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAwZtYXJrZXQHX3RyYWRlcgdfb3B0aW9uBAZ0dXBsZTEJAQtnZXRQb3NpdGlvbgIFBm1hcmtldAUHX3RyYWRlcgQMcG9zaXRpb25TaXplCAUGdHVwbGUxAl8xBA5wb3NpdGlvbk1hcmdpbggFBnR1cGxlMQJfMgQDcG9uCAUGdHVwbGUxAl8zBBZwb3NpdGlvbkxhc3RVcGRhdGVkQ1BGCAUGdHVwbGUxAl80BBFwb3NpdGlvblRpbWVzdGFtcAgFBnR1cGxlMQJfNQQGdHVwbGUyCQEjZ2V0UG9zaXRpb25Ob3Rpb25hbEFuZFVucmVhbGl6ZWRQbmwDBQZtYXJrZXQFB190cmFkZXIFB19vcHRpb24EEHBvc2l0aW9uTm90aW9uYWwIBQZ0dXBsZTICXzEEDXVucmVhbGl6ZWRQbmwIBQZ0dXBsZTICXzIEBnR1cGxlMwkBMGNhbGNSZW1haW5NYXJnaW5XaXRoRnVuZGluZ1BheW1lbnRBbmRSb2xsb3ZlckZlZQYFBm1hcmtldAUMcG9zaXRpb25TaXplBQ5wb3NpdGlvbk1hcmdpbgUWcG9zaXRpb25MYXN0VXBkYXRlZENQRgURcG9zaXRpb25UaW1lc3RhbXAFDXVucmVhbGl6ZWRQbmwEDHJlbWFpbk1hcmdpbggFBnR1cGxlMwJfMQQHYmFkRGVidAgFBnR1cGxlMwJfMgkBD2NhbGNNYXJnaW5SYXRpbwMFDHJlbWFpbk1hcmdpbgUHYmFkRGVidAUQcG9zaXRpb25Ob3Rpb25hbAEOZ2V0TWFyZ2luUmF0aW8CBm1hcmtldAdfdHJhZGVyCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgMFBm1hcmtldAUHX3RyYWRlcgUPUE5MX09QVElPTl9TUE9UAQlsaXF1aWRhdGUCBm1hcmtldAZ0cmFkZXIEDW1hcmtldEFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBm1hcmtldAQEc3luYwkA/AcEBQ1tYXJrZXRBZGRyZXNzAhlzeW5jVGVybWluYWxQcmljZVRvT3JhY2xlBQNuaWwFA25pbAMJAAACBQRzeW5jBQRzeW5jBA9zcG90TWFyZ2luUmF0aW8JARZnZXRNYXJnaW5SYXRpb0J5T3B0aW9uAwUNbWFya2V0QWRkcmVzcwUGdHJhZGVyBQ9QTkxfT1BUSU9OX1NQT1QEFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8DCQEWaXNPdmVyRmx1Y3R1YXRpb25MaW1pdAEFDW1hcmtldEFkZHJlc3MEEW9yYWNsZU1hcmdpblJhdGlvCQEWZ2V0TWFyZ2luUmF0aW9CeU9wdGlvbgMFDW1hcmtldEFkZHJlc3MFBnRyYWRlcgURUE5MX09QVElPTl9PUkFDTEUJAQR2bWF4AgUPc3BvdE1hcmdpblJhdGlvBRFvcmFjbGVNYXJnaW5SYXRpbwUPc3BvdE1hcmdpblJhdGlvBBBtYWludE1hcmdpblJhdGlvCQEWbWFpbnRlbmFuY2VNYXJnaW5SYXRpbwEFDW1hcmtldEFkZHJlc3MEBWFsbG93AwMDCQEWcmVxdWlyZU1vcmVNYXJnaW5SYXRpbwMFFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8FEG1haW50TWFyZ2luUmF0aW8HCQETcmVxdWlyZU9wZW5Qb3NpdGlvbgIFDW1hcmtldEFkZHJlc3MFBnRyYWRlcgcJAQtpbml0aWFsaXplZAEFDW1hcmtldEFkZHJlc3MHCQEBIQEJAQZwYXVzZWQBBQ1tYXJrZXRBZGRyZXNzBwQDcmVzAwUFYWxsb3cAAQAABBRyZW1haW5pbmdNYXJnaW5SYXRpbwkAZQIFFmxpcXVpZGF0aW9uTWFyZ2luUmF0aW8FEG1haW50TWFyZ2luUmF0aW8JAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCkAwEFA3JlcwIBOwkApAMBBRZsaXF1aWRhdGlvbk1hcmdpblJhdGlvAgE7CQCkAwEFEG1haW50TWFyZ2luUmF0aW8CATsJAKQDAQUUcmVtYWluaW5nTWFyZ2luUmF0aW8JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAF3mcGU=", "chainId": 87, "height": 3520690, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 81NbskXGTc4mMRF2LA86EuzMnvKu8jDBLEKnJJptKHHA Next: 9PnJMJqpzJ6m4zbg6Mmiph7zhnxNqH4q2hebamr4eimw Diff:
OldNewDifferences
348348 if (if (_largerThanOrEqualTo)
349349 then (0 > remainingMarginRatio)
350350 else false)
351- then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
351+ then true
352352 else if (if (!(_largerThanOrEqualTo))
353353 then (remainingMarginRatio >= 0)
354354 else false)
355- then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
355+ then true
356356 else true
357357 }
358358
398398
399399
400400 func requireOpenPosition (market,_trader) = if ((getPosition(market, _trader)._1 == 0))
401- then throw("No open position")
401+ then false
402402 else true
403403
404404
701701 }
702702 else spotMarginRatio
703703 let maintMarginRatio = maintenanceMarginRatio(marketAddress)
704- let allow = if (if (if (if (requireMoreMarginRatio(liquidationMarginRatio, maintMarginRatio, false))
704+ let allow = if (if (if (requireMoreMarginRatio(liquidationMarginRatio, maintMarginRatio, false))
705705 then requireOpenPosition(marketAddress, trader)
706706 else false)
707707 then initialized(marketAddress)
708708 else false)
709709 then !(paused(marketAddress))
710- else false)
711- then !(isMarketClosed(marketAddress))
712710 else false
713711 let res = if (allow)
714712 then 1
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_positionAsset = "k_positionAsset"
2323
2424 let k_positionFee = "k_positionFee"
2525
2626 let k_positionLastUpdatedTimestamp = "k_positionTimestamp"
2727
2828 let k_initialized = "k_initialized"
2929
3030 let k_paused = "k_paused"
3131
3232 let k_closeOnly = "k_closeOnly"
3333
3434 let k_fee = "k_fee"
3535
3636 let k_rolloverFee = "k_rollover_fee"
3737
3838 let k_fundingPeriod = "k_fundingPeriod"
3939
4040 let k_initMarginRatio = "k_initMarginRatio"
4141
4242 let k_maintenanceMarginRatio = "k_mmr"
4343
4444 let k_liquidationFeeRatio = "k_liquidationFeeRatio"
4545
4646 let k_partialLiquidationRatio = "k_partLiquidationRatio"
4747
4848 let k_spreadLimit = "k_spreadLimit"
4949
5050 let k_maxPriceImpact = "k_maxPriceImpact"
5151
5252 let k_maxPriceSpread = "k_maxPriceSpread"
5353
5454 let k_maxOpenNotional = "k_maxOpenNotional"
5555
5656 let k_feeToStakersPercent = "k_feeToStakersPercent"
5757
5858 let k_maxOracleDelay = "k_maxOracleDelay"
5959
6060 let k_fundingMode = "k_fundingMode"
6161
6262 let k_lastDataStr = "k_lastDataStr"
6363
6464 let k_lastMinuteId = "k_lastMinuteId"
6565
6666 let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
6767
6868 let k_twapDataLastPrice = "k_twapDataLastPrice"
6969
7070 let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
7171
7272 let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
7373
7474 let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
7575
7676 let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
7777
7878 let k_longFundingRate = "k_longFundingRate"
7979
8080 let k_shortFundingRate = "k_shortFundingRate"
8181
8282 let k_quoteAssetReserve = "k_qtAstR"
8383
8484 let k_baseAssetReserve = "k_bsAstR"
8585
8686 let k_quoteAssetWeight = "k_qtAstW"
8787
8888 let k_baseAssetWeight = "k_bsAstW"
8989
9090 let k_totalPositionSize = "k_totalPositionSize"
9191
9292 let k_totalLongPositionSize = "k_totalLongPositionSize"
9393
9494 let k_totalShortPositionSize = "k_totalShortPositionSize"
9595
9696 let k_openInterestNotional = "k_openInterestNotional"
9797
9898 let k_openInterestShort = "k_openInterestShort"
9999
100100 let k_openInterestLong = "k_openInterestLong"
101101
102102 let k_lastTx = "k_lastTx"
103103
104104 let k_coordinatorAddress = "k_coordinatorAddress"
105105
106106 let k_vault_address = "k_vault_address"
107107
108108 let k_admin_address = "k_admin_address"
109109
110110 let k_quote_asset = "k_quote_asset"
111111
112112 let k_quote_staking = "k_quote_staking"
113113
114114 let k_staking_address = "k_staking_address"
115115
116116 let k_miner_address = "k_miner_address"
117117
118118 let k_orders_address = "k_orders_address"
119119
120120 let k_referral_address = "k_referral_address"
121121
122122 let k_exchange_address = "k_exchange_address"
123123
124124 let k_nft_manager_address = "k_nft_manager_address"
125125
126126 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
127127
128128
129129 func coordinator (market) = valueOrErrorMessage(addressFromString(getStringValue(market, k_coordinatorAddress)), "Coordinator not set")
130130
131131
132132 func adminAddress (market) = addressFromString(getStringValue(coordinator(market), k_admin_address))
133133
134134
135135 func quoteAsset (market) = fromBase58String(getStringValue(coordinator(market), k_quote_asset))
136136
137137
138138 func quoteAssetStaking (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_quote_staking)), "Quote asset staking not set")
139139
140140
141141 func stakingAddress (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_staking_address)), "Staking not set")
142142
143143
144144 func vaultAddress (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_vault_address)), "Vault not set")
145145
146146
147147 func minerAddress (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_miner_address)), "Miner not set")
148148
149149
150150 func ordersAddress (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_orders_address)), "Orders not set")
151151
152152
153153 func referralAddress (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_referral_address)), "Referral not set")
154154
155155
156156 func nftManagerAddress (market) = valueOrErrorMessage(addressFromString(getStringValue(coordinator(market), k_nft_manager_address)), "NFT Manager not set")
157157
158158
159159 let k_token_param = "k_token_param"
160160
161161 let k_token_type = "k_token_type"
162162
163163 let FEE_REDUCTION_TOKEN_TYPE = "fee_reduction"
164164
165165 let DIR_LONG = 1
166166
167167 let DIR_SHORT = 2
168168
169169 let TWAP_INTERVAL = 15
170170
171171 let SECONDS = 1000
172172
173173 let DECIMAL_NUMBERS = 6
174174
175175 let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
176176
177177 let MINUTES_IN_YEAR = (525600 * DECIMAL_UNIT)
178178
179179 let ONE_DAY = (86400 * DECIMAL_UNIT)
180180
181181 let PNL_OPTION_SPOT = 1
182182
183183 let PNL_OPTION_ORACLE = 2
184184
185185 let FUNDING_ASYMMETRIC = 1
186186
187187 let FUNDING_SYMMETRIC = 2
188188
189189 func s (_x) = (toString(_x) + ",")
190190
191191
192192 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
193193
194194
195195 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
196196
197197
198198 func bdivd (_x,_y) = fraction(_x, toBigInt(DECIMAL_UNIT), _y, HALFEVEN)
199199
200200
201201 func bmuld (_x,_y) = fraction(_x, _y, toBigInt(DECIMAL_UNIT), HALFEVEN)
202202
203203
204204 func abs (_x) = if ((_x > 0))
205205 then _x
206206 else -(_x)
207207
208208
209209 func vmax (_x,_y) = if ((_x >= _y))
210210 then _x
211211 else _y
212212
213213
214214 func listToStr (_list) = if ((size(_list) == 0))
215215 then ""
216216 else makeString(_list, ",")
217217
218218
219219 func strToList (_str) = if ((_str == ""))
220220 then nil
221221 else split(_str, ",")
222222
223223
224224 func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
225225 then (removeByIndex(_list, 0) :+ _value)
226226 else (_list :+ _value)
227227
228228
229229 func int (market,k) = valueOrErrorMessage(getInteger(market, k), ("no value for " + k))
230230
231231
232232 func intOr (market,k,def) = valueOrElse(getInteger(market, k), def)
233233
234234
235235 func strA (_address,_key) = {
236236 let val = valueOrErrorMessage(getString(_address, _key), ("No value for key " + _key))
237237 val
238238 }
239239
240240
241241 func intA (_address,_key) = {
242242 let val = valueOrErrorMessage(getInteger(_address, _key), ("No value for key " + _key))
243243 val
244244 }
245245
246246
247247 func cbalance (market) = int(market, k_balance)
248248
249249
250250 func fee (market) = int(market, k_fee)
251251
252252
253253 func rolloverFeeRate (market) = int(market, k_rolloverFee)
254254
255255
256256 func initMarginRatio (market) = int(market, k_initMarginRatio)
257257
258258
259259 func qtAstR (market) = int(market, k_quoteAssetReserve)
260260
261261
262262 func bsAstR (market) = int(market, k_baseAssetReserve)
263263
264264
265265 func qtAstW (market) = intOr(market, k_quoteAssetWeight, DECIMAL_UNIT)
266266
267267
268268 func bsAstW (market) = intOr(market, k_baseAssetWeight, DECIMAL_UNIT)
269269
270270
271271 func totalPositionSize (market) = int(market, k_totalPositionSize)
272272
273273
274274 func openInterestNotional (market) = int(market, k_openInterestNotional)
275275
276276
277277 func openInterestShort (market) = int(market, k_openInterestShort)
278278
279279
280280 func openInterestLong (market) = int(market, k_openInterestLong)
281281
282282
283283 func nextFundingBlockTimestamp (market) = int(market, k_nextFundingBlock)
284284
285285
286286 func fundingPeriodRaw (market) = int(market, k_fundingPeriod)
287287
288288
289289 func fundingPeriodDecimal (market) = (fundingPeriodRaw(market) * DECIMAL_UNIT)
290290
291291
292292 func fundingPeriodSeconds (market) = (fundingPeriodRaw(market) * SECONDS)
293293
294294
295295 func maintenanceMarginRatio (market) = int(market, k_maintenanceMarginRatio)
296296
297297
298298 func liquidationFeeRatio (market) = int(market, k_liquidationFeeRatio)
299299
300300
301301 func partialLiquidationRatio (market) = int(market, k_partialLiquidationRatio)
302302
303303
304304 func spreadLimit (market) = int(market, k_spreadLimit)
305305
306306
307307 func maxPriceImpact (market) = int(market, k_maxPriceImpact)
308308
309309
310310 func maxPriceSpread (market) = int(market, k_maxPriceSpread)
311311
312312
313313 func maxOpenNotional (market) = int(market, k_maxOpenNotional)
314314
315315
316316 func latestLongCumulativePremiumFraction (market) = int(market, k_latestLongCumulativePremiumFraction)
317317
318318
319319 func latestShortCumulativePremiumFraction (market) = int(market, k_latestShortCumulativePremiumFraction)
320320
321321
322322 func totalShortPositionSize (market) = int(market, k_totalShortPositionSize)
323323
324324
325325 func totalLongPositionSize (market) = int(market, k_totalLongPositionSize)
326326
327327
328328 func lastSequence (market) = intOr(market, k_sequence, 0)
329329
330330
331331 func feeToStakersPercent (market) = int(market, k_feeToStakersPercent)
332332
333333
334334 func maxOracleDelay (market) = int(market, k_maxOracleDelay)
335335
336336
337337 func fundingMode (market) = intOr(market, k_fundingMode, FUNDING_ASYMMETRIC)
338338
339339
340340 func lastTimestamp () = lastBlock.timestamp
341341
342342
343343 func getActualCaller (market,i) = valueOrElse(getString(ordersAddress(market), "k_sender"), toString(i.caller))
344344
345345
346346 func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
347347 let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
348348 if (if (_largerThanOrEqualTo)
349349 then (0 > remainingMarginRatio)
350350 else false)
351- then throw(((("Invalid margin: " + toString(_marginRatio)) + " < ") + toString(_baseMarginRatio)))
351+ then true
352352 else if (if (!(_largerThanOrEqualTo))
353353 then (remainingMarginRatio >= 0)
354354 else false)
355- then throw(((("Invalid margin: " + toString(_marginRatio)) + " > ") + toString(_baseMarginRatio)))
355+ then true
356356 else true
357357 }
358358
359359
360360 func latestCumulativePremiumFraction (market,_positionSize) = if ((_positionSize == 0))
361361 then throw("Should not be called with _positionSize == 0")
362362 else if ((_positionSize > 0))
363363 then latestLongCumulativePremiumFraction(market)
364364 else latestShortCumulativePremiumFraction(market)
365365
366366
367367 func getPosition (market,_trader) = {
368368 let positionSizeOpt = getInteger(market, toCompositeKey(k_positionSize, _trader))
369369 match positionSizeOpt {
370370 case positionSize: Int =>
371371 $Tuple5(positionSize, getIntegerValue(market, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(market, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(market, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)), getIntegerValue(market, toCompositeKey(k_positionLastUpdatedTimestamp, _trader)))
372372 case _ =>
373373 $Tuple5(0, 0, 0, 0, 0)
374374 }
375375 }
376376
377377
378378 func getPositionAsset (market,_trader) = {
379379 let positionAssetOpt = getString(market, toCompositeKey(k_positionAsset, _trader))
380380 match positionAssetOpt {
381381 case positionAsset: String =>
382382 positionAsset
383383 case _ =>
384384 toBase58String(quoteAsset(market))
385385 }
386386 }
387387
388388
389389 func getPositionFee (market,_trader) = {
390390 let positionFeeOpt = getInteger(market, toCompositeKey(k_positionFee, _trader))
391391 match positionFeeOpt {
392392 case positionFee: Int =>
393393 positionFee
394394 case _ =>
395395 fee(market)
396396 }
397397 }
398398
399399
400400 func requireOpenPosition (market,_trader) = if ((getPosition(market, _trader)._1 == 0))
401- then throw("No open position")
401+ then false
402402 else true
403403
404404
405405 func getOracleData (market,key) = {
406406 let oracleDataStr = getString(market, key)
407407 if (if (isDefined(oracleDataStr))
408408 then (value(oracleDataStr) != "")
409409 else false)
410410 then {
411411 let oracleData = split(value(oracleDataStr), ",")
412412 let oracleAddress = valueOrErrorMessage(addressFromString(oracleData[0]), ("Invalid oracle address in: " + value(oracleDataStr)))
413413 let priceKey = oracleData[1]
414414 let blockKey = oracleData[2]
415415 let openKey = oracleData[3]
416416 $Tuple4(oracleAddress, priceKey, blockKey, openKey)
417417 }
418418 else unit
419419 }
420420
421421
422422 func initialized (market) = valueOrElse(getBoolean(market, k_initialized), false)
423423
424424
425425 func paused (market) = valueOrElse(getBoolean(market, k_paused), false)
426426
427427
428428 func closeOnly (market) = valueOrElse(getBoolean(market, k_closeOnly), false)
429429
430430
431431 func updateReserve (market,_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
432432 then {
433433 let newBase = (bsAstR(market) - _baseAssetAmount)
434434 if ((0 >= newBase))
435435 then throw("Tx lead to base asset reserve <= 0, revert")
436436 else $Tuple3((qtAstR(market) + _quoteAssetAmount), newBase, (totalPositionSize(market) + _baseAssetAmount))
437437 }
438438 else {
439439 let newQuote = (qtAstR(market) - _quoteAssetAmount)
440440 if ((0 >= newQuote))
441441 then throw("Tx lead to base quote reserve <= 0, revert")
442442 else $Tuple3(newQuote, (bsAstR(market) + _baseAssetAmount), (totalPositionSize(market) - _baseAssetAmount))
443443 }
444444
445445
446446 func calcInvariant (_qtAstR,_bsAstR) = {
447447 let bqtAstR = toBigInt(_qtAstR)
448448 let bbsAstR = toBigInt(_bsAstR)
449449 bmuld(bqtAstR, bbsAstR)
450450 }
451451
452452
453453 func swapInput (market,_isAdd,_quoteAssetAmount) = {
454454 let _qtAstR = qtAstR(market)
455455 let _bsAstR = bsAstR(market)
456456 let _qtAstW = qtAstW(market)
457457 let _bsAstW = bsAstW(market)
458458 let quoteAssetAmountAdjusted = divd(_quoteAssetAmount, _qtAstW)
459459 let k = calcInvariant(_qtAstR, _bsAstR)
460460 let quoteAssetReserveAfter = if (_isAdd)
461461 then (_qtAstR + quoteAssetAmountAdjusted)
462462 else (_qtAstR - quoteAssetAmountAdjusted)
463463 let baseAssetReserveAfter = toInt(bdivd(k, toBigInt(quoteAssetReserveAfter)))
464464 let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
465465 let amountBaseAssetBought = if (_isAdd)
466466 then amountBaseAssetBoughtAbs
467467 else -(amountBaseAssetBoughtAbs)
468468 let tuple = updateReserve(market, _isAdd, quoteAssetAmountAdjusted, amountBaseAssetBoughtAbs)
469469 let quoteAssetReserveAfter1 = tuple._1
470470 let baseAssetReserveAfter1 = tuple._2
471471 let totalPositionSizeAfter1 = tuple._3
472472 let priceBefore = divd(muld(_qtAstR, _qtAstW), muld(_bsAstR, _bsAstW))
473473 let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
474474 let priceDiff = abs((priceBefore - marketPrice))
475475 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
476476 let maxPriceImpactValue = maxPriceImpact(market)
477477 if ((priceImpact > maxPriceImpactValue))
478478 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)))
479479 else $Tuple4(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1)
480480 }
481481
482482
483483 func calcRolloverFee (market,_oldPositionMargin,_oldPositionLastUpdatedTimestamp) = {
484484 let positionMinutes = ((((lastTimestamp() - _oldPositionLastUpdatedTimestamp) / 1000) / 60) * DECIMAL_UNIT)
485485 let rolloverFee = divd(muld(muld(_oldPositionMargin, positionMinutes), rolloverFeeRate(market)), MINUTES_IN_YEAR)
486486 rolloverFee
487487 }
488488
489489
490490 func calcRemainMarginWithFundingPaymentAndRolloverFee (market,_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_oldPositionLastUpdatedTimestamp,_marginDelta) = {
491491 let fundingPayment = if ((_oldPositionSize != 0))
492492 then {
493493 let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(market, _oldPositionSize)
494494 muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
495495 }
496496 else 0
497497 let rolloverFee = calcRolloverFee(market, _oldPositionMargin, _oldPositionLastUpdatedTimestamp)
498498 let signedMargin = (((_marginDelta - rolloverFee) - fundingPayment) + _oldPositionMargin)
499499 let tuple = if ((0 > signedMargin))
500500 then $Tuple2(0, abs(signedMargin))
501501 else $Tuple2(abs(signedMargin), 0)
502502 let remainMargin = tuple._1
503503 let badDebt = tuple._2
504504 $Tuple4(remainMargin, badDebt, fundingPayment, rolloverFee)
505505 }
506506
507507
508508 func swapOutputWithReserves (market,_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
509509 let priceBefore = divd(muld(_quoteAssetReserve, _quoteAssetWeight), muld(_baseAssetReserve, _baseAssetWeight))
510510 if ((_baseAssetAmount == 0))
511511 then throw("Invalid base asset amount")
512512 else {
513513 let k = calcInvariant(_quoteAssetReserve, _baseAssetReserve)
514514 let baseAssetPoolAmountAfter = if (_isAdd)
515515 then (_baseAssetReserve + _baseAssetAmount)
516516 else (_baseAssetReserve - _baseAssetAmount)
517517 let quoteAssetAfter = toInt(bdivd(k, toBigInt(baseAssetPoolAmountAfter)))
518518 let quoteAssetDelta = abs((quoteAssetAfter - _quoteAssetReserve))
519519 let quoteAssetSold = muld(quoteAssetDelta, _quoteAssetWeight)
520520 let maxPriceImpactValue = maxPriceImpact(market)
521521 let tuple = updateReserve(market, !(_isAdd), quoteAssetDelta, _baseAssetAmount)
522522 let quoteAssetReserveAfter1 = tuple._1
523523 let baseAssetReserveAfter1 = tuple._2
524524 let totalPositionSizeAfter1 = tuple._3
525525 let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
526526 let priceDiff = abs((priceBefore - marketPrice))
527527 let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
528528 if (if ((priceImpact > maxPriceImpactValue))
529529 then _checkMaxPriceImpact
530530 else false)
531531 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)))
532532 else $Tuple7(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, (totalLongPositionSize(market) - (if (_isAdd)
533533 then abs(_baseAssetAmount)
534534 else 0)), (totalShortPositionSize(market) - (if (!(_isAdd))
535535 then abs(_baseAssetAmount)
536536 else 0)), priceImpact)
537537 }
538538 }
539539
540540
541541 func swapOutput (market,_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(market, _isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(market), qtAstW(market), bsAstR(market), bsAstW(market))
542542
543543
544544 func getOraclePriceValue (market,oracle,priceKey,blockKey) = {
545545 let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
546546 if ((blockKey != ""))
547547 then {
548548 let currentBlock = lastBlock.height
549549 let lastOracleBlock = valueOrErrorMessage(getInteger(oracle, blockKey), ((("Can not get oracle block. Oracle: " + toString(oracle)) + " key: ") + blockKey))
550550 if (((currentBlock - lastOracleBlock) > maxOracleDelay(market)))
551551 then throw(((("Oracle stale data. Last oracle block: " + toString(lastOracleBlock)) + " current block: ") + toString(currentBlock)))
552552 else lastValue
553553 }
554554 else lastValue
555555 }
556556
557557
558558 func getOraclePrice (market) = {
559559 let baseOracle = valueOrErrorMessage(getOracleData(market, k_baseOracle), "No base asset oracle data")
560560 let baseOraclePrice = getOraclePriceValue(market, baseOracle._1, baseOracle._2, baseOracle._3)
561561 let quoteOracle = getOracleData(market, k_quoteOracle)
562562 let quoteOraclePrice = if (isDefined(quoteOracle))
563563 then {
564564 let quoteOracleV = value(quoteOracle)
565565 getOraclePriceValue(market, quoteOracleV._1, quoteOracleV._2, quoteOracleV._3)
566566 }
567567 else DECIMAL_UNIT
568568 divd(baseOraclePrice, quoteOraclePrice)
569569 }
570570
571571
572572 func isMarketClosed (market) = {
573573 let baseOracle = valueOrErrorMessage(getOracleData(market, k_baseOracle), "No base asset oracle data")
574574 let oracle = baseOracle._1
575575 let openKey = baseOracle._4
576576 if ((openKey != ""))
577577 then {
578578 let isOpen = valueOrErrorMessage(getBoolean(oracle, openKey), ((("Can not get oracle is open/closed. Oracle: " + toString(oracle)) + " key: ") + openKey))
579579 !(isOpen)
580580 }
581581 else false
582582 }
583583
584584
585585 func absPriceDiff (_oraclePrice,_quoteAssetReserve,_baseAssetReserve,_qtAstW,_bsAstW) = {
586586 let priceAfter = divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
587587 let averagePrice = divd((_oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
588588 let absPriceDiff = divd(abs((_oraclePrice - priceAfter)), averagePrice)
589589 absPriceDiff
590590 }
591591
592592
593593 func requireNotOverSpreadLimit (market,_quoteAssetReserve,_baseAssetReserve) = {
594594 let oraclePrice = getOraclePrice(market)
595595 let _qtAstW = qtAstW(market)
596596 let _bsAstW = bsAstW(market)
597597 let absPriceDiffBefore = absPriceDiff(oraclePrice, qtAstR(market), bsAstR(market), _qtAstW, _bsAstW)
598598 let absPriceDiffAfter = absPriceDiff(oraclePrice, _quoteAssetReserve, _baseAssetReserve, _qtAstW, _bsAstW)
599599 if (if ((absPriceDiffAfter > maxPriceSpread(market)))
600600 then (absPriceDiffAfter > absPriceDiffBefore)
601601 else false)
602602 then throw(((("Price spread " + toString(absPriceDiffAfter)) + " > max price spread ") + toString(maxPriceSpread(market))))
603603 else true
604604 }
605605
606606
607607 func requireNotOverMaxOpenNotional (market,_longOpenNotional,_shortOpenNotional) = {
608608 let _maxOpenNotional = maxOpenNotional(market)
609609 if ((_longOpenNotional > _maxOpenNotional))
610610 then throw(((("Long open notional " + toString(_longOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
611611 else if ((_shortOpenNotional > _maxOpenNotional))
612612 then throw(((("Short open notional " + toString(_shortOpenNotional)) + " > max open notional ") + toString(_maxOpenNotional)))
613613 else true
614614 }
615615
616616
617617 func getSpotPrice (market) = {
618618 let _quoteAssetReserve = qtAstR(market)
619619 let _baseAssetReserve = bsAstR(market)
620620 let _qtAstW = qtAstW(market)
621621 let _bsAstW = bsAstW(market)
622622 divd(muld(_quoteAssetReserve, _qtAstW), muld(_baseAssetReserve, _bsAstW))
623623 }
624624
625625
626626 func isOverFluctuationLimit (market) = {
627627 let oraclePrice = getOraclePrice(market)
628628 let currentPrice = getSpotPrice(market)
629629 (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit(market))
630630 }
631631
632632
633633 func getPositionAdjustedOpenNotional (market,_positionSize,_option,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight) = {
634634 let positionSizeAbs = abs(_positionSize)
635635 let isShort = (0 > _positionSize)
636636 let positionNotional = if ((_option == PNL_OPTION_SPOT))
637637 then {
638638 let outPositionNotional = swapOutputWithReserves(market, !(isShort), positionSizeAbs, false, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)._1
639639 outPositionNotional
640640 }
641641 else muld(positionSizeAbs, getOraclePrice(market))
642642 positionNotional
643643 }
644644
645645
646646 func getPositionNotionalAndUnrealizedPnlByValues (market,_positionSize,_positionOpenNotional,_quoteAssetReserve,_quoteAssetWeight,_baseAssetReserve,_baseAssetWeight,_option) = if ((_positionSize == 0))
647647 then throw("Invalid position size")
648648 else {
649649 let isShort = (0 > _positionSize)
650650 let positionNotional = getPositionAdjustedOpenNotional(market, _positionSize, _option, _quoteAssetReserve, _quoteAssetWeight, _baseAssetReserve, _baseAssetWeight)
651651 let unrealizedPnl = if (isShort)
652652 then (_positionOpenNotional - positionNotional)
653653 else (positionNotional - _positionOpenNotional)
654654 $Tuple2(positionNotional, unrealizedPnl)
655655 }
656656
657657
658658 func getPositionNotionalAndUnrealizedPnl (market,_trader,_option) = {
659659 let tuple = getPosition(market, _trader)
660660 let positionSize = tuple._1
661661 let positionMargin = tuple._2
662662 let positionOpenNotional = tuple._3
663663 let positionLstUpdCPF = tuple._4
664664 getPositionNotionalAndUnrealizedPnlByValues(market, positionSize, positionOpenNotional, qtAstR(market), qtAstW(market), bsAstR(market), bsAstW(market), _option)
665665 }
666666
667667
668668 func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
669669
670670
671671 func getMarginRatioByOption (market,_trader,_option) = {
672672 let tuple1 = getPosition(market, _trader)
673673 let positionSize = tuple1._1
674674 let positionMargin = tuple1._2
675675 let pon = tuple1._3
676676 let positionLastUpdatedCPF = tuple1._4
677677 let positionTimestamp = tuple1._5
678678 let tuple2 = getPositionNotionalAndUnrealizedPnl(market, _trader, _option)
679679 let positionNotional = tuple2._1
680680 let unrealizedPnl = tuple2._2
681681 let tuple3 = calcRemainMarginWithFundingPaymentAndRolloverFee(market, positionSize, positionMargin, positionLastUpdatedCPF, positionTimestamp, unrealizedPnl)
682682 let remainMargin = tuple3._1
683683 let badDebt = tuple3._2
684684 calcMarginRatio(remainMargin, badDebt, positionNotional)
685685 }
686686
687687
688688 func getMarginRatio (market,_trader) = getMarginRatioByOption(market, _trader, PNL_OPTION_SPOT)
689689
690690
691691 func liquidate (market,trader) = {
692692 let marketAddress = addressFromStringValue(market)
693693 let sync = invoke(marketAddress, "syncTerminalPriceToOracle", nil, nil)
694694 if ((sync == sync))
695695 then {
696696 let spotMarginRatio = getMarginRatioByOption(marketAddress, trader, PNL_OPTION_SPOT)
697697 let liquidationMarginRatio = if (isOverFluctuationLimit(marketAddress))
698698 then {
699699 let oracleMarginRatio = getMarginRatioByOption(marketAddress, trader, PNL_OPTION_ORACLE)
700700 vmax(spotMarginRatio, oracleMarginRatio)
701701 }
702702 else spotMarginRatio
703703 let maintMarginRatio = maintenanceMarginRatio(marketAddress)
704- let allow = if (if (if (if (requireMoreMarginRatio(liquidationMarginRatio, maintMarginRatio, false))
704+ let allow = if (if (if (requireMoreMarginRatio(liquidationMarginRatio, maintMarginRatio, false))
705705 then requireOpenPosition(marketAddress, trader)
706706 else false)
707707 then initialized(marketAddress)
708708 else false)
709709 then !(paused(marketAddress))
710- else false)
711- then !(isMarketClosed(marketAddress))
712710 else false
713711 let res = if (allow)
714712 then 1
715713 else 0
716714 let remainingMarginRatio = (liquidationMarginRatio - maintMarginRatio)
717715 throw(((((((toString(res) + ";") + toString(liquidationMarginRatio)) + ";") + toString(maintMarginRatio)) + ";") + toString(remainingMarginRatio)))
718716 }
719717 else throw("Strict value is not equal to itself.")
720718 }
721719
722720
723721

github/deemru/w8io/0e76f2f 
78.39 ms