tx · 5ty41AZR2LfJYwct3k3w9JVDW3W2uBMqz9ixrPWsiGaT 3MyPDBgBTqFuYMvY7MmL36MXyLavvvF7xZu: -0.02000000 Waves 2025.02.04 16:12 [3489019] smart account 3MyPDBgBTqFuYMvY7MmL36MXyLavvvF7xZu > SELF 0.00000000 Waves
{ "type": 13, "id": "5ty41AZR2LfJYwct3k3w9JVDW3W2uBMqz9ixrPWsiGaT", "fee": 2000000, "feeAssetId": null, "timestamp": 1738674827586, "version": 2, "chainId": 84, "sender": "3MyPDBgBTqFuYMvY7MmL36MXyLavvvF7xZu", "senderPublicKey": "EySEzs3eDHZUXVeYi92SuyJLMgJutuipHwC5KR1hbt6a", "proofs": [ "Ebwwd9HzCkPRs9RYzacK4a8Ze4VNKgdrPBNa3v436845iWaTB7B8tzDgwBvtydmfwrxGt92oH9ciDNvSspsMy1F" ], "script": "base64:BwI8CAISAwoBAhIAEgQKAggBEgASBAoCCAESBAoCCAgSAwoBCBIECgIIARIDCgEBEgMKAQgSAwoBCBIDCgEIEQARcmVxdWlyZWRXWFhBbW91bnQAgMivoCUAFWN5Y2xlRHVyYXRpb25JbkJsb2NrcwDoBwAYZW1lcmdlbmN5Vm90aW5nVGhyZXNob2xkAAoADXRvdGFsVm90ZXNrZXkCCnRvdGFsVm90ZXMACnd4eEFzc2V0SWQJARFAZXh0ck5hdGl2ZSgxMDU3KQECDnByb2plY3RBc3NldElkAA14V2F2ZXNBc3NldElkCQERQGV4dHJOYXRpdmUoMTA1NykBAg14V2F2ZXNBc3NldElkAAxjdXJyZW50Q3ljbGUJAGkCCQBlAggFCWxhc3RCbG9jawZoZWlnaHQJARFAZXh0ck5hdGl2ZSgxMDU1KQECCnN0YXJ0QmxvY2sFFWN5Y2xlRHVyYXRpb25JbkJsb2NrcwAgY3VycmVudEN5Y2xlUmVxdWVzdGVkV2l0aGRyYXdhbHMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkArAICAhdjeWNsZVJlcXVlc3RlZFdpdGhkcmF3OgkApAMBBQxjdXJyZW50Q3ljbGUAAAAdY3VycmVudEN5Y2xlUmVxdWVzdGVkRGVwb3NpdHMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkArAICAhZjeWNsZVJlcXVlc3RlZERlcG9zaXQ6CQCkAwEFDGN1cnJlbnRDeWNsZQAAAAp0b3RhbFZvdGVzCQERQGV4dHJOYXRpdmUoMTA1NSkBBQ10b3RhbFZvdGVza2V5ARZhc3NlcnRWYWxpZGF0b3JBZGRyZXNzARB2YWxpZGF0b3JBZGRyZXNzAwkBCWlzRGVmaW5lZAEJAJ0IAgUEdGhpcwkArAICAgp2YWxpZGF0b3I6CQClCAEFEHZhbGlkYXRvckFkZHJlc3MFBHVuaXQJAAIBAhFVbmtub3duIHZhbGlkYXRvcgEQYXNzZXJ0T25lUGF5bWVudAEKaW52b2NhdGlvbgMJAQIhPQIJAJADAQgFCmludm9jYXRpb24IcGF5bWVudHMAAQkAAgECD05vdCBvbmUgcGF5bWVudAUEdW5pdAESYXNzZXJ0UGF5bWVudEFzc2V0AgppbnZvY2F0aW9uDWV4cGVjdGVkVG9rZW4DCQECIT0CCAkAkQMCCAUKaW52b2NhdGlvbghwYXltZW50cwAAB2Fzc2V0SWQFDWV4cGVjdGVkVG9rZW4JAAIBAhNVbmV4cGVjdGVkIGFzc2V0IGlkBQR1bml0AQphc3NlcnRVaW50AQF2AwkAZgIAAAUBdgkAAgECDEludmFsaWQgdWludAUEdW5pdAEbYXNzZXJ0QWN0aXZlVmFsaWRhdG9yU3RhdHVzARB2YWxpZGF0b3JBZGRyZXNzBBJ2YWxpZGF0b3JTdGF0dXNLZXkJAKwCAgIQdmFsaWRhdG9yU3RhdHVzOgkApQgBBRB2YWxpZGF0b3JBZGRyZXNzAwkBASEBCQERQGV4dHJOYXRpdmUoMTA1NikBBRJ2YWxpZGF0b3JTdGF0dXNLZXkJAAIBAhJVbmFjdGl2ZSB2YWxpZGF0b3IFBHVuaXQBG2Fzc2VydEN5Y2xlTG93ZXJUaGF0Q3VycmVudAEFY3ljbGUDCQBmAgUMY3VycmVudEN5Y2xlBQVjeWNsZQUEdW5pdAkAAgECDUludmFsaWQgY3ljbGUBFmFzc2VydENhbGxlcklzQ29udHJhY3QBCmludm9jYXRpb24DCQECIT0CBQR0aGlzCAUKaW52b2NhdGlvbgZjYWxsZXIJAAIBAgxVbmF1dGhvcml6ZWQFBHVuaXQMCmludm9jYXRpb24BBGluaXQBCnd4eFRva2VuSWQEC2NhbGxlckNoZWNrCQEWYXNzZXJ0Q2FsbGVySXNDb250cmFjdAEFCmludm9jYXRpb24DCQAAAgULY2FsbGVyQ2hlY2sFC2NhbGxlckNoZWNrAwkBCWlzRGVmaW5lZAEJAKEIAQIOcHJvamVjdEFzc2V0SWQJAAIBAgtJbml0aWFsaXplZAQFaXNzdWUJAMIIBQIGeFdhdmVzAgZ4V2F2ZXMAAAAIBgQPeFdhdmVzQXNzZXRJZElkCQC4CAEFBWlzc3VlCQDMCAIFBWlzc3VlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ10b3RhbFZvdGVza2V5AAAJAMwIAgkBC0JpbmFyeUVudHJ5AgIOcHJvamVjdEFzc2V0SWQFCnd4eFRva2VuSWQJAMwIAgkBC0JpbmFyeUVudHJ5AgINeFdhdmVzQXNzZXRJZAUPeFdhdmVzQXNzZXRJZElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgpzdGFydEJsb2NrCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgIWdG90YWxSZXF1ZXN0ZWRXaXRoZHJhdwAACQDMCAIJAQxJbnRlZ2VyRW50cnkCAhFyZXF1aXJlZFdYWEFtb3VudAURcmVxdWlyZWRXWFhBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICGGVtZXJnZW5jeVZvdGluZ1RocmVzaG9sZAUYZW1lcmdlbmN5Vm90aW5nVGhyZXNob2xkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEOcmVxdWVzdERlcG9zaXQABBFfYXNzZXJ0T25lUGF5bWVudAkBEGFzc2VydE9uZVBheW1lbnQBBQppbnZvY2F0aW9uAwkAAAIFEV9hc3NlcnRPbmVQYXltZW50BRFfYXNzZXJ0T25lUGF5bWVudAQTX2Fzc2VydFBheW1lbnRBc3NldAkBEmFzc2VydFBheW1lbnRBc3NldAIFCmludm9jYXRpb24FBHVuaXQDCQAAAgUTX2Fzc2VydFBheW1lbnRBc3NldAUTX2Fzc2VydFBheW1lbnRBc3NldAQLd2F2ZXNBbW91bnQICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAGYW1vdW50BAljYWxsZXJLZXkJAKUIAQgFCmludm9jYXRpb24GY2FsbGVyBBNyZXF1ZXN0ZWREZXBvc2l0S2V5CQCsAgIJAKwCAgkArAICAhFyZXF1ZXN0ZWREZXBvc2l0OgUJY2FsbGVyS2V5AgF8CQCkAwEFDGN1cnJlbnRDeWNsZQQRcmVxdWVzdGVkRGVwb3NpdHMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUTcmVxdWVzdGVkRGVwb3NpdEtleQAABBZ0b3RhbFJlcXVlc3RlZERlcG9zaXRzCQELdmFsdWVPckVsc2UCCQCfCAEJAKwCAgIWY3ljbGVSZXF1ZXN0ZWREZXBvc2l0OgkApAMBBQxjdXJyZW50Q3ljbGUAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUTcmVxdWVzdGVkRGVwb3NpdEtleQkAZAIFEXJlcXVlc3RlZERlcG9zaXRzBQt3YXZlc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhZjeWNsZVJlcXVlc3RlZERlcG9zaXQ6CQCkAwEFDGN1cnJlbnRDeWNsZQkAZAIFFnRvdGFsUmVxdWVzdGVkRGVwb3NpdHMFC3dhdmVzQW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEOcHJvY2Vzc0RlcG9zaXQCCXJlY2lwaWVudAVjeWNsZQQMX2Fzc2VydEN5Y2xlCQEbYXNzZXJ0Q3ljbGVMb3dlclRoYXRDdXJyZW50AQUFY3ljbGUDCQAAAgUMX2Fzc2VydEN5Y2xlBQxfYXNzZXJ0Q3ljbGUEEHJlY2lwaWVudEFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCXJlY2lwaWVudAQTcmVxdWVzdGVkRGVwb3NpdEtleQkArAICCQCsAgIJAKwCAgIRcmVxdWVzdGVkRGVwb3NpdDoFCXJlY2lwaWVudAIBfAkApAMBBQVjeWNsZQQWY3ljbGVSZXF1ZXN0ZWREZXBvc2l0cwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJAKwCAgIWY3ljbGVSZXF1ZXN0ZWREZXBvc2l0OgkApAMBBQVjeWNsZQIfTm8gcmVxdWVzdGVkIGRlcG9zaXRzIGZvciBjeWNsZQQQcmVxdWVzdGVkRGVwb3NpdAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFE3JlcXVlc3RlZERlcG9zaXRLZXkCFE5vIHJlcXVlc3RlZCBkZXBvc2l0BA1scFRva2VuSXNzdWVkCAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFDXhXYXZlc0Fzc2V0SWQCD1Vrbm93biBhc3NldCBpZAhxdWFudGl0eQQJcG9vbFZhbHVlCQBlAggJAO8HAQUEdGhpcwdyZWd1bGFyBRZjeWNsZVJlcXVlc3RlZERlcG9zaXRzBAx4V2F2ZXNBbW91bnQDCQAAAgUNbHBUb2tlbklzc3VlZAAABRByZXF1ZXN0ZWREZXBvc2l0CQBrAwUQcmVxdWVzdGVkRGVwb3NpdAUNbHBUb2tlbklzc3VlZAUJcG9vbFZhbHVlBA1uZXdDeWNsZVZhbHVlCQBlAgUWY3ljbGVSZXF1ZXN0ZWREZXBvc2l0cwUQcmVxdWVzdGVkRGVwb3NpdAQTY3ljbGVXaXRoZHJhd0NoYW5nZQMJAGcCAAEFDW5ld0N5Y2xlVmFsdWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICAhZjeWNsZVJlcXVlc3RlZERlcG9zaXQ6CQCkAwEFBWN5Y2xlBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIWY3ljbGVSZXF1ZXN0ZWREZXBvc2l0OgkApAMBBQVjeWNsZQUNbmV3Q3ljbGVWYWx1ZQUDbmlsCQDOCAIFE2N5Y2xlV2l0aGRyYXdDaGFuZ2UJAMwIAgkBC0RlbGV0ZUVudHJ5AQUTcmVxdWVzdGVkRGVwb3NpdEtleQkAzAgCCQEHUmVpc3N1ZQMFDXhXYXZlc0Fzc2V0SWQFDHhXYXZlc0Ftb3VudAYJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUQcmVjaXBpZW50QWRkcmVzcwUMeFdhdmVzQW1vdW50BQ14V2F2ZXNBc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEPcmVxdWVzdFdpdGhkcmF3AAQRX2Fzc2VydE9uZVBheW1lbnQJARBhc3NlcnRPbmVQYXltZW50AQUKaW52b2NhdGlvbgMJAAACBRFfYXNzZXJ0T25lUGF5bWVudAURX2Fzc2VydE9uZVBheW1lbnQEE19hc3NlcnRQYXltZW50QXNzZXQJARJhc3NlcnRQYXltZW50QXNzZXQCBQppbnZvY2F0aW9uBQ14V2F2ZXNBc3NldElkAwkAAAIFE19hc3NlcnRQYXltZW50QXNzZXQFE19hc3NlcnRQYXltZW50QXNzZXQEDHhXYXZlc0Ftb3VudAgJAJEDAggFCmludm9jYXRpb24IcGF5bWVudHMAAAZhbW91bnQECWNhbGxlcktleQkApQgBCAUKaW52b2NhdGlvbgZjYWxsZXIEHXJlcXVlc3RlZFdpdGhkcmF3Rm9yQ2FsbGVyS2V5CQCsAgIJAKwCAgkArAICAhJyZXF1ZXN0ZWRXaXRoZHJhdzoFCWNhbGxlcktleQIBfAkApAMBBQxjdXJyZW50Q3ljbGUEGnJlcXVlc3RlZFdpdGhkcmF3Rm9yQ2FsbGVyCQELdmFsdWVPckVsc2UCCQCfCAEFHXJlcXVlc3RlZFdpdGhkcmF3Rm9yQ2FsbGVyS2V5AAAEFnRvdGFsUmVxdWVzdGVkV2l0aGRyYXcJAQt2YWx1ZU9yRWxzZQIJAJ8IAQIWdG90YWxSZXF1ZXN0ZWRXaXRoZHJhdwAABB1jdXJyZW50Q3ljbGVSZXF1ZXN0ZWRXaXRoZHJhdwUgY3VycmVudEN5Y2xlUmVxdWVzdGVkV2l0aGRyYXdhbHMJAMwIAgkBDEludGVnZXJFbnRyeQIFHXJlcXVlc3RlZFdpdGhkcmF3Rm9yQ2FsbGVyS2V5CQBkAgUacmVxdWVzdGVkV2l0aGRyYXdGb3JDYWxsZXIFDHhXYXZlc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdjeWNsZVJlcXVlc3RlZFdpdGhkcmF3OgkApAMBBQxjdXJyZW50Q3ljbGUJAGQCBR1jdXJyZW50Q3ljbGVSZXF1ZXN0ZWRXaXRoZHJhdwUMeFdhdmVzQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhZ0b3RhbFJlcXVlc3RlZFdpdGhkcmF3CQBkAgUWdG90YWxSZXF1ZXN0ZWRXaXRoZHJhdwUMeFdhdmVzQW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEPcHJvY2Vzc1dpdGhkcmF3AglyZWNpcGllbnQFY3ljbGUEDF9hc3NlcnRDeWNsZQkBG2Fzc2VydEN5Y2xlTG93ZXJUaGF0Q3VycmVudAEFBWN5Y2xlAwkAAAIFDF9hc3NlcnRDeWNsZQUMX2Fzc2VydEN5Y2xlBBByZWNpcGllbnRBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQlyZWNpcGllbnQEFHJlcXVlc3RlZFdpdGhkcmF3S2V5CQCsAgIJAKwCAgkArAICAhJyZXF1ZXN0ZWRXaXRoZHJhdzoFCXJlY2lwaWVudAIBfAkApAMBBQVjeWNsZQQTcmVxdWVzdGVkV2l0aGRyYXdhbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFFHJlcXVlc3RlZFdpdGhkcmF3S2V5AhVObyByZXF1ZXN0ZWQgd2l0aGRyYXcEFmN5Y2xlUmVxdWVzdGVkV2l0aGRyYXcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBCQCsAgICF2N5Y2xlUmVxdWVzdGVkV2l0aGRyYXc6CQCkAwEFBWN5Y2xlAiJObyByZXF1ZXN0ZWQgd2l0aGRyYXdhbHMgZm9yIGN5Y2xlBAlwb29sVmFsdWUICQDvBwEFBHRoaXMHcmVndWxhcgQNbHBUb2tlbklzc3VlZAgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQ14V2F2ZXNBc3NldElkAg9Va25vd24gYXNzZXQgaWQIcXVhbnRpdHkEFnRvdGFsUmVxdWVzdGVkV2l0aGRyYXcJAQt2YWx1ZU9yRWxzZQIJAJ8IAQIWdG90YWxSZXF1ZXN0ZWRXaXRoZHJhdwAABAt3YXZlc0Ftb3VudAkAawMFE3JlcXVlc3RlZFdpdGhkcmF3YWwFCXBvb2xWYWx1ZQUNbHBUb2tlbklzc3VlZAQNbmV3Q3ljbGVWYWx1ZQkAZQIFFmN5Y2xlUmVxdWVzdGVkV2l0aGRyYXcFE3JlcXVlc3RlZFdpdGhkcmF3YWwEE2N5Y2xlV2l0aGRyYXdDaGFuZ2UDCQAAAgUNbmV3Q3ljbGVWYWx1ZQAACQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgIXY3ljbGVSZXF1ZXN0ZWRXaXRoZHJhdzoJAKQDAQUFY3ljbGUFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdjeWNsZVJlcXVlc3RlZFdpdGhkcmF3OgkApAMBBQVjeWNsZQUNbmV3Q3ljbGVWYWx1ZQUDbmlsCQDOCAIFE2N5Y2xlV2l0aGRyYXdDaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQICFnRvdGFsUmVxdWVzdGVkV2l0aGRyYXcJAGUCBRZ0b3RhbFJlcXVlc3RlZFdpdGhkcmF3BRNyZXF1ZXN0ZWRXaXRoZHJhd2FsCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFEHJlY2lwaWVudEFkZHJlc3MFC3dhdmVzQW1vdW50BQR1bml0CQDMCAIJAQRCdXJuAgUNeFdhdmVzQXNzZXRJZAUTcmVxdWVzdGVkV2l0aGRyYXdhbAkAzAgCCQELRGVsZXRlRW50cnkBBRRyZXF1ZXN0ZWRXaXRoZHJhd0tleQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BCHJlZ2lzdGVyAgl2YWxpZGF0b3ILbWV0YWRhdGFVcmwEEV9hc3NlcnRPbmVQYXltZW50CQEQYXNzZXJ0T25lUGF5bWVudAEFCmludm9jYXRpb24DCQAAAgURX2Fzc2VydE9uZVBheW1lbnQFEV9hc3NlcnRPbmVQYXltZW50BBNfYXNzZXJ0UGF5bWVudEFzc2V0CQESYXNzZXJ0UGF5bWVudEFzc2V0AgUKaW52b2NhdGlvbgUKd3h4QXNzZXRJZAMJAAACBRNfYXNzZXJ0UGF5bWVudEFzc2V0BRNfYXNzZXJ0UGF5bWVudEFzc2V0BBNfYXNzZXJ0VmFsaWRBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IDCQAAAgUTX2Fzc2VydFZhbGlkQWRkcmVzcwUTX2Fzc2VydFZhbGlkQWRkcmVzcwQJd3h4QW1vdW50CAkAkQMCCAUKaW52b2NhdGlvbghwYXltZW50cwAABmFtb3VudAQMdmFsaWRhdG9yS2V5CQCsAgICCnZhbGlkYXRvcjoFCXZhbGlkYXRvcgQSdmFsaWRhdG9yU3RhdHVzS2V5CQCsAgICEHZhbGlkYXRvclN0YXR1czoFCXZhbGlkYXRvcgQXdmFsaWRhdG9yUmVnaXN0cmF0b3JLZXkJAKwCAgIVdmFsaWRhdG9yUmVnaXN0cmF0b3I6BQl2YWxpZGF0b3IDCQEJaXNEZWZpbmVkAQkAnQgCBQR0aGlzBQx2YWxpZGF0b3JLZXkJAAIBAhJBbHJlYWR5IHJlZ2lzdGVyZWQDCQECIT0CBRFyZXF1aXJlZFdYWEFtb3VudAUJd3h4QW1vdW50CQACAQISSW52YWxpZCBXWFggYW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIFDHZhbGlkYXRvcktleQULbWV0YWRhdGFVcmwJAMwIAgkBDEJvb2xlYW5FbnRyeQIFEnZhbGlkYXRvclN0YXR1c0tleQYJAMwIAgkBC0JpbmFyeUVudHJ5AgUXdmFsaWRhdG9yUmVnaXN0cmF0b3JLZXkICAUKaW52b2NhdGlvbgZjYWxsZXIFYnl0ZXMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQpkZXJlZ2lzdGVyAQl2YWxpZGF0b3IEEHZhbGlkYXRvckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCXZhbGlkYXRvcgQXdmFsaWRhdG9yUmVnaXN0cmF0b3JLZXkJAKwCAgIVdmFsaWRhdG9yUmVnaXN0cmF0b3I6BQl2YWxpZGF0b3IEEnZhbGlkYXRvclN0YXR1c0tleQkArAICAhB2YWxpZGF0b3JTdGF0dXM6BQl2YWxpZGF0b3IEEXZhbGlkYXRvclZvdGVzS2V5CQCsAgICBnZvdGVzOgUJdmFsaWRhdG9yBBdfYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwkBFmFzc2VydFZhbGlkYXRvckFkZHJlc3MBBRB2YWxpZGF0b3JBZGRyZXNzAwkAAAIFF19hc3NlcnRWYWxpZGF0b3JBZGRyZXNzBRdfYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwQZX2Fzc2V0Q2FsbGVySXNSZWdpc3RyYXRvcgMJAQIhPQIJARFAZXh0ck5hdGl2ZSgxMDU3KQEFF3ZhbGlkYXRvclJlZ2lzdHJhdG9yS2V5CAgFCmludm9jYXRpb24GY2FsbGVyBWJ5dGVzCQACAQITV3JvbmcgZGVyZWdpc3RyYXRvcgUEdW5pdAMJAAACBRlfYXNzZXRDYWxsZXJJc1JlZ2lzdHJhdG9yBRlfYXNzZXRDYWxsZXJJc1JlZ2lzdHJhdG9yBBN2YWxpZGF0b3JMZWFzZUlkS2V5CQCsAgICCGxlYXNlSWQ6BQl2YWxpZGF0b3IEBmNhbmNlbAQHJG1hdGNoMAkAoQgBBRN2YWxpZGF0b3JMZWFzZUlkS2V5AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAmlkBQckbWF0Y2gwCQDMCAIJAQtMZWFzZUNhbmNlbAEFAmlkBQNuaWwDCQABAgUHJG1hdGNoMAIEVW5pdAUDbmlsCQACAQILTWF0Y2ggZXJyb3IJAM4IAgkAzggCAwkBEUBleHRyTmF0aXZlKDEwNTYpAQUSdmFsaWRhdG9yU3RhdHVzS2V5BA52YWxpZGF0b3JWb3RlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBBRF2YWxpZGF0b3JWb3Rlc0tleQAACQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ10b3RhbFZvdGVza2V5CQBlAgUKdG90YWxWb3RlcwUOdmFsaWRhdG9yVm90ZXMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFCmludm9jYXRpb24GY2FsbGVyBRFyZXF1aXJlZFdYWEFtb3VudAUKd3h4QXNzZXRJZAUDbmlsBQNuaWwFBmNhbmNlbAkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgICBnZvdGVzOgUJdmFsaWRhdG9yCQDMCAIJAQtEZWxldGVFbnRyeQEFEnZhbGlkYXRvclN0YXR1c0tleQkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgICCnZhbGlkYXRvcjoFCXZhbGlkYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBBRF2YWxpZGF0b3JWb3Rlc0tleQkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgICEHZhbGlkYXRvckxlYXNlczoFCXZhbGlkYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBBRN2YWxpZGF0b3JMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgITbGF0ZXN0TGVhc2luZ0N5Y2xlOgUJdmFsaWRhdG9yBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEEdm90ZQIJdmFsaWRhdG9yCGludGVydmFsBBB2YWxpZGF0b3JBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IEF19hc3NlcnRWYWxpZGF0b3JBZGRyZXNzCQEWYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwEFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUXX2Fzc2VydFZhbGlkYXRvckFkZHJlc3MFF19hc3NlcnRWYWxpZGF0b3JBZGRyZXNzBBVfYXNzZXRWYWxpZGF0b3JTdGF0dXMJARthc3NlcnRBY3RpdmVWYWxpZGF0b3JTdGF0dXMBBRB2YWxpZGF0b3JBZGRyZXNzAwkAAAIFFV9hc3NldFZhbGlkYXRvclN0YXR1cwUVX2Fzc2V0VmFsaWRhdG9yU3RhdHVzBBFfYXNzZXJ0T25lUGF5bWVudAkBEGFzc2VydE9uZVBheW1lbnQBBQppbnZvY2F0aW9uAwkAAAIFEV9hc3NlcnRPbmVQYXltZW50BRFfYXNzZXJ0T25lUGF5bWVudAQTX2Fzc2VydFBheW1lbnRBc3NldAkBEmFzc2VydFBheW1lbnRBc3NldAIFCmludm9jYXRpb24FCnd4eEFzc2V0SWQDCQAAAgUTX2Fzc2VydFBheW1lbnRBc3NldAUTX2Fzc2VydFBheW1lbnRBc3NldAQLX2Fzc2VydFVpbnQJAQphc3NlcnRVaW50AQUIaW50ZXJ2YWwDCQAAAgULX2Fzc2VydFVpbnQFC19hc3NlcnRVaW50BAt1bmxvY2tCbG9jawkAZAIIBQlsYXN0QmxvY2sGaGVpZ2h0BQhpbnRlcnZhbAQJdXNlclZvdGVzCAkAkQMCCAUKaW52b2NhdGlvbghwYXltZW50cwAABmFtb3VudAQIdXNlckxvY2sICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAGYW1vdW50BAljYWxsZXJLZXkJAKUIAQgFCmludm9jYXRpb24GY2FsbGVyBA51bmxvY2tCbG9ja0tleQkArAICCQCsAgIJAKwCAgIMdW5sb2NrQmxvY2s6BQljYWxsZXJLZXkCAXwJAKQDAQULdW5sb2NrQmxvY2sEFnRvdGFsVmFsaWRhdG9yVm90ZXNLZXkJAKwCAgIGdm90ZXM6BQl2YWxpZGF0b3IEC3VzZXJWb3RlS2V5CQCsAgIJAKwCAgkArAICAgl1c2VyVm90ZToFCWNhbGxlcktleQIBfAkApAMBBQt1bmxvY2tCbG9jawQLdXNlckxvY2tLZXkJAKwCAgkArAICCQCsAgICCXVzZXJMb2NrOgUJY2FsbGVyS2V5AgF8CQCkAwEFC3VubG9ja0Jsb2NrBBN0b3RhbFZhbGlkYXRvclZvdGVzCQELdmFsdWVPckVsc2UCCQCfCAEFFnRvdGFsVmFsaWRhdG9yVm90ZXNLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgULdXNlclZvdGVLZXkFCXVzZXJWb3RlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgULdXNlckxvY2tLZXkFCHVzZXJMb2NrCQDMCAIJAQtCaW5hcnlFbnRyeQIFDnVubG9ja0Jsb2NrS2V5CAUQdmFsaWRhdG9yQWRkcmVzcwVieXRlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgUWdG90YWxWYWxpZGF0b3JWb3Rlc0tleQkAZAIFE3RvdGFsVmFsaWRhdG9yVm90ZXMFCXVzZXJWb3RlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgUNdG90YWxWb3Rlc2tleQkAZAIFCnRvdGFsVm90ZXMFCXVzZXJWb3RlcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BBnJlZGVlbQELdW5sb2NrQmxvY2sEEl9hc3NlcnRVbmxvY2tCbG9jawMJAGYCBQt1bmxvY2tCbG9jawgFCWxhc3RCbG9jawZoZWlnaHQJAAIBAglUb28gZWFybHkFBHVuaXQDCQAAAgUSX2Fzc2VydFVubG9ja0Jsb2NrBRJfYXNzZXJ0VW5sb2NrQmxvY2sECWNhbGxlcktleQkApQgBCAUKaW52b2NhdGlvbgZjYWxsZXIEDnVubG9ja0Jsb2NrS2V5CQCsAgIJAKwCAgkArAICAgx1bmxvY2tCbG9jazoFCWNhbGxlcktleQIBfAkApAMBBQt1bmxvY2tCbG9jawQLdXNlclZvdGVLZXkJAKwCAgkArAICCQCsAgICCXVzZXJWb3RlOgUJY2FsbGVyS2V5AgF8CQCkAwEFC3VubG9ja0Jsb2NrBAt1c2VyTG9ja0tleQkArAICCQCsAgIJAKwCAgIJdXNlckxvY2s6BQljYWxsZXJLZXkCAXwJAKQDAQULdW5sb2NrQmxvY2sEEHZhbGlkYXRvckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoQgBBQ51bmxvY2tCbG9ja0tleQIMVW5rbm93biBsb2NrBBF2YWxpZGF0b3JWb3Rlc0tleQkArAICAgZ2b3RlczoJANgEAQUQdmFsaWRhdG9yQWRkcmVzcwQJdXNlclZvdGVzCQERQGV4dHJOYXRpdmUoMTA1NSkBBQt1c2VyVm90ZUtleQQTdG90YWxWYWxpZGF0b3JWb3RlcwkBEUBleHRyTmF0aXZlKDEwNTUpAQURdmFsaWRhdG9yVm90ZXNLZXkECHVzZXJMb2NrCQERQGV4dHJOYXRpdmUoMTA1NSkBBQt1c2VyTG9ja0tleQQSdmFsaWRhdG9yU3RhdHVzS2V5CQCsAgICEHZhbGlkYXRvclN0YXR1czoJANgEAQUQdmFsaWRhdG9yQWRkcmVzcwkAzggCAwkBEUBleHRyTmF0aXZlKDEwNTYpAQUSdmFsaWRhdG9yU3RhdHVzS2V5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ10b3RhbFZvdGVza2V5CQBlAgUKdG90YWxWb3RlcwUJdXNlclZvdGVzBQNuaWwFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUKaW52b2NhdGlvbgZjYWxsZXIFCHVzZXJMb2NrBQp3eHhBc3NldElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRF2YWxpZGF0b3JWb3Rlc0tleQkAZQIFE3RvdGFsVmFsaWRhdG9yVm90ZXMFCXVzZXJWb3RlcwkAzAgCCQELRGVsZXRlRW50cnkBBQt1c2VyVm90ZUtleQkAzAgCCQELRGVsZXRlRW50cnkBBQ51bmxvY2tCbG9ja0tleQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BB2xlYXNpbmcBCXZhbGlkYXRvcgQQdmFsaWRhdG9yQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUJdmFsaWRhdG9yBBdfYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwkBFmFzc2VydFZhbGlkYXRvckFkZHJlc3MBBRB2YWxpZGF0b3JBZGRyZXNzAwkAAAIFF19hc3NlcnRWYWxpZGF0b3JBZGRyZXNzBRdfYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwQVX2Fzc2V0VmFsaWRhdG9yU3RhdHVzCQEbYXNzZXJ0QWN0aXZlVmFsaWRhdG9yU3RhdHVzAQUQdmFsaWRhdG9yQWRkcmVzcwMJAAACBRVfYXNzZXRWYWxpZGF0b3JTdGF0dXMFFV9hc3NldFZhbGlkYXRvclN0YXR1cwQTdmFsaWRhdG9yTGVhc2VJZEtleQkArAICAghsZWFzZUlkOgUJdmFsaWRhdG9yBBVsYXRlc3RMZWFzaW5nQ3ljbGVLZXkJAKwCAgITbGF0ZXN0TGVhc2luZ0N5Y2xlOgUJdmFsaWRhdG9yBA52YWxpZGF0b3JWb3RlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBCQCsAgICBnZvdGVzOgUJdmFsaWRhdG9yAAAEEmN1cnJlbnRMZWFzZUFtb3VudAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQCsAgICEHZhbGlkYXRvckxlYXNlczoFCXZhbGlkYXRvcgAABBNfY2hlY2tMZWFzaW5nU3RhdHVzAwkAAAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUVbGF0ZXN0TGVhc2luZ0N5Y2xlS2V5AP///////////wEFDGN1cnJlbnRDeWNsZQkAAgECDkFscmVhZHkgbGVhc2VkBQR1bml0AwkAAAIFE19jaGVja0xlYXNpbmdTdGF0dXMFE19jaGVja0xlYXNpbmdTdGF0dXMEDWxwVG9rZW5Jc3N1ZWQICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUNeFdhdmVzQXNzZXRJZAIPVWtub3duIGFzc2V0IGlkCHF1YW50aXR5BAlwb29sVmFsdWUJAGUCCAkA7wcBBQR0aGlzB3JlZ3VsYXIFHWN1cnJlbnRDeWNsZVJlcXVlc3RlZERlcG9zaXRzBBZ0b3RhbFJlcXVlc3RlZFdpdGhkcmF3CQELdmFsdWVPckVsc2UCCQCfCAECFnRvdGFsUmVxdWVzdGVkV2l0aGRyYXcAAAQbcHJldmlvdXNseVJlcXVlc3RlZFdpdGhkcmF3CQBlAgUWdG90YWxSZXF1ZXN0ZWRXaXRoZHJhdwUgY3VycmVudEN5Y2xlUmVxdWVzdGVkV2l0aGRyYXdhbHMEEXJlcXVlc3RlZFdpdGhkcmF3AwkAAAIFDWxwVG9rZW5Jc3N1ZWQAAAUbcHJldmlvdXNseVJlcXVlc3RlZFdpdGhkcmF3CQBrAwUbcHJldmlvdXNseVJlcXVlc3RlZFdpdGhkcmF3BQlwb29sVmFsdWUFDWxwVG9rZW5Jc3N1ZWQEEXRhcmdldExlYXNlQW1vdW50CQBrAwkAZQIFCXBvb2xWYWx1ZQURcmVxdWVzdGVkV2l0aGRyYXcFDnZhbGlkYXRvclZvdGVzBQp0b3RhbFZvdGVzBAZjYW5jZWwEByRtYXRjaDAJAKEIAQUTdmFsaWRhdG9yTGVhc2VJZEtleQMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJpZAUHJG1hdGNoMAkAzAgCCQELTGVhc2VDYW5jZWwBBQJpZAUDbmlsAwkAAQIFByRtYXRjaDACBFVuaXQFA25pbAkAAgECC01hdGNoIGVycm9yAwkBAiE9AgURdGFyZ2V0TGVhc2VBbW91bnQFEmN1cnJlbnRMZWFzZUFtb3VudAQFbGVhc2UJAMQIAgUQdmFsaWRhdG9yQWRkcmVzcwURdGFyZ2V0TGVhc2VBbW91bnQJAM4IAgUGY2FuY2VsAwkAAAIFEXRhcmdldExlYXNlQW1vdW50AAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIQdmFsaWRhdG9yTGVhc2VzOgUJdmFsaWRhdG9yBRF0YXJnZXRMZWFzZUFtb3VudAkAzAgCCQELRGVsZXRlRW50cnkBBRN2YWxpZGF0b3JMZWFzZUlkS2V5BQNuaWwJAMwIAgUFbGVhc2UJAMwIAgkBC0JpbmFyeUVudHJ5AgUTdmFsaWRhdG9yTGVhc2VJZEtleQkAuQgBBQVsZWFzZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhB2YWxpZGF0b3JMZWFzZXM6BQl2YWxpZGF0b3IFEXRhcmdldExlYXNlQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRVsYXRlc3RMZWFzaW5nQ3ljbGVLZXkFDGN1cnJlbnRDeWNsZQUDbmlsCQACAQIPTm90aGluZyBjaGFuZ2VzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BD2VtZXJnZW5jeVZvdGluZwEJdmFsaWRhdG9yBBB2YWxpZGF0b3JBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IEF19hc3NlcnRWYWxpZGF0b3JBZGRyZXNzCQEWYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwEFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUXX2Fzc2VydFZhbGlkYXRvckFkZHJlc3MFF19hc3NlcnRWYWxpZGF0b3JBZGRyZXNzBBVfYXNzZXRWYWxpZGF0b3JTdGF0dXMJARthc3NlcnRBY3RpdmVWYWxpZGF0b3JTdGF0dXMBBRB2YWxpZGF0b3JBZGRyZXNzAwkAAAIFFV9hc3NldFZhbGlkYXRvclN0YXR1cwUVX2Fzc2V0VmFsaWRhdG9yU3RhdHVzBBFfYXNzZXJ0T25lUGF5bWVudAkBEGFzc2VydE9uZVBheW1lbnQBBQppbnZvY2F0aW9uAwkAAAIFEV9hc3NlcnRPbmVQYXltZW50BRFfYXNzZXJ0T25lUGF5bWVudAQTX2Fzc2VydFBheW1lbnRBc3NldAkBEmFzc2VydFBheW1lbnRBc3NldAIFCmludm9jYXRpb24FDXhXYXZlc0Fzc2V0SWQDCQAAAgUTX2Fzc2VydFBheW1lbnRBc3NldAUTX2Fzc2VydFBheW1lbnRBc3NldAQKdm90ZUFtb3VudAgJAJEDAggFCmludm9jYXRpb24IcGF5bWVudHMAAAZhbW91bnQECWNhbGxlcktleQkApQgBCAUKaW52b2NhdGlvbgZjYWxsZXIEEWVtZXJnZW5jeVZvdGVzS2V5CQCsAgICD2VtZXJnZW5jeVZvdGVzOgUJdmFsaWRhdG9yBBVlbWVyZ2VuY3lVc2VyVm90ZXNLZXkJAKwCAgkArAICAhNlbWVyZ2VuY3lVc2VyVm90ZXM6BQljYWxsZXJLZXkFCXZhbGlkYXRvcgQOZW1lcmdlbmN5Vm90ZXMJAGQCBQp2b3RlQW1vdW50CQELdmFsdWVPckVsc2UCCQCfCAEFEWVtZXJnZW5jeVZvdGVzS2V5AAAECHF1YW50aXR5CAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFDXhXYXZlc0Fzc2V0SWQCD1Vrbm93biBhc3NldCBpZAhxdWFudGl0eQQMd3h4QXNzZXRJbmZvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUKd3h4QXNzZXRJZAIPVWtub3duIGFzc2V0IGlkBA5pc1ZhbGlkYXRvckJhZAkAZgIJAGkCCQBoAgUOZW1lcmdlbmN5Vm90ZXMAZAUIcXVhbnRpdHkFGGVtZXJnZW5jeVZvdGluZ1RocmVzaG9sZAQKcHVuaXNobWVudAMFDmlzVmFsaWRhdG9yQmFkBBN2YWxpZGF0b3JMZWFzZUlkS2V5CQCsAgICCGxlYXNlSWQ6BQl2YWxpZGF0b3IEBmNhbmNlbAQHJG1hdGNoMAkAoQgBBRN2YWxpZGF0b3JMZWFzZUlkS2V5AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAmlkBQckbWF0Y2gwCQDMCAIJAQtMZWFzZUNhbmNlbAEFAmlkBQNuaWwDCQABAgUHJG1hdGNoMAIEVW5pdAUDbmlsCQACAQILTWF0Y2ggZXJyb3IEEXZhbGlkYXRvclZvdGVzS2V5CQCsAgICBnZvdGVzOgUJdmFsaWRhdG9yBBN0b3RhbFZhbGlkYXRvclZvdGVzCQELdmFsdWVPckVsc2UCCQCfCAEFEXZhbGlkYXRvclZvdGVzS2V5AAAJAM4IAgUGY2FuY2VsCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQx3eHhBc3NldEluZm8GaXNzdWVyBRFyZXF1aXJlZFdYWEFtb3VudAUKd3h4QXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUNdG90YWxWb3Rlc2tleQkAZQIFCnRvdGFsVm90ZXMFE3RvdGFsVmFsaWRhdG9yVm90ZXMJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAKwCAgIQdmFsaWRhdG9yU3RhdHVzOgUJdmFsaWRhdG9yBwkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgICEHZhbGlkYXRvckxlYXNlczoFCXZhbGlkYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgICCGxlYXNlSWQ6BQl2YWxpZGF0b3IJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICAhNsYXRlc3RMZWFzaW5nQ3ljbGU6BQl2YWxpZGF0b3IFA25pbAUDbmlsCQDOCAIFCnB1bmlzaG1lbnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWVtZXJnZW5jeVZvdGVzS2V5CQBkAgUKdm90ZUFtb3VudAUOZW1lcmdlbmN5Vm90ZXMJAMwIAgkBDEludGVnZXJFbnRyeQIFFWVtZXJnZW5jeVVzZXJWb3Rlc0tleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUVZW1lcmdlbmN5VXNlclZvdGVzS2V5AAAFDmVtZXJnZW5jeVZvdGVzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgETcmVkZWVtRW1lcmdlbmN5Vm90ZQEJdmFsaWRhdG9yBBB2YWxpZGF0b3JBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IECWNhbGxlcktleQkApQgBCAUKaW52b2NhdGlvbgZjYWxsZXIEFWVtZXJnZW5jeVVzZXJWb3Rlc0tleQkArAICCQCsAgICE2VtZXJnZW5jeVVzZXJWb3RlczoFCWNhbGxlcktleQUJdmFsaWRhdG9yBBJlbWVyZ2VuY3lVc2VyVm90ZXMJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBRVlbWVyZ2VuY3lVc2VyVm90ZXNLZXkCG05vIGVtZXJnZW5jeSB2b3RlcyBmb3IgdXNlcgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUKaW52b2NhdGlvbgZjYWxsZXIFEmVtZXJnZW5jeVVzZXJWb3RlcwUNeFdhdmVzQXNzZXRJZAUDbmlsAFbPJjE=", "height": 3489019, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 7 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let requiredWXXAmount = 10000000000 | |
5 | + | ||
6 | + | let cycleDurationInBlocks = 1000 | |
7 | + | ||
8 | + | let emergencyVotingThreshold = 10 | |
9 | + | ||
10 | + | let totalVoteskey = "totalVotes" | |
11 | + | ||
12 | + | let wxxAssetId = getBinaryValue("projectAssetId") | |
13 | + | ||
14 | + | let xWavesAssetId = getBinaryValue("xWavesAssetId") | |
15 | + | ||
16 | + | let currentCycle = ((lastBlock.height - getIntegerValue("startBlock")) / cycleDurationInBlocks) | |
17 | + | ||
18 | + | let currentCycleRequestedWithdrawals = valueOrElse(getInteger(("cycleRequestedWithdraw:" + toString(currentCycle))), 0) | |
19 | + | ||
20 | + | let currentCycleRequestedDeposits = valueOrElse(getInteger(("cycleRequestedDeposit:" + toString(currentCycle))), 0) | |
21 | + | ||
22 | + | let totalVotes = getIntegerValue(totalVoteskey) | |
23 | + | ||
24 | + | func assertValidatorAddress (validatorAddress) = if (isDefined(getString(this, ("validator:" + toString(validatorAddress))))) | |
25 | + | then unit | |
26 | + | else throw("Unknown validator") | |
27 | + | ||
28 | + | ||
29 | + | func assertOnePayment (invocation) = if ((size(invocation.payments) != 1)) | |
30 | + | then throw("Not one payment") | |
31 | + | else unit | |
32 | + | ||
33 | + | ||
34 | + | func assertPaymentAsset (invocation,expectedToken) = if ((invocation.payments[0].assetId != expectedToken)) | |
35 | + | then throw("Unexpected asset id") | |
36 | + | else unit | |
37 | + | ||
38 | + | ||
39 | + | func assertUint (v) = if ((0 > v)) | |
40 | + | then throw("Invalid uint") | |
41 | + | else unit | |
42 | + | ||
43 | + | ||
44 | + | func assertActiveValidatorStatus (validatorAddress) = { | |
45 | + | let validatorStatusKey = ("validatorStatus:" + toString(validatorAddress)) | |
46 | + | if (!(getBooleanValue(validatorStatusKey))) | |
47 | + | then throw("Unactive validator") | |
48 | + | else unit | |
49 | + | } | |
50 | + | ||
51 | + | ||
52 | + | func assertCycleLowerThatCurrent (cycle) = if ((currentCycle > cycle)) | |
53 | + | then unit | |
54 | + | else throw("Invalid cycle") | |
55 | + | ||
56 | + | ||
57 | + | func assertCallerIsContract (invocation) = if ((this != invocation.caller)) | |
58 | + | then throw("Unauthorized") | |
59 | + | else unit | |
60 | + | ||
61 | + | ||
62 | + | @Callable(invocation) | |
63 | + | func init (wxxTokenId) = { | |
64 | + | let callerCheck = assertCallerIsContract(invocation) | |
65 | + | if ((callerCheck == callerCheck)) | |
66 | + | then if (isDefined(getBinary("projectAssetId"))) | |
67 | + | then throw("Initialized") | |
68 | + | else { | |
69 | + | let issue = Issue("xWaves", "xWaves", 0, 8, true) | |
70 | + | let xWavesAssetIdId = calculateAssetId(issue) | |
71 | + | [issue, IntegerEntry(totalVoteskey, 0), BinaryEntry("projectAssetId", wxxTokenId), BinaryEntry("xWavesAssetId", xWavesAssetIdId), IntegerEntry("startBlock", lastBlock.height), IntegerEntry("totalRequestedWithdraw", 0), IntegerEntry("requiredWXXAmount", requiredWXXAmount), IntegerEntry("emergencyVotingThreshold", emergencyVotingThreshold)] | |
72 | + | } | |
73 | + | else throw("Strict value is not equal to itself.") | |
74 | + | } | |
75 | + | ||
76 | + | ||
77 | + | ||
78 | + | @Callable(invocation) | |
79 | + | func requestDeposit () = { | |
80 | + | let _assertOnePayment = assertOnePayment(invocation) | |
81 | + | if ((_assertOnePayment == _assertOnePayment)) | |
82 | + | then { | |
83 | + | let _assertPaymentAsset = assertPaymentAsset(invocation, unit) | |
84 | + | if ((_assertPaymentAsset == _assertPaymentAsset)) | |
85 | + | then { | |
86 | + | let wavesAmount = invocation.payments[0].amount | |
87 | + | let callerKey = toString(invocation.caller) | |
88 | + | let requestedDepositKey = ((("requestedDeposit:" + callerKey) + "|") + toString(currentCycle)) | |
89 | + | let requestedDeposits = valueOrElse(getInteger(requestedDepositKey), 0) | |
90 | + | let totalRequestedDeposits = valueOrElse(getInteger(("cycleRequestedDeposit:" + toString(currentCycle))), 0) | |
91 | + | [IntegerEntry(requestedDepositKey, (requestedDeposits + wavesAmount)), IntegerEntry(("cycleRequestedDeposit:" + toString(currentCycle)), (totalRequestedDeposits + wavesAmount))] | |
92 | + | } | |
93 | + | else throw("Strict value is not equal to itself.") | |
94 | + | } | |
95 | + | else throw("Strict value is not equal to itself.") | |
96 | + | } | |
97 | + | ||
98 | + | ||
99 | + | ||
100 | + | @Callable(invocation) | |
101 | + | func processDeposit (recipient,cycle) = { | |
102 | + | let _assertCycle = assertCycleLowerThatCurrent(cycle) | |
103 | + | if ((_assertCycle == _assertCycle)) | |
104 | + | then { | |
105 | + | let recipientAddress = addressFromStringValue(recipient) | |
106 | + | let requestedDepositKey = ((("requestedDeposit:" + recipient) + "|") + toString(cycle)) | |
107 | + | let cycleRequestedDeposits = valueOrErrorMessage(getInteger(("cycleRequestedDeposit:" + toString(cycle))), "No requested deposits for cycle") | |
108 | + | let requestedDeposit = valueOrErrorMessage(getInteger(requestedDepositKey), "No requested deposit") | |
109 | + | let lpTokenIssued = valueOrErrorMessage(assetInfo(xWavesAssetId), "Uknown asset id").quantity | |
110 | + | let poolValue = (wavesBalance(this).regular - cycleRequestedDeposits) | |
111 | + | let xWavesAmount = if ((lpTokenIssued == 0)) | |
112 | + | then requestedDeposit | |
113 | + | else fraction(requestedDeposit, lpTokenIssued, poolValue) | |
114 | + | let newCycleValue = (cycleRequestedDeposits - requestedDeposit) | |
115 | + | let cycleWithdrawChange = if ((1 >= newCycleValue)) | |
116 | + | then [DeleteEntry(("cycleRequestedDeposit:" + toString(cycle)))] | |
117 | + | else [IntegerEntry(("cycleRequestedDeposit:" + toString(cycle)), newCycleValue)] | |
118 | + | (cycleWithdrawChange ++ [DeleteEntry(requestedDepositKey), Reissue(xWavesAssetId, xWavesAmount, true), ScriptTransfer(recipientAddress, xWavesAmount, xWavesAssetId)]) | |
119 | + | } | |
120 | + | else throw("Strict value is not equal to itself.") | |
121 | + | } | |
122 | + | ||
123 | + | ||
124 | + | ||
125 | + | @Callable(invocation) | |
126 | + | func requestWithdraw () = { | |
127 | + | let _assertOnePayment = assertOnePayment(invocation) | |
128 | + | if ((_assertOnePayment == _assertOnePayment)) | |
129 | + | then { | |
130 | + | let _assertPaymentAsset = assertPaymentAsset(invocation, xWavesAssetId) | |
131 | + | if ((_assertPaymentAsset == _assertPaymentAsset)) | |
132 | + | then { | |
133 | + | let xWavesAmount = invocation.payments[0].amount | |
134 | + | let callerKey = toString(invocation.caller) | |
135 | + | let requestedWithdrawForCallerKey = ((("requestedWithdraw:" + callerKey) + "|") + toString(currentCycle)) | |
136 | + | let requestedWithdrawForCaller = valueOrElse(getInteger(requestedWithdrawForCallerKey), 0) | |
137 | + | let totalRequestedWithdraw = valueOrElse(getInteger("totalRequestedWithdraw"), 0) | |
138 | + | let currentCycleRequestedWithdraw = currentCycleRequestedWithdrawals | |
139 | + | [IntegerEntry(requestedWithdrawForCallerKey, (requestedWithdrawForCaller + xWavesAmount)), IntegerEntry(("cycleRequestedWithdraw:" + toString(currentCycle)), (currentCycleRequestedWithdraw + xWavesAmount)), IntegerEntry("totalRequestedWithdraw", (totalRequestedWithdraw + xWavesAmount))] | |
140 | + | } | |
141 | + | else throw("Strict value is not equal to itself.") | |
142 | + | } | |
143 | + | else throw("Strict value is not equal to itself.") | |
144 | + | } | |
145 | + | ||
146 | + | ||
147 | + | ||
148 | + | @Callable(invocation) | |
149 | + | func processWithdraw (recipient,cycle) = { | |
150 | + | let _assertCycle = assertCycleLowerThatCurrent(cycle) | |
151 | + | if ((_assertCycle == _assertCycle)) | |
152 | + | then { | |
153 | + | let recipientAddress = addressFromStringValue(recipient) | |
154 | + | let requestedWithdrawKey = ((("requestedWithdraw:" + recipient) + "|") + toString(cycle)) | |
155 | + | let requestedWithdrawal = valueOrErrorMessage(getInteger(requestedWithdrawKey), "No requested withdraw") | |
156 | + | let cycleRequestedWithdraw = valueOrErrorMessage(getInteger(("cycleRequestedWithdraw:" + toString(cycle))), "No requested withdrawals for cycle") | |
157 | + | let poolValue = wavesBalance(this).regular | |
158 | + | let lpTokenIssued = valueOrErrorMessage(assetInfo(xWavesAssetId), "Uknown asset id").quantity | |
159 | + | let totalRequestedWithdraw = valueOrElse(getInteger("totalRequestedWithdraw"), 0) | |
160 | + | let wavesAmount = fraction(requestedWithdrawal, poolValue, lpTokenIssued) | |
161 | + | let newCycleValue = (cycleRequestedWithdraw - requestedWithdrawal) | |
162 | + | let cycleWithdrawChange = if ((newCycleValue == 0)) | |
163 | + | then [DeleteEntry(("cycleRequestedWithdraw:" + toString(cycle)))] | |
164 | + | else [IntegerEntry(("cycleRequestedWithdraw:" + toString(cycle)), newCycleValue)] | |
165 | + | (cycleWithdrawChange ++ [IntegerEntry("totalRequestedWithdraw", (totalRequestedWithdraw - requestedWithdrawal)), ScriptTransfer(recipientAddress, wavesAmount, unit), Burn(xWavesAssetId, requestedWithdrawal), DeleteEntry(requestedWithdrawKey)]) | |
166 | + | } | |
167 | + | else throw("Strict value is not equal to itself.") | |
168 | + | } | |
169 | + | ||
170 | + | ||
171 | + | ||
172 | + | @Callable(invocation) | |
173 | + | func register (validator,metadataUrl) = { | |
174 | + | let _assertOnePayment = assertOnePayment(invocation) | |
175 | + | if ((_assertOnePayment == _assertOnePayment)) | |
176 | + | then { | |
177 | + | let _assertPaymentAsset = assertPaymentAsset(invocation, wxxAssetId) | |
178 | + | if ((_assertPaymentAsset == _assertPaymentAsset)) | |
179 | + | then { | |
180 | + | let _assertValidAddress = addressFromStringValue(validator) | |
181 | + | if ((_assertValidAddress == _assertValidAddress)) | |
182 | + | then { | |
183 | + | let wxxAmount = invocation.payments[0].amount | |
184 | + | let validatorKey = ("validator:" + validator) | |
185 | + | let validatorStatusKey = ("validatorStatus:" + validator) | |
186 | + | let validatorRegistratorKey = ("validatorRegistrator:" + validator) | |
187 | + | if (isDefined(getString(this, validatorKey))) | |
188 | + | then throw("Already registered") | |
189 | + | else if ((requiredWXXAmount != wxxAmount)) | |
190 | + | then throw("Invalid WXX amount") | |
191 | + | else [StringEntry(validatorKey, metadataUrl), BooleanEntry(validatorStatusKey, true), BinaryEntry(validatorRegistratorKey, invocation.caller.bytes)] | |
192 | + | } | |
193 | + | else throw("Strict value is not equal to itself.") | |
194 | + | } | |
195 | + | else throw("Strict value is not equal to itself.") | |
196 | + | } | |
197 | + | else throw("Strict value is not equal to itself.") | |
198 | + | } | |
199 | + | ||
200 | + | ||
201 | + | ||
202 | + | @Callable(invocation) | |
203 | + | func deregister (validator) = { | |
204 | + | let validatorAddress = addressFromStringValue(validator) | |
205 | + | let validatorRegistratorKey = ("validatorRegistrator:" + validator) | |
206 | + | let validatorStatusKey = ("validatorStatus:" + validator) | |
207 | + | let validatorVotesKey = ("votes:" + validator) | |
208 | + | let _assertValidatorAddress = assertValidatorAddress(validatorAddress) | |
209 | + | if ((_assertValidatorAddress == _assertValidatorAddress)) | |
210 | + | then { | |
211 | + | let _assetCallerIsRegistrator = if ((getBinaryValue(validatorRegistratorKey) != invocation.caller.bytes)) | |
212 | + | then throw("Wrong deregistrator") | |
213 | + | else unit | |
214 | + | if ((_assetCallerIsRegistrator == _assetCallerIsRegistrator)) | |
215 | + | then { | |
216 | + | let validatorLeaseIdKey = ("leaseId:" + validator) | |
217 | + | let cancel = match getBinary(validatorLeaseIdKey) { | |
218 | + | case id: ByteVector => | |
219 | + | [LeaseCancel(id)] | |
220 | + | case _: Unit => | |
221 | + | nil | |
222 | + | case _ => | |
223 | + | throw("Match error") | |
224 | + | } | |
225 | + | (((if (getBooleanValue(validatorStatusKey)) | |
226 | + | then { | |
227 | + | let validatorVotes = valueOrElse(getInteger(validatorVotesKey), 0) | |
228 | + | [IntegerEntry(totalVoteskey, (totalVotes - validatorVotes)), ScriptTransfer(invocation.caller, requiredWXXAmount, wxxAssetId)] | |
229 | + | } | |
230 | + | else nil) ++ cancel) ++ [DeleteEntry(("votes:" + validator)), DeleteEntry(validatorStatusKey), DeleteEntry(("validator:" + validator)), DeleteEntry(validatorVotesKey), DeleteEntry(("validatorLeases:" + validator)), DeleteEntry(validatorLeaseIdKey), DeleteEntry(("latestLeasingCycle:" + validator))]) | |
231 | + | } | |
232 | + | else throw("Strict value is not equal to itself.") | |
233 | + | } | |
234 | + | else throw("Strict value is not equal to itself.") | |
235 | + | } | |
236 | + | ||
237 | + | ||
238 | + | ||
239 | + | @Callable(invocation) | |
240 | + | func vote (validator,interval) = { | |
241 | + | let validatorAddress = addressFromStringValue(validator) | |
242 | + | let _assertValidatorAddress = assertValidatorAddress(validatorAddress) | |
243 | + | if ((_assertValidatorAddress == _assertValidatorAddress)) | |
244 | + | then { | |
245 | + | let _assetValidatorStatus = assertActiveValidatorStatus(validatorAddress) | |
246 | + | if ((_assetValidatorStatus == _assetValidatorStatus)) | |
247 | + | then { | |
248 | + | let _assertOnePayment = assertOnePayment(invocation) | |
249 | + | if ((_assertOnePayment == _assertOnePayment)) | |
250 | + | then { | |
251 | + | let _assertPaymentAsset = assertPaymentAsset(invocation, wxxAssetId) | |
252 | + | if ((_assertPaymentAsset == _assertPaymentAsset)) | |
253 | + | then { | |
254 | + | let _assertUint = assertUint(interval) | |
255 | + | if ((_assertUint == _assertUint)) | |
256 | + | then { | |
257 | + | let unlockBlock = (lastBlock.height + interval) | |
258 | + | let userVotes = invocation.payments[0].amount | |
259 | + | let userLock = invocation.payments[0].amount | |
260 | + | let callerKey = toString(invocation.caller) | |
261 | + | let unlockBlockKey = ((("unlockBlock:" + callerKey) + "|") + toString(unlockBlock)) | |
262 | + | let totalValidatorVotesKey = ("votes:" + validator) | |
263 | + | let userVoteKey = ((("userVote:" + callerKey) + "|") + toString(unlockBlock)) | |
264 | + | let userLockKey = ((("userLock:" + callerKey) + "|") + toString(unlockBlock)) | |
265 | + | let totalValidatorVotes = valueOrElse(getInteger(totalValidatorVotesKey), 0) | |
266 | + | [IntegerEntry(userVoteKey, userVotes), IntegerEntry(userLockKey, userLock), BinaryEntry(unlockBlockKey, validatorAddress.bytes), IntegerEntry(totalValidatorVotesKey, (totalValidatorVotes + userVotes)), IntegerEntry(totalVoteskey, (totalVotes + userVotes))] | |
267 | + | } | |
268 | + | else throw("Strict value is not equal to itself.") | |
269 | + | } | |
270 | + | else throw("Strict value is not equal to itself.") | |
271 | + | } | |
272 | + | else throw("Strict value is not equal to itself.") | |
273 | + | } | |
274 | + | else throw("Strict value is not equal to itself.") | |
275 | + | } | |
276 | + | else throw("Strict value is not equal to itself.") | |
277 | + | } | |
278 | + | ||
279 | + | ||
280 | + | ||
281 | + | @Callable(invocation) | |
282 | + | func redeem (unlockBlock) = { | |
283 | + | let _assertUnlockBlock = if ((unlockBlock > lastBlock.height)) | |
284 | + | then throw("Too early") | |
285 | + | else unit | |
286 | + | if ((_assertUnlockBlock == _assertUnlockBlock)) | |
287 | + | then { | |
288 | + | let callerKey = toString(invocation.caller) | |
289 | + | let unlockBlockKey = ((("unlockBlock:" + callerKey) + "|") + toString(unlockBlock)) | |
290 | + | let userVoteKey = ((("userVote:" + callerKey) + "|") + toString(unlockBlock)) | |
291 | + | let userLockKey = ((("userLock:" + callerKey) + "|") + toString(unlockBlock)) | |
292 | + | let validatorAddress = valueOrErrorMessage(getBinary(unlockBlockKey), "Unknown lock") | |
293 | + | let validatorVotesKey = ("votes:" + toBase58String(validatorAddress)) | |
294 | + | let userVotes = getIntegerValue(userVoteKey) | |
295 | + | let totalValidatorVotes = getIntegerValue(validatorVotesKey) | |
296 | + | let userLock = getIntegerValue(userLockKey) | |
297 | + | let validatorStatusKey = ("validatorStatus:" + toBase58String(validatorAddress)) | |
298 | + | ((if (getBooleanValue(validatorStatusKey)) | |
299 | + | then [IntegerEntry(totalVoteskey, (totalVotes - userVotes))] | |
300 | + | else nil) ++ [ScriptTransfer(invocation.caller, userLock, wxxAssetId), IntegerEntry(validatorVotesKey, (totalValidatorVotes - userVotes)), DeleteEntry(userVoteKey), DeleteEntry(unlockBlockKey)]) | |
301 | + | } | |
302 | + | else throw("Strict value is not equal to itself.") | |
303 | + | } | |
304 | + | ||
305 | + | ||
306 | + | ||
307 | + | @Callable(invocation) | |
308 | + | func leasing (validator) = { | |
309 | + | let validatorAddress = addressFromStringValue(validator) | |
310 | + | let _assertValidatorAddress = assertValidatorAddress(validatorAddress) | |
311 | + | if ((_assertValidatorAddress == _assertValidatorAddress)) | |
312 | + | then { | |
313 | + | let _assetValidatorStatus = assertActiveValidatorStatus(validatorAddress) | |
314 | + | if ((_assetValidatorStatus == _assetValidatorStatus)) | |
315 | + | then { | |
316 | + | let validatorLeaseIdKey = ("leaseId:" + validator) | |
317 | + | let latestLeasingCycleKey = ("latestLeasingCycle:" + validator) | |
318 | + | let validatorVotes = valueOrElse(getInteger(("votes:" + validator)), 0) | |
319 | + | let currentLeaseAmount = valueOrElse(getInteger(("validatorLeases:" + validator)), 0) | |
320 | + | let _checkLeasingStatus = if ((valueOrElse(getInteger(latestLeasingCycleKey), -1) == currentCycle)) | |
321 | + | then throw("Already leased") | |
322 | + | else unit | |
323 | + | if ((_checkLeasingStatus == _checkLeasingStatus)) | |
324 | + | then { | |
325 | + | let lpTokenIssued = valueOrErrorMessage(assetInfo(xWavesAssetId), "Uknown asset id").quantity | |
326 | + | let poolValue = (wavesBalance(this).regular - currentCycleRequestedDeposits) | |
327 | + | let totalRequestedWithdraw = valueOrElse(getInteger("totalRequestedWithdraw"), 0) | |
328 | + | let previouslyRequestedWithdraw = (totalRequestedWithdraw - currentCycleRequestedWithdrawals) | |
329 | + | let requestedWithdraw = if ((lpTokenIssued == 0)) | |
330 | + | then previouslyRequestedWithdraw | |
331 | + | else fraction(previouslyRequestedWithdraw, poolValue, lpTokenIssued) | |
332 | + | let targetLeaseAmount = fraction((poolValue - requestedWithdraw), validatorVotes, totalVotes) | |
333 | + | let cancel = match getBinary(validatorLeaseIdKey) { | |
334 | + | case id: ByteVector => | |
335 | + | [LeaseCancel(id)] | |
336 | + | case _: Unit => | |
337 | + | nil | |
338 | + | case _ => | |
339 | + | throw("Match error") | |
340 | + | } | |
341 | + | if ((targetLeaseAmount != currentLeaseAmount)) | |
342 | + | then { | |
343 | + | let lease = Lease(validatorAddress, targetLeaseAmount) | |
344 | + | (cancel ++ (if ((targetLeaseAmount == 0)) | |
345 | + | then [IntegerEntry(("validatorLeases:" + validator), targetLeaseAmount), DeleteEntry(validatorLeaseIdKey)] | |
346 | + | else [lease, BinaryEntry(validatorLeaseIdKey, calculateLeaseId(lease)), IntegerEntry(("validatorLeases:" + validator), targetLeaseAmount), IntegerEntry(latestLeasingCycleKey, currentCycle)])) | |
347 | + | } | |
348 | + | else throw("Nothing changes") | |
349 | + | } | |
350 | + | else throw("Strict value is not equal to itself.") | |
351 | + | } | |
352 | + | else throw("Strict value is not equal to itself.") | |
353 | + | } | |
354 | + | else throw("Strict value is not equal to itself.") | |
355 | + | } | |
356 | + | ||
357 | + | ||
358 | + | ||
359 | + | @Callable(invocation) | |
360 | + | func emergencyVoting (validator) = { | |
361 | + | let validatorAddress = addressFromStringValue(validator) | |
362 | + | let _assertValidatorAddress = assertValidatorAddress(validatorAddress) | |
363 | + | if ((_assertValidatorAddress == _assertValidatorAddress)) | |
364 | + | then { | |
365 | + | let _assetValidatorStatus = assertActiveValidatorStatus(validatorAddress) | |
366 | + | if ((_assetValidatorStatus == _assetValidatorStatus)) | |
367 | + | then { | |
368 | + | let _assertOnePayment = assertOnePayment(invocation) | |
369 | + | if ((_assertOnePayment == _assertOnePayment)) | |
370 | + | then { | |
371 | + | let _assertPaymentAsset = assertPaymentAsset(invocation, xWavesAssetId) | |
372 | + | if ((_assertPaymentAsset == _assertPaymentAsset)) | |
373 | + | then { | |
374 | + | let voteAmount = invocation.payments[0].amount | |
375 | + | let callerKey = toString(invocation.caller) | |
376 | + | let emergencyVotesKey = ("emergencyVotes:" + validator) | |
377 | + | let emergencyUserVotesKey = (("emergencyUserVotes:" + callerKey) + validator) | |
378 | + | let emergencyVotes = (voteAmount + valueOrElse(getInteger(emergencyVotesKey), 0)) | |
379 | + | let quantity = valueOrErrorMessage(assetInfo(xWavesAssetId), "Uknown asset id").quantity | |
380 | + | let wxxAssetInfo = valueOrErrorMessage(assetInfo(wxxAssetId), "Uknown asset id") | |
381 | + | let isValidatorBad = (((emergencyVotes * 100) / quantity) > emergencyVotingThreshold) | |
382 | + | let punishment = if (isValidatorBad) | |
383 | + | then { | |
384 | + | let validatorLeaseIdKey = ("leaseId:" + validator) | |
385 | + | let cancel = match getBinary(validatorLeaseIdKey) { | |
386 | + | case id: ByteVector => | |
387 | + | [LeaseCancel(id)] | |
388 | + | case _: Unit => | |
389 | + | nil | |
390 | + | case _ => | |
391 | + | throw("Match error") | |
392 | + | } | |
393 | + | let validatorVotesKey = ("votes:" + validator) | |
394 | + | let totalValidatorVotes = valueOrElse(getInteger(validatorVotesKey), 0) | |
395 | + | (cancel ++ [ScriptTransfer(wxxAssetInfo.issuer, requiredWXXAmount, wxxAssetId), IntegerEntry(totalVoteskey, (totalVotes - totalValidatorVotes)), BooleanEntry(("validatorStatus:" + validator), false), DeleteEntry(("validatorLeases:" + validator)), DeleteEntry(("leaseId:" + validator)), DeleteEntry(("latestLeasingCycle:" + validator))]) | |
396 | + | } | |
397 | + | else nil | |
398 | + | (punishment ++ [IntegerEntry(emergencyVotesKey, (voteAmount + emergencyVotes)), IntegerEntry(emergencyUserVotesKey, (valueOrElse(getInteger(emergencyUserVotesKey), 0) + emergencyVotes))]) | |
399 | + | } | |
400 | + | else throw("Strict value is not equal to itself.") | |
401 | + | } | |
402 | + | else throw("Strict value is not equal to itself.") | |
403 | + | } | |
404 | + | else throw("Strict value is not equal to itself.") | |
405 | + | } | |
406 | + | else throw("Strict value is not equal to itself.") | |
407 | + | } | |
408 | + | ||
409 | + | ||
410 | + | ||
411 | + | @Callable(invocation) | |
412 | + | func redeemEmergencyVote (validator) = { | |
413 | + | let validatorAddress = addressFromStringValue(validator) | |
414 | + | let callerKey = toString(invocation.caller) | |
415 | + | let emergencyUserVotesKey = (("emergencyUserVotes:" + callerKey) + validator) | |
416 | + | let emergencyUserVotes = valueOrErrorMessage(getInteger(emergencyUserVotesKey), "No emergency votes for user") | |
417 | + | [ScriptTransfer(invocation.caller, emergencyUserVotes, xWavesAssetId)] | |
418 | + | } | |
419 | + | ||
420 | + |
github/deemru/w8io/169f3d6 28.83 ms ◑![]()