tx · Civ8rCW7mavCc7qbzq3u6hgdbJTLASZqRvV4czv1AFE8 3MuL1yGdfqgUc4hoJe7uFg6feVQFmif3Wkr: -0.03100000 Waves 2025.04.11 15:52 [3584279] smart account 3MuL1yGdfqgUc4hoJe7uFg6feVQFmif3Wkr > SELF 0.00000000 Waves
{ "type": 13, "id": "Civ8rCW7mavCc7qbzq3u6hgdbJTLASZqRvV4czv1AFE8", "fee": 3100000, "feeAssetId": null, "timestamp": 1744375981800, "version": 2, "chainId": 84, "sender": "3MuL1yGdfqgUc4hoJe7uFg6feVQFmif3Wkr", "senderPublicKey": "BayhJDaR6KMN1T18joqBr5P8S5ScG3SHGTNpyHpJvNtd", "proofs": [ "52YYKu5keX2nbCoLyG67xpRsBo1ZaCJ9wpSXVqNexaoF7JuKHYHsd6n1NBHfeqytVkY8Ej3d2PWmZgu4Fhgh5e6x" ], "script": "base64:BwJVCAISCAoGAggICAgIEgASAwoBCBIDCgEIEgMKAQgSAwoBARIFCgMIAQESAwoBCBIAEgASABIDCgEIEgASBAoCCAESAwoBARIDCgEIEgMKAQgSAwoBAXgAC2Zsb3dMZWFzZVBrASCJ1zbFT/U+b0OeSEHFqOCQcKdkOSI1UdSmsNDi5FmDKQACQlAAkE4AEnJlcXVpcmVkRmxvd0Ftb3VudACAyK+gJQAVY3ljbGVEdXJhdGlvbkluQmxvY2tzAOgHAB5jeWNsZUR1cmF0aW9uSW5CbG9ja3NTcXJ0Rmxvb3IAAwAUbWluVm90ZUN5Y2xlSW50ZXJ2YWwAAQAPbWluVm90ZUludGVydmFsCQBoAgUVY3ljbGVEdXJhdGlvbkluQmxvY2tzBRRtaW5Wb3RlQ3ljbGVJbnRlcnZhbAAUbWF4Vm90ZUN5Y2xlSW50ZXJ2YWwAkgQAD21heFZvdGVJbnRlcnZhbAkAaAIFFWN5Y2xlRHVyYXRpb25JbkJsb2NrcwUUbWF4Vm90ZUN5Y2xlSW50ZXJ2YWwAGGVtZXJnZW5jeVZvdGluZ1RocmVzaG9sZAAKABtlbWVyZ2VuY3lWb3RpbmdMb2NrSW5DeWNsZXMACgATZW1lcmdlbmN5Vm90aW5nTG9jawkAaAIFG2VtZXJnZW5jeVZvdGluZ0xvY2tJbkN5Y2xlcwUVY3ljbGVEdXJhdGlvbkluQmxvY2tzAA1hZG1pbk11bHRpU2lnCQDMCAICDnNldFN0b3BNYW5hZ2VyCQDMCAICD3NldEZlZUNvbGxlY3RvcgkAzAgCAghzZXRBZG1pbgkAzAgCAg1zZXRBZG1pbkZlZUJQCQDMCAICEHN3YXBSZXdhcmRUb2tlbnMFA25pbAAXdmFsaWRhdG9yU3RhdHVzRW50cnlLZXkCEHZhbGlkYXRvclN0YXR1czoAGGFjdGl2ZVZhbGlkYXRvcnNFbnRyeUtleQIQYWN0aXZlVmFsaWRhdG9ycwASYWRtaW5GZWVCUEVudHJ5S2V5AgphZG1pbkZlZUJQABhsZWFzaW5nUG9vbFZhbHVlRW50cnlLZXkCEWxlYXNpbmdQb29sVmFsdWU6AB1jeWNsZUR1cmF0aW9uSW5CbG9ja3NFbnRyeUtleQIVY3ljbGVEdXJhdGlvbkluQmxvY2tzABplbWVyZ2VuY3lVc2VyVm90ZXNFbnRyeUtleQITZW1lcmdlbmN5VXNlclZvdGVzOgAWZW1lcmdlbmN5Vm90ZXNFbnRyeUtleQIPZW1lcmdlbmN5Vm90ZXM6ACBlbWVyZ2VuY3lWb3RpbmdUaHJlc2hvbGRFbnRyeUtleQIYZW1lcmdlbmN5Vm90aW5nVGhyZXNob2xkABllbWVyZ2VuY3lVc2VyTG9ja0VudHJ5S2V5AhJlbWVyZ2VuY3lVc2VyTG9jazoAG2lzTGVhc2luZ0luUHJvZ3Jlc3NFbnRyeUtleQIUaXNMZWFzaW5nSW5Qcm9ncmVzczoAGmxhdGVzdExlYXNpbmdDeWNsZUVudHJ5S2V5AhJsYXRlc3RMZWFzaW5nQ3ljbGUAI2xhdGVzdFZhbGlkYXRvckxlYXNpbmdDeWNsZUVudHJ5S2V5AhNsYXRlc3RMZWFzaW5nQ3ljbGU6ABlyZWdpc3RyYXRpb25DeWNsZUVudHJ5S2V5AhJyZWdpc3RyYXRpb25DeWNsZToAD2xlYXNlSWRFbnRyeUtleQIIbGVhc2VJZDoAF3Byb2Nlc3NlZExlYXNlc0VudHJ5S2V5AhBwcm9jZXNzZWRMZWFzZXM6AB9yZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0VudHJ5S2V5AhhyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhdzoAHnJlcXVlc3RlZFdhdmVzV2l0aGRyYXdFbnRyeUtleQIXcmVxdWVzdGVkV2F2ZXNXaXRoZHJhdzoAGnJlcXVpcmVkRmxvd0Ftb3VudEVudHJ5S2V5AhJyZXF1aXJlZEZsb3dBbW91bnQAEnN0YXJ0QmxvY2tFbnRyeUtleQIKc3RhcnRCbG9jawAWY29udHJhY3RTdGF0dXNFbnRyeUtleQIOY29udHJhY3RTdGF0dXMAE3N0b3BNYW5hZ2VyRW50cnlLZXkCC3N0b3BNYW5hZ2VyACN0b3RhbFJlcXVlc3RlZFdhdmVzV2l0aGRyYXdFbnRyeUtleQIbdG90YWxSZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3ABJ0b3RhbFZvdGVzRW50cnlLZXkCCnRvdGFsVm90ZXMAE3VubG9ja0Jsb2NrRW50cnlLZXkCDHVubG9ja0Jsb2NrOgAQdXNlckxvY2tFbnRyeUtleQIJdXNlckxvY2s6ABB1c2VyVm90ZUVudHJ5S2V5Agl1c2VyVm90ZToAFXZhbGlkYXRvck1ldGFFbnRyeUtleQIOdmFsaWRhdG9yTWV0YToAGHZhbGlkYXRvckFkZHJlc3NFbnRyeUtleQIRdmFsaWRhdG9yQWRkcmVzczoAE3ZhbGlkYXRvcklkRW50cnlLZXkCDHZhbGlkYXRvcklkOgAXdmFsaWRhdG9yTGVhc2VzRW50cnlLZXkCEHZhbGlkYXRvckxlYXNlczoADXZvdGVzRW50cnlLZXkCBnZvdGVzOgAjd2l0aGRyYXdGV2F2ZXNRdWFudGl0eVN0YXRlRW50cnlLZXkCG3dpdGhkcmF3RldhdmVzUXVhbnRpdHlTdGF0ZQAhd2l0aGRyYXdXYXZlc0JhbGFuY2VTdGF0ZUVudHJ5S2V5Ahl3aXRoZHJhd1dhdmVzQmFsYW5jZVN0YXRlABNmbG93QXNzZXRJZEVudHJ5S2V5AgtmbG93QXNzZXRJZAAVZldhdmVzQXNzZXRJZEVudHJ5S2V5Ag1mV2F2ZXNBc3NldElkABVmV2F2ZXNXcmFwcGVyRW50cnlLZXkCDWZXYXZlc1dyYXBwZXIAGWFkbWluRmVlQ29sbGVjdG9yRW50cnlLZXkCEWFkbWluRmVlQ29sbGVjdG9yABRpZ25vcmVkVm90ZXNFbnRyeUtleQIMaWdub3JlVm90ZXM6ABlpZ25vcmVkVmFsaWRhdG9yc0VudHJ5S2V5AhJpZ25vcmVkVmFsaWRhdG9yczoAD2FkbWluUEtFbnRyeUtleQIHYWRtaW5QSwAWZldhdmVzUXVhbnRpdHlFbnRyeUtleQIOZldhdmVzUXVhbnRpdHkAEnB1enpsZVN3YXBFbnRyeUtleQIKcHV6emxlU3dhcAAXZXJyb3JNZXNzYWdlVW5yZWFjaGFibGUCC1VucmVhY2hhYmxlAB5lcnJvck1lc3NhZ2VBbHJlYWR5SW5pdGlhbGl6ZWQCE0FscmVhZHkgaW5pdGlhbGl6ZWQAGWVycm9yTWVzc2FnZUFscmVhZHlMZWFzZWQCDkFscmVhZHkgbGVhc2VkAB1lcnJvck1lc3NhZ2VBbHJlYWR5UmVnaXN0ZXJlZAISQWxyZWFkeSByZWdpc3RlcmVkAB1lcnJvck1lc3NhZ2VDb250cmFjdE5vdEFjdGl2ZQIWQ29udHJhY3QgaXMgbm90IGFjdGl2ZQAbZXJyb3JNZXNzYWdlSW52YWxpZEludGVydmFsAhBJbnZhbGlkIGludGVydmFsAB1lcnJvck1lc3NhZ2VJbnZhbGlkRmxvd0Ftb3VudAITSW52YWxpZCBGbG93IGFtb3VudAAdZXJyb3JNZXNzYWdlTGVhc2luZ0luUHJvZ3Jlc3MCE0xlYXNpbmcgaW4gcHJvZ3Jlc3MAHGVycm9yTWVzc2FnZU5vRW1lcmdlbmN5Vm90ZXMCG05vIGVtZXJnZW5jeSB2b3RlcyBmb3IgdXNlcgAfZXJyb3JNZXNzYWdlTm9SZXF1ZXN0ZWRXaXRoZHJhdwIVTm8gcmVxdWVzdGVkIHdpdGhkcmF3ABllcnJvck1lc3NhZ2VOb3RPbmVQYXltZW50Ag9Ob3Qgb25lIHBheW1lbnQAFGVycm9yTWVzc2FnZVRvb0Vhcmx5AglUb28gZWFybHkAGGVycm9yTWVzc2FnZVVuYXV0aG9yaXplZAIMVW5hdXRob3JpemVkAB1lcnJvck1lc3NhZ2VVbmV4cGVjdGVkQXNzZXRJZAITVW5leHBlY3RlZCBhc3NldCBpZAAXZXJyb3JNZXNzYWdlVW5rbm93bkxvY2sCDFVua25vd24gbG9jawAcZXJyb3JNZXNzYWdlVW5rbm93blZhbGlkYXRvcgIRVW5rbm93biB2YWxpZGF0b3IAJGVycm9yTWVzc2FnZVZhbGlkYXRvck5vdFJlYWR5VG9MZWFzZQIfVmFsaWRhdG9yIGlzIG5vdCByZWFkeSB0byBsZWFzZQAhZXJyb3JNZXNzYWdlV2F2ZXNCYWxhbmNlTm90RW5vdWdoAiJOb3QgZW5vdWdoIFdBVkVTLiBQbGVhc2UgdHJ5IGxhdGVyAB5lcnJvck1lc3NhZ2VWYWxpZGF0b3JXYXNLaWNrZWQCFFZhbGlkYXRvciB3YXMga2lja2VkAB1lcnJvck1lc3NhZ2VJbnZhbGlkQWRtaW5GZWVCUAISSW52YWxpZCBhZG1pbkZlZUJQABdlcnJvck1lc3NhZ2VJbnZhbGlkVWludAIMSW52YWxpZCBVaW50AAlhdmFpbGFibGUICQDvBwEFBHRoaXMJYXZhaWxhYmxlAAtmbG93QXNzZXRJZAkBEUBleHRyTmF0aXZlKDEwNTcpAQUTZmxvd0Fzc2V0SWRFbnRyeUtleQANZldhdmVzQXNzZXRJZAkBEUBleHRyTmF0aXZlKDEwNTcpAQUVZldhdmVzQXNzZXRJZEVudHJ5S2V5AA1mV2F2ZXNXcmFwcGVyCQEHQWRkcmVzcwEJARFAZXh0ck5hdGl2ZSgxMDU3KQEFFWZXYXZlc1dyYXBwZXJFbnRyeUtleQANZmxvd0Fzc2V0SW5mbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFC2Zsb3dBc3NldElkBRdlcnJvck1lc3NhZ2VVbnJlYWNoYWJsZQAOZldhdmVzUXVhbnRpdHkJARFAZXh0ck5hdGl2ZSgxMDU1KQEFFmZXYXZlc1F1YW50aXR5RW50cnlLZXkADGN1cnJlbnRDeWNsZQkAaQIJAGUCCAUJbGFzdEJsb2NrBmhlaWdodAkBEUBleHRyTmF0aXZlKDEwNTUpAQUSc3RhcnRCbG9ja0VudHJ5S2V5BRVjeWNsZUR1cmF0aW9uSW5CbG9ja3MAGXdpdGhkcmF3V2F2ZXNCYWxhbmNlU3RhdGUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUhd2l0aGRyYXdXYXZlc0JhbGFuY2VTdGF0ZUVudHJ5S2V5CAkA7wcBBQR0aGlzB3JlZ3VsYXIAG3dpdGhkcmF3RldhdmVzUXVhbnRpdHlTdGF0ZQkBC3ZhbHVlT3JFbHNlAgkAnwgBBSN3aXRoZHJhd0ZXYXZlc1F1YW50aXR5U3RhdGVFbnRyeUtleQUOZldhdmVzUXVhbnRpdHkAG2N1cnJlbnRDeWNsZUlnbm9yZWRWb3Rlc0tleQkArAICBRRpZ25vcmVkVm90ZXNFbnRyeUtleQkApAMBBQxjdXJyZW50Q3ljbGUAIGN1cnJlbnRDeWNsZUlnbm9yZWRWYWxpZGF0b3JzS2V5CQCsAgIFGWlnbm9yZWRWYWxpZGF0b3JzRW50cnlLZXkJAKQDAQUMY3VycmVudEN5Y2xlABhjdXJyZW50Q3ljbGVJZ25vcmVkVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUbY3VycmVudEN5Y2xlSWdub3JlZFZvdGVzS2V5AAAAHWN1cnJlbnRDeWNsZUlnbm9yZWRWYWxpZGF0b3JzCQELdmFsdWVPckVsc2UCCQCfCAEFIGN1cnJlbnRDeWNsZUlnbm9yZWRWYWxpZGF0b3JzS2V5AAAACnRvdGFsVm90ZXMJARFAZXh0ck5hdGl2ZSgxMDU1KQEFEnRvdGFsVm90ZXNFbnRyeUtleQAddG90YWxWb3Rlc1dpdGhvdXRJZ25vcmVkVm90ZXMJAGUCBQp0b3RhbFZvdGVzBRhjdXJyZW50Q3ljbGVJZ25vcmVkVm90ZXMAG3RvdGFsUmVxdWVzdGVkV2F2ZXNXaXRoZHJhdwkBC3ZhbHVlT3JFbHNlAgkAnwgBBSN0b3RhbFJlcXVlc3RlZFdhdmVzV2l0aGRyYXdFbnRyeUtleQAAAA5jb250cmFjdFN0YXR1cwkBEUBleHRyTmF0aXZlKDEwNTYpAQUWY29udHJhY3RTdGF0dXNFbnRyeUtleQALc3RvcE1hbmFnZXIJARFAZXh0ck5hdGl2ZSgxMDU3KQEFE3N0b3BNYW5hZ2VyRW50cnlLZXkABWFkbWluCQERQGV4dHJOYXRpdmUoMTA1NykBBQ9hZG1pblBLRW50cnlLZXkACmFkbWluRmVlQlAJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUSYWRtaW5GZWVCUEVudHJ5S2V5ADIAEGFjdGl2ZVZhbGlkYXRvcnMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUYYWN0aXZlVmFsaWRhdG9yc0VudHJ5S2V5AAAAHmFjdGl2ZVZhbGlkYXRvcnNXaXRob3V0SWdub3JlZAkAZQIFEGFjdGl2ZVZhbGlkYXRvcnMFHWN1cnJlbnRDeWNsZUlnbm9yZWRWYWxpZGF0b3JzAApwdXp6bGVTd2FwCQEHQWRkcmVzcwEJARFAZXh0ck5hdGl2ZSgxMDU3KQEFEnB1enpsZVN3YXBFbnRyeUtleQEGYXNzZXJ0AgF2AWUDBQF2BQR1bml0CQACAQUBZQEJYm9vbFRvSW50AQFiAwUBYgABAAABCVVpbnRFbnRyeQIDa2V5AXYEC19hc3NlcnRVaW50CQEGYXNzZXJ0AgkAZwIFAXYAAAUXZXJyb3JNZXNzYWdlSW52YWxpZFVpbnQDCQAAAgULX2Fzc2VydFVpbnQFC19hc3NlcnRVaW50CQEMSW50ZWdlckVudHJ5AgUDa2V5BQF2CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARJnZXRWYWxpZGF0b3JTdGF0dXMBEHZhbGlkYXRvckFkZHJlc3MJAKAIAQkArAICBRd2YWxpZGF0b3JTdGF0dXNFbnRyeUtleQkApQgBBRB2YWxpZGF0b3JBZGRyZXNzARdnZXRWYWxpZGF0b3JTdGF0dXNWYWx1ZQEQdmFsaWRhdG9yQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQESZ2V0VmFsaWRhdG9yU3RhdHVzAQUQdmFsaWRhdG9yQWRkcmVzcwUcZXJyb3JNZXNzYWdlVW5rbm93blZhbGlkYXRvcgEaZ2V0Q2FuY2VsTGVhc2VGb3JWYWxpZGF0b3IBEHZhbGlkYXRvckFkZHJlc3MEE3ZhbGlkYXRvckxlYXNlSWRLZXkJAKwCAgUPbGVhc2VJZEVudHJ5S2V5CQDYBAEIBRB2YWxpZGF0b3JBZGRyZXNzBWJ5dGVzBAckbWF0Y2gwCQChCAEFE3ZhbGlkYXRvckxlYXNlSWRLZXkDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCaWQFByRtYXRjaDAJAMwIAgkBC0xlYXNlQ2FuY2VsAQUCaWQFA25pbAMJAAECBQckbWF0Y2gwAgRVbml0BQNuaWwJAAIBAgtNYXRjaCBlcnJvcgEZZ2V0UmVnaXN0cmF0aW9uQ3ljbGVWYWx1ZQEQdmFsaWRhdG9yQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJAKwCAgUZcmVnaXN0cmF0aW9uQ3ljbGVFbnRyeUtleQkApQgBBRB2YWxpZGF0b3JBZGRyZXNzBRxlcnJvck1lc3NhZ2VVbmtub3duVmFsaWRhdG9yARZnZXRWYWxpZGF0b3JJZHNDaGFuZ2VzARB2YWxpZGF0b3JBZGRyZXNzBBJ0aGlzVmFsaWRhdG9ySWRLZXkJAKwCAgUTdmFsaWRhdG9ySWRFbnRyeUtleQkApQgBBRB2YWxpZGF0b3JBZGRyZXNzBA90aGlzVmFsaWRhdG9ySWQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFEnRoaXNWYWxpZGF0b3JJZEtleQQXdGhpc1ZhbGlkYXRvckFkZHJlc3NLZXkJAKwCAgUYdmFsaWRhdG9yQWRkcmVzc0VudHJ5S2V5CQCkAwEFD3RoaXNWYWxpZGF0b3JJZAMDCQAAAgUPdGhpc1ZhbGlkYXRvcklkBRBhY3RpdmVWYWxpZGF0b3JzBgkAAAIFEGFjdGl2ZVZhbGlkYXRvcnMAAQkAzAgCCQELRGVsZXRlRW50cnkBBRJ0aGlzVmFsaWRhdG9ySWRLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUXdGhpc1ZhbGlkYXRvckFkZHJlc3NLZXkFA25pbAQXbGFzdFZhbGlkYXRvckFkZHJlc3NLZXkJAKwCAgUYdmFsaWRhdG9yQWRkcmVzc0VudHJ5S2V5CQCkAwEFEGFjdGl2ZVZhbGlkYXRvcnMEEmxhc3RWYWxpZGF0b3JCeXRlcwkBEUBleHRyTmF0aXZlKDEwNTcpAQUXbGFzdFZhbGlkYXRvckFkZHJlc3NLZXkEEmxhc3RWYWxpZGF0b3JJZEtleQkArAICBRN2YWxpZGF0b3JJZEVudHJ5S2V5CQDYBAEFEmxhc3RWYWxpZGF0b3JCeXRlcwkAzAgCCQEMSW50ZWdlckVudHJ5AgUSbGFzdFZhbGlkYXRvcklkS2V5BQ90aGlzVmFsaWRhdG9ySWQJAMwIAgkBC0JpbmFyeUVudHJ5AgUXdGhpc1ZhbGlkYXRvckFkZHJlc3NLZXkFEmxhc3RWYWxpZGF0b3JCeXRlcwkAzAgCCQELRGVsZXRlRW50cnkBBRJ0aGlzVmFsaWRhdG9ySWRLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUXbGFzdFZhbGlkYXRvckFkZHJlc3NLZXkFA25pbAEWYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwEQdmFsaWRhdG9yQWRkcmVzcwkBBmFzc2VydAIJAQlpc0RlZmluZWQBCQCiCAEJAKwCAgUVdmFsaWRhdG9yTWV0YUVudHJ5S2V5CQClCAEFEHZhbGlkYXRvckFkZHJlc3MFHGVycm9yTWVzc2FnZVVua25vd25WYWxpZGF0b3IBEGFzc2VydE9uZVBheW1lbnQBCmludm9jYXRpb24JAQZhc3NlcnQCCQAAAgkAkAMBCAUKaW52b2NhdGlvbghwYXltZW50cwABBRllcnJvck1lc3NhZ2VOb3RPbmVQYXltZW50ARphc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwAEE2lzTGVhc2luZ0luUHJvZ3Jlc3MJAQt2YWx1ZU9yRWxzZQIJAKAIAQkArAICBRtpc0xlYXNpbmdJblByb2dyZXNzRW50cnlLZXkJAKQDAQUMY3VycmVudEN5Y2xlBwkBBmFzc2VydAIJAQEhAQUTaXNMZWFzaW5nSW5Qcm9ncmVzcwUdZXJyb3JNZXNzYWdlTGVhc2luZ0luUHJvZ3Jlc3MBEmFzc2VydFBheW1lbnRBc3NldAIKaW52b2NhdGlvbg1leHBlY3RlZFRva2VuCQEGYXNzZXJ0AgkAAAIICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAHYXNzZXRJZAUNZXhwZWN0ZWRUb2tlbgUdZXJyb3JNZXNzYWdlVW5leHBlY3RlZEFzc2V0SWQBFWFzc2VydE9uZVBheW1lbnRBc3NldAIKaW52b2NhdGlvbg1leHBlY3RlZFRva2VuBBFfYXNzZXJ0T25lUGF5bWVudAkBEGFzc2VydE9uZVBheW1lbnQBBQppbnZvY2F0aW9uAwkAAAIFEV9hc3NlcnRPbmVQYXltZW50BRFfYXNzZXJ0T25lUGF5bWVudAQTX2Fzc2VydFBheW1lbnRBc3NldAkBEmFzc2VydFBheW1lbnRBc3NldAIFCmludm9jYXRpb24FDWV4cGVjdGVkVG9rZW4DCQAAAgUTX2Fzc2VydFBheW1lbnRBc3NldAUTX2Fzc2VydFBheW1lbnRBc3NldAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEeYXNzZXJ0Tm90S2lja2VkVmFsaWRhdG9yU3RhdHVzARB2YWxpZGF0b3JBZGRyZXNzCQEGYXNzZXJ0AgkBF2dldFZhbGlkYXRvclN0YXR1c1ZhbHVlAQUQdmFsaWRhdG9yQWRkcmVzcwUeZXJyb3JNZXNzYWdlVmFsaWRhdG9yV2FzS2lja2VkARphc3NlcnRWYWxpZGF0b3JJc0xlYXNlYWJsZQEQdmFsaWRhdG9yQWRkcmVzcwkBBmFzc2VydAIJAGYCBQxjdXJyZW50Q3ljbGUJARlnZXRSZWdpc3RyYXRpb25DeWNsZVZhbHVlAQUQdmFsaWRhdG9yQWRkcmVzcwUkZXJyb3JNZXNzYWdlVmFsaWRhdG9yTm90UmVhZHlUb0xlYXNlARphc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwAJAQZhc3NlcnQCBQ5jb250cmFjdFN0YXR1cwUdZXJyb3JNZXNzYWdlQ29udHJhY3ROb3RBY3RpdmUBDGFzc2VydENhbGxlcgIKaW52b2NhdGlvbghleHBlY3RlZAkBBmFzc2VydAIJAAACBQhleHBlY3RlZAgIBQppbnZvY2F0aW9uBmNhbGxlcgVieXRlcwUYZXJyb3JNZXNzYWdlVW5hdXRob3JpemVkARZhc3NlcnRDYWxsZXJJc0NvbnRyYWN0AQppbnZvY2F0aW9uCQEMYXNzZXJ0Q2FsbGVyAgUKaW52b2NhdGlvbggFBHRoaXMFYnl0ZXMBGWFzc2VydENhbGxlcklzU3RvcE1hbmFnZXIBCmludm9jYXRpb24JAQxhc3NlcnRDYWxsZXICBQppbnZvY2F0aW9uBQtzdG9wTWFuYWdlcgETYXNzZXJ0Q2FsbGVySXNBZG1pbgEKaW52b2NhdGlvbgkBDGFzc2VydENhbGxlcgIFCmludm9jYXRpb24FBWFkbWluAQ9hc3NlcnRDYW5VbmxvY2sCC3VubG9ja0Jsb2NrCXZhbGlkYXRvcgkBBmFzc2VydAIDCQBnAggFCWxhc3RCbG9jawZoZWlnaHQFC3VubG9ja0Jsb2NrBgkBASEBCQELdmFsdWVPckVsc2UCCQESZ2V0VmFsaWRhdG9yU3RhdHVzAQUJdmFsaWRhdG9yBwUUZXJyb3JNZXNzYWdlVG9vRWFybHkSCmludm9jYXRpb24BBGluaXQGC2Zsb3dUb2tlbklkB2FkbWluUGsLc3RvcE1hbmFnZXIMZmVlQ29sbGVjdG9yCnB1enpsZVN3YXANZldhdmVzV3JhcHBlcgQLY2FsbGVyQ2hlY2sJARZhc3NlcnRDYWxsZXJJc0NvbnRyYWN0AQUKaW52b2NhdGlvbgMJAAACBQtjYWxsZXJDaGVjawULY2FsbGVyQ2hlY2sEDl9hc3NlcnROb3RJbml0CQEGYXNzZXJ0AgkBASEBCQEJaXNEZWZpbmVkAQkAnwgBBRJzdGFydEJsb2NrRW50cnlLZXkFHmVycm9yTWVzc2FnZUFscmVhZHlJbml0aWFsaXplZAMJAAACBQ5fYXNzZXJ0Tm90SW5pdAUOX2Fzc2VydE5vdEluaXQEEnN0b3BNYW5hZ2VyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQULc3RvcE1hbmFnZXIEE2ZlZUNvbGxlY3RvckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDGZlZUNvbGxlY3RvcgQRcHV6emxlU3dhcEFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCnB1enpsZVN3YXAEFGZXYXZlc1dyYXBwZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQ1mV2F2ZXNXcmFwcGVyBAhmV2F2ZXNJZAkBEUBleHRyTmF0aXZlKDEwNTIpAgUUZldhdmVzV3JhcHBlckFkZHJlc3MCDWZXYXZlc0Fzc2V0SWQEDGFkbWluUGtCeXRlcwkA2QQBBQdhZG1pblBrBA1fY2hlY2tBZGRyZXNzCQCnCAEFDGFkbWluUGtCeXRlcwMJAAACBQ1fY2hlY2tBZGRyZXNzBQ1fY2hlY2tBZGRyZXNzCQDMCAIJAQlVaW50RW50cnkCBRJ0b3RhbFZvdGVzRW50cnlLZXkAAAkAzAgCCQEJVWludEVudHJ5AgUWZldhdmVzUXVhbnRpdHlFbnRyeUtleQAACQDMCAIJAQxCb29sZWFuRW50cnkCBRZjb250cmFjdFN0YXR1c0VudHJ5S2V5BgkAzAgCCQELQmluYXJ5RW50cnkCBRNmbG93QXNzZXRJZEVudHJ5S2V5BQtmbG93VG9rZW5JZAkAzAgCCQELQmluYXJ5RW50cnkCBRVmV2F2ZXNBc3NldElkRW50cnlLZXkFCGZXYXZlc0lkCQDMCAIJAQlVaW50RW50cnkCBRJhZG1pbkZlZUJQRW50cnlLZXkFCmFkbWluRmVlQlAJAMwIAgkBC0JpbmFyeUVudHJ5AgUPYWRtaW5QS0VudHJ5S2V5BQxhZG1pblBrQnl0ZXMJAMwIAgkBCVVpbnRFbnRyeQIFI3RvdGFsUmVxdWVzdGVkV2F2ZXNXaXRoZHJhd0VudHJ5S2V5AAAJAMwIAgkBCVVpbnRFbnRyeQIFEnN0YXJ0QmxvY2tFbnRyeUtleQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkBCVVpbnRFbnRyeQIFGnJlcXVpcmVkRmxvd0Ftb3VudEVudHJ5S2V5BRJyZXF1aXJlZEZsb3dBbW91bnQJAMwIAgkBC0JpbmFyeUVudHJ5AgUTc3RvcE1hbmFnZXJFbnRyeUtleQgFEnN0b3BNYW5hZ2VyQWRkcmVzcwVieXRlcwkAzAgCCQEJVWludEVudHJ5AgUdY3ljbGVEdXJhdGlvbkluQmxvY2tzRW50cnlLZXkFFWN5Y2xlRHVyYXRpb25JbkJsb2NrcwkAzAgCCQELQmluYXJ5RW50cnkCBRlhZG1pbkZlZUNvbGxlY3RvckVudHJ5S2V5CAUTZmVlQ29sbGVjdG9yQWRkcmVzcwVieXRlcwkAzAgCCQEJVWludEVudHJ5AgUgZW1lcmdlbmN5Vm90aW5nVGhyZXNob2xkRW50cnlLZXkFGGVtZXJnZW5jeVZvdGluZ1RocmVzaG9sZAkAzAgCCQELQmluYXJ5RW50cnkCBRJwdXp6bGVTd2FwRW50cnlLZXkIBRFwdXp6bGVTd2FwQWRkcmVzcwVieXRlcwkAzAgCCQELQmluYXJ5RW50cnkCBRVmV2F2ZXNXcmFwcGVyRW50cnlLZXkIBRRmV2F2ZXNXcmFwcGVyQWRkcmVzcwVieXRlcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BBHN0b3AABAtjYWxsZXJDaGVjawkBGWFzc2VydENhbGxlcklzU3RvcE1hbmFnZXIBBQppbnZvY2F0aW9uAwkAAAIFC2NhbGxlckNoZWNrBQtjYWxsZXJDaGVjawkAzAgCCQEMQm9vbGVhbkVudHJ5AgUWY29udHJhY3RTdGF0dXNFbnRyeUtleQcFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQ5zZXRTdG9wTWFuYWdlcgEObmV3U3RvcE1hbmFnZXIEC2NhbGxlckNoZWNrCQEWYXNzZXJ0Q2FsbGVySXNDb250cmFjdAEFCmludm9jYXRpb24DCQAAAgULY2FsbGVyQ2hlY2sFC2NhbGxlckNoZWNrBBVuZXdTdG9wTWFuYWdlckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDm5ld1N0b3BNYW5hZ2VyCQDMCAIJAQtCaW5hcnlFbnRyeQIFE3N0b3BNYW5hZ2VyRW50cnlLZXkIBRVuZXdTdG9wTWFuYWdlckFkZHJlc3MFYnl0ZXMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQ9zZXRGZWVDb2xsZWN0b3IBD25ld0ZlZUNvbGxlY3RvcgQLY2FsbGVyQ2hlY2sJARZhc3NlcnRDYWxsZXJJc0NvbnRyYWN0AQUKaW52b2NhdGlvbgMJAAACBQtjYWxsZXJDaGVjawULY2FsbGVyQ2hlY2sEFm5ld0ZlZUNvbGxlY3RvckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFD25ld0ZlZUNvbGxlY3RvcgkAzAgCCQELQmluYXJ5RW50cnkCBRlhZG1pbkZlZUNvbGxlY3RvckVudHJ5S2V5CAUWbmV3RmVlQ29sbGVjdG9yQWRkcmVzcwVieXRlcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BCHNldEFkbWluAQhuZXdBZG1pbgQLY2FsbGVyQ2hlY2sJARZhc3NlcnRDYWxsZXJJc0NvbnRyYWN0AQUKaW52b2NhdGlvbgMJAAACBQtjYWxsZXJDaGVjawULY2FsbGVyQ2hlY2sEDW5ld0FkbWluQnl0ZXMJANkEAQUIbmV3QWRtaW4EDV9jaGVja0FkZHJlc3MJAKcIAQUNbmV3QWRtaW5CeXRlcwMJAAACBQ1fY2hlY2tBZGRyZXNzBQ1fY2hlY2tBZGRyZXNzCQDMCAIJAQtCaW5hcnlFbnRyeQIFD2FkbWluUEtFbnRyeUtleQUNbmV3QWRtaW5CeXRlcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BDXNldEFkbWluRmVlQlABDW5ld0FkbWluRmVlQlAEC2NhbGxlckNoZWNrCQEWYXNzZXJ0Q2FsbGVySXNDb250cmFjdAEFCmludm9jYXRpb24DCQAAAgULY2FsbGVyQ2hlY2sFC2NhbGxlckNoZWNrBBBfY2hlY2tBZG1pbkZlZUJQCQEGYXNzZXJ0AgMJAGcCBQ1uZXdBZG1pbkZlZUJQAAAJAGcCBQJCUAUNbmV3QWRtaW5GZWVCUAcFHWVycm9yTWVzc2FnZUludmFsaWRBZG1pbkZlZUJQAwkAAAIFEF9jaGVja0FkbWluRmVlQlAFEF9jaGVja0FkbWluRmVlQlAJAMwIAgkBCVVpbnRFbnRyeQIFEmFkbWluRmVlQlBFbnRyeUtleQUNbmV3QWRtaW5GZWVCUAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BEHN3YXBSZXdhcmRUb2tlbnMDCXJvdXRlc1N0cgZhbW91bnQMbWluVG9SZWNlaXZlBAtjYWxsZXJDaGVjawkBFmFzc2VydENhbGxlcklzQ29udHJhY3QBBQppbnZvY2F0aW9uAwkAAAIFC2NhbGxlckNoZWNrBQtjYWxsZXJDaGVjawQNc3BsaXR0ZWRSb3V0ZQkAtQkCCQCyAgIFCXJvdXRlc1N0cgAyAgEsBAlhc3NldDFTdHIJAJEDAgUNc3BsaXR0ZWRSb3V0ZQkAZQIJAJADAQUNc3BsaXR0ZWRSb3V0ZQABBAZhc3NldDEJANkEAQUJYXNzZXQxU3RyBAZzd2FwZWQJAPwHBAUKcHV6emxlU3dhcAIEc3dhcAkAzAgCBQlyb3V0ZXNTdHIJAMwIAgUMbWluVG9SZWNlaXZlBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFBmFzc2V0MQUGYW1vdW50BQNuaWwDCQAAAgUGc3dhcGVkBQZzd2FwZWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQhyZWdpc3RlcgELbWV0YWRhdGFVcmwEG19hc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwkBGmFzc2VydENvbnRyYWN0QWN0aXZlU3RhdHVzAAMJAAACBRtfYXNzZXJ0Q29udHJhY3RBY3RpdmVTdGF0dXMFG19hc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwQbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzCQEaYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MAAwkAAAIFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwUbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzBBZfYXNzZXJ0T25lUGF5bWVudEFzc2V0CQEVYXNzZXJ0T25lUGF5bWVudEFzc2V0AgUKaW52b2NhdGlvbgULZmxvd0Fzc2V0SWQDCQAAAgUWX2Fzc2VydE9uZVBheW1lbnRBc3NldAUWX2Fzc2VydE9uZVBheW1lbnRBc3NldAQJdmFsaWRhdG9yCQClCAEIBQppbnZvY2F0aW9uBmNhbGxlcgQKZmxvd0Ftb3VudAgJAJEDAggFCmludm9jYXRpb24IcGF5bWVudHMAAAZhbW91bnQEDHZhbGlkYXRvcktleQkArAICBRV2YWxpZGF0b3JNZXRhRW50cnlLZXkFCXZhbGlkYXRvcgQUcmVnaXN0ZXJlZEluQ3ljbGVLZXkJAKwCAgUZcmVnaXN0cmF0aW9uQ3ljbGVFbnRyeUtleQUJdmFsaWRhdG9yBAJpZAkAZAIFEGFjdGl2ZVZhbGlkYXRvcnMAAQQOdmFsaWRhdG9ySWRLZXkJAKwCAgUTdmFsaWRhdG9ySWRFbnRyeUtleQUJdmFsaWRhdG9yBBN2YWxpZGF0b3JBZGRyZXNzS2V5CQCsAgIFGHZhbGlkYXRvckFkZHJlc3NFbnRyeUtleQkApAMBBQJpZAQUX2Fzc2VydE5vdFJlZ2lzdGVyZWQJAQZhc3NlcnQCCQEBIQEJAQlpc0RlZmluZWQBCQCiCAEFDHZhbGlkYXRvcktleQUdZXJyb3JNZXNzYWdlQWxyZWFkeVJlZ2lzdGVyZWQDCQAAAgUUX2Fzc2VydE5vdFJlZ2lzdGVyZWQFFF9hc3NlcnROb3RSZWdpc3RlcmVkBBFfYXNzZXJ0RW5vdWdoRmxvdwkBBmFzc2VydAIJAAACBRJyZXF1aXJlZEZsb3dBbW91bnQFCmZsb3dBbW91bnQFHWVycm9yTWVzc2FnZUludmFsaWRGbG93QW1vdW50AwkAAAIFEV9hc3NlcnRFbm91Z2hGbG93BRFfYXNzZXJ0RW5vdWdoRmxvdwkAzAgCCQEJVWludEVudHJ5AgUUcmVnaXN0ZXJlZEluQ3ljbGVLZXkFDGN1cnJlbnRDeWNsZQkAzAgCCQELU3RyaW5nRW50cnkCBQx2YWxpZGF0b3JLZXkFC21ldGFkYXRhVXJsCQDMCAIJAQxCb29sZWFuRW50cnkCCQCsAgIFF3ZhbGlkYXRvclN0YXR1c0VudHJ5S2V5BQl2YWxpZGF0b3IGCQDMCAIJAQlVaW50RW50cnkCBSBjdXJyZW50Q3ljbGVJZ25vcmVkVmFsaWRhdG9yc0tleQkAZAIFHWN1cnJlbnRDeWNsZUlnbm9yZWRWYWxpZGF0b3JzAAEJAMwIAgkBCVVpbnRFbnRyeQIFGGFjdGl2ZVZhbGlkYXRvcnNFbnRyeUtleQkAZAIFEGFjdGl2ZVZhbGlkYXRvcnMAAQkAzAgCCQEMSW50ZWdlckVudHJ5AgUOdmFsaWRhdG9ySWRLZXkFAmlkCQDMCAIJAQtCaW5hcnlFbnRyeQIFE3ZhbGlkYXRvckFkZHJlc3NLZXkICAUKaW52b2NhdGlvbgZjYWxsZXIFYnl0ZXMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQpkZXJlZ2lzdGVyAAQbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzCQEaYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MAAwkAAAIFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwUbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzBBB2YWxpZGF0b3JBZGRyZXNzCAUKaW52b2NhdGlvbgZjYWxsZXIECXZhbGlkYXRvcgkApQgBCAUKaW52b2NhdGlvbgZjYWxsZXIEEnZhbGlkYXRvclN0YXR1c0tleQkArAICBRd2YWxpZGF0b3JTdGF0dXNFbnRyeUtleQUJdmFsaWRhdG9yBBF2YWxpZGF0b3JWb3Rlc0tleQkArAICBQ12b3Rlc0VudHJ5S2V5BQl2YWxpZGF0b3IEFHJlZ2lzdGVyZWRJbkN5Y2xlS2V5CQCsAgIFGXJlZ2lzdHJhdGlvbkN5Y2xlRW50cnlLZXkFCXZhbGlkYXRvcgQXX2Fzc2VydFZhbGlkYXRvckFkZHJlc3MJARZhc3NlcnRWYWxpZGF0b3JBZGRyZXNzAQUQdmFsaWRhdG9yQWRkcmVzcwMJAAACBRdfYXNzZXJ0VmFsaWRhdG9yQWRkcmVzcwUXX2Fzc2VydFZhbGlkYXRvckFkZHJlc3MEE3ZhbGlkYXRvcklkc0NoYW5nZXMJARZnZXRWYWxpZGF0b3JJZHNDaGFuZ2VzAQUQdmFsaWRhdG9yQWRkcmVzcwQTdmFsaWRhdG9yTGVhc2VJZEtleQkArAICBQ9sZWFzZUlkRW50cnlLZXkFCXZhbGlkYXRvcgQGY2FuY2VsCQEaZ2V0Q2FuY2VsTGVhc2VGb3JWYWxpZGF0b3IBBRB2YWxpZGF0b3JBZGRyZXNzBBBub25LaWNrZWRDaGFuZ2VzAwkBF2dldFZhbGlkYXRvclN0YXR1c1ZhbHVlAQUQdmFsaWRhdG9yQWRkcmVzcwQOdmFsaWRhdG9yVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQURdmFsaWRhdG9yVm90ZXNLZXkAAAkAzggCBRN2YWxpZGF0b3JJZHNDaGFuZ2VzCQDMCAIJAQlVaW50RW50cnkCBRhhY3RpdmVWYWxpZGF0b3JzRW50cnlLZXkJAGUCBRBhY3RpdmVWYWxpZGF0b3JzAAEJAMwIAgkBCVVpbnRFbnRyeQIFEnRvdGFsVm90ZXNFbnRyeUtleQkAZQIFCnRvdGFsVm90ZXMFDnZhbGlkYXRvclZvdGVzCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFEHZhbGlkYXRvckFkZHJlc3MFEnJlcXVpcmVkRmxvd0Ftb3VudAULZmxvd0Fzc2V0SWQFA25pbAUDbmlsBBhpZ25vcmVkVmFsaWRhdG9yc0NoYW5nZXMDCQAAAgkBGWdldFJlZ2lzdHJhdGlvbkN5Y2xlVmFsdWUBBRB2YWxpZGF0b3JBZGRyZXNzBQxjdXJyZW50Q3ljbGUJAMwIAgkBCVVpbnRFbnRyeQIFIGN1cnJlbnRDeWNsZUlnbm9yZWRWYWxpZGF0b3JzS2V5CQBlAgUdY3VycmVudEN5Y2xlSWdub3JlZFZhbGlkYXRvcnMAAQUDbmlsBQNuaWwJAM4IAgkAzggCCQDOCAIFEG5vbktpY2tlZENoYW5nZXMFGGlnbm9yZWRWYWxpZGF0b3JzQ2hhbmdlcwUGY2FuY2VsCQDMCAIJAQtEZWxldGVFbnRyeQEFEXZhbGlkYXRvclZvdGVzS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFFHJlZ2lzdGVyZWRJbkN5Y2xlS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFEnZhbGlkYXRvclN0YXR1c0tleQkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIFFXZhbGlkYXRvck1ldGFFbnRyeUtleQUJdmFsaWRhdG9yCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUXdmFsaWRhdG9yTGVhc2VzRW50cnlLZXkFCXZhbGlkYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBBRN2YWxpZGF0b3JMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUjbGF0ZXN0VmFsaWRhdG9yTGVhc2luZ0N5Y2xlRW50cnlLZXkFCXZhbGlkYXRvcgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BB2RlcG9zaXQABBtfYXNzZXJ0Q29udHJhY3RBY3RpdmVTdGF0dXMJARphc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwADCQAAAgUbX2Fzc2VydENvbnRyYWN0QWN0aXZlU3RhdHVzBRtfYXNzZXJ0Q29udHJhY3RBY3RpdmVTdGF0dXMEG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwkBGmFzc2VydExlYXNpbmdOb3RJblByb2dyZXNzAAMJAAACBRtfYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwQWX2Fzc2VydE9uZVBheW1lbnRBc3NldAkBFWFzc2VydE9uZVBheW1lbnRBc3NldAIFCmludm9jYXRpb24FBHVuaXQDCQAAAgUWX2Fzc2VydE9uZVBheW1lbnRBc3NldAUWX2Fzc2VydE9uZVBheW1lbnRBc3NldAQLd2F2ZXNBbW91bnQICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAGYW1vdW50BAxmV2F2ZXNBbW91bnQDCQAAAgUOZldhdmVzUXVhbnRpdHkAAAULd2F2ZXNBbW91bnQJAGsDBQt3YXZlc0Ftb3VudAUOZldhdmVzUXVhbnRpdHkJAGUCCAkA7wcBBQR0aGlzB3JlZ3VsYXIFC3dhdmVzQW1vdW50BBFhZG1pbkZXYXZlc0Ftb3VudAkAbgQFDGZXYXZlc0Ftb3VudAUKYWRtaW5GZWVCUAUCQlAFB0NFSUxJTkcEG2ZXYXZlc0Ftb3VudFdpdGhvdXRBZG1pbkZlZQkAZQIFDGZXYXZlc0Ftb3VudAURYWRtaW5GV2F2ZXNBbW91bnQEGGFkbWluRmVlQ29sbGVjdG9yQWRkcmVzcwkBB0FkZHJlc3MBCQERQGV4dHJOYXRpdmUoMTA1NykBBRlhZG1pbkZlZUNvbGxlY3RvckVudHJ5S2V5BARtaW50CQD8BwQFDWZXYXZlc1dyYXBwZXICBG1pbnQJAMwIAgUMZldhdmVzQW1vdW50BQNuaWwFA25pbAMJAAACBQRtaW50BQRtaW50CQDMCAIJAQlVaW50RW50cnkCBRZmV2F2ZXNRdWFudGl0eUVudHJ5S2V5CQBkAgUOZldhdmVzUXVhbnRpdHkFDGZXYXZlc0Ftb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUKaW52b2NhdGlvbgZjYWxsZXIFG2ZXYXZlc0Ftb3VudFdpdGhvdXRBZG1pbkZlZQUNZldhdmVzQXNzZXRJZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBRhhZG1pbkZlZUNvbGxlY3RvckFkZHJlc3MFEWFkbWluRldhdmVzQW1vdW50BQ1mV2F2ZXNBc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEPcmVxdWVzdFdpdGhkcmF3AAQbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzCQEaYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MAAwkAAAIFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwUbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzBBZfYXNzZXJ0T25lUGF5bWVudEFzc2V0CQEVYXNzZXJ0T25lUGF5bWVudEFzc2V0AgUKaW52b2NhdGlvbgUNZldhdmVzQXNzZXRJZAMJAAACBRZfYXNzZXJ0T25lUGF5bWVudEFzc2V0BRZfYXNzZXJ0T25lUGF5bWVudEFzc2V0BAxmV2F2ZXNBbW91bnQICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAGYW1vdW50BAt3YXZlc0Ftb3VudAkAawMFDGZXYXZlc0Ftb3VudAUZd2l0aGRyYXdXYXZlc0JhbGFuY2VTdGF0ZQUbd2l0aGRyYXdGV2F2ZXNRdWFudGl0eVN0YXRlBAljYWxsZXJLZXkJAKUIAQgFCmludm9jYXRpb24GY2FsbGVyBBpyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0tleQkArAICBR9yZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0VudHJ5S2V5BQljYWxsZXJLZXkEGXJlcXVlc3RlZFdhdmVzV2l0aGRyYXdLZXkJAKwCAgUecmVxdWVzdGVkV2F2ZXNXaXRoZHJhd0VudHJ5S2V5BQljYWxsZXJLZXkEIHJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3Rm9yQ2FsbGVyCQELdmFsdWVPckVsc2UCCQCfCAEFGnJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3S2V5AAAEH3JlcXVlc3RlZFdhdmVzV2l0aGRyYXdGb3JDYWxsZXIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUZcmVxdWVzdGVkV2F2ZXNXaXRoZHJhd0tleQAACQDMCAIJAQlVaW50RW50cnkCBRpyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0tleQkAZAIFIHJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3Rm9yQ2FsbGVyBQxmV2F2ZXNBbW91bnQJAMwIAgkBCVVpbnRFbnRyeQIFGXJlcXVlc3RlZFdhdmVzV2l0aGRyYXdLZXkJAGQCBR9yZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3Rm9yQ2FsbGVyBQt3YXZlc0Ftb3VudAkAzAgCCQEJVWludEVudHJ5AgUjdG90YWxSZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3RW50cnlLZXkJAGQCBRt0b3RhbFJlcXVlc3RlZFdhdmVzV2l0aGRyYXcFC3dhdmVzQW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEPcHJvY2Vzc1dpdGhkcmF3AQlyZWNpcGllbnQEG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwkBGmFzc2VydExlYXNpbmdOb3RJblByb2dyZXNzAAMJAAACBRtfYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwQQcmVjaXBpZW50QWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUJcmVjaXBpZW50BBpyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0tleQkArAICBR9yZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0VudHJ5S2V5BQlyZWNpcGllbnQEGXJlcXVlc3RlZFdhdmVzV2l0aGRyYXdLZXkJAKwCAgUecmVxdWVzdGVkV2F2ZXNXaXRoZHJhd0VudHJ5S2V5BQlyZWNpcGllbnQEFnJlcXVlc3RlZFdhdmVzV2l0aGRyYXcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBRlyZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3S2V5BR9lcnJvck1lc3NhZ2VOb1JlcXVlc3RlZFdpdGhkcmF3BBdyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhdwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFGnJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3S2V5BR9lcnJvck1lc3NhZ2VOb1JlcXVlc3RlZFdpdGhkcmF3BA9fYXNzZXJBdmFpbGFibGUJAQZhc3NlcnQCCQBnAgUJYXZhaWxhYmxlBRZyZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3BSFlcnJvck1lc3NhZ2VXYXZlc0JhbGFuY2VOb3RFbm91Z2gDCQAAAgUPX2Fzc2VyQXZhaWxhYmxlBQ9fYXNzZXJBdmFpbGFibGUEBGJ1cm4JAPwHBAUNZldhdmVzV3JhcHBlcgIEYnVybgUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQ1mV2F2ZXNBc3NldElkBRdyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhdwUDbmlsAwkAAAIFBGJ1cm4FBGJ1cm4JAMwIAgkBCVVpbnRFbnRyeQIFI3RvdGFsUmVxdWVzdGVkV2F2ZXNXaXRoZHJhd0VudHJ5S2V5CQBlAgUbdG90YWxSZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3BRZyZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3CQDMCAIJAQtEZWxldGVFbnRyeQEFGnJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3S2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFGXJlcXVlc3RlZFdhdmVzV2l0aGRyYXdLZXkJAMwIAgkBCVVpbnRFbnRyeQIFFmZXYXZlc1F1YW50aXR5RW50cnlLZXkJAGUCBQ5mV2F2ZXNRdWFudGl0eQUXcmVxdWVzdGVkRldhdmVzV2l0aGRyYXcJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUQcmVjaXBpZW50QWRkcmVzcwUWcmVxdWVzdGVkV2F2ZXNXaXRoZHJhdwUEdW5pdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BDnJldm9rZVdpdGhkcmF3AAQbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzCQEaYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MAAwkAAAIFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwUbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzBAlyZWNpcGllbnQJAKUIAQgFCmludm9jYXRpb24GY2FsbGVyBBpyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0tleQkArAICBR9yZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhd0VudHJ5S2V5BQlyZWNpcGllbnQEGXJlcXVlc3RlZFdhdmVzV2l0aGRyYXdLZXkJAKwCAgUecmVxdWVzdGVkV2F2ZXNXaXRoZHJhd0VudHJ5S2V5BQlyZWNpcGllbnQEFnJlcXVlc3RlZFdhdmVzV2l0aGRyYXcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBRlyZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3S2V5BR9lcnJvck1lc3NhZ2VOb1JlcXVlc3RlZFdpdGhkcmF3BBdyZXF1ZXN0ZWRGV2F2ZXNXaXRoZHJhdwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFGnJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3S2V5BR9lcnJvck1lc3NhZ2VOb1JlcXVlc3RlZFdpdGhkcmF3CQDMCAIJAQlVaW50RW50cnkCBSN0b3RhbFJlcXVlc3RlZFdhdmVzV2l0aGRyYXdFbnRyeUtleQkAZQIFG3RvdGFsUmVxdWVzdGVkV2F2ZXNXaXRoZHJhdwUWcmVxdWVzdGVkV2F2ZXNXaXRoZHJhdwkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUKaW52b2NhdGlvbgZjYWxsZXIFF3JlcXVlc3RlZEZXYXZlc1dpdGhkcmF3BQ1mV2F2ZXNBc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEFGnJlcXVlc3RlZEZXYXZlc1dpdGhkcmF3S2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFGXJlcXVlc3RlZFdhdmVzV2l0aGRyYXdLZXkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQR2b3RlAgl2YWxpZGF0b3IIaW50ZXJ2YWwEG19hc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwkBGmFzc2VydENvbnRyYWN0QWN0aXZlU3RhdHVzAAMJAAACBRtfYXNzZXJ0Q29udHJhY3RBY3RpdmVTdGF0dXMFG19hc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwQbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzCQEaYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MAAwkAAAIFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwUbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzBBB2YWxpZGF0b3JBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IEFV9hc3NldFZhbGlkYXRvclN0YXR1cwkBHmFzc2VydE5vdEtpY2tlZFZhbGlkYXRvclN0YXR1cwEFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUVX2Fzc2V0VmFsaWRhdG9yU3RhdHVzBRVfYXNzZXRWYWxpZGF0b3JTdGF0dXMEFl9hc3NlcnRPbmVQYXltZW50QXNzZXQJARVhc3NlcnRPbmVQYXltZW50QXNzZXQCBQppbnZvY2F0aW9uBQtmbG93QXNzZXRJZAMJAAACBRZfYXNzZXJ0T25lUGF5bWVudEFzc2V0BRZfYXNzZXJ0T25lUGF5bWVudEFzc2V0BBRfYXNzZXJ0VmFsaWRJbnRlcnZhbAkBBmFzc2VydAIDCQBnAgUIaW50ZXJ2YWwFD21pblZvdGVJbnRlcnZhbAkAZwIFD21heFZvdGVJbnRlcnZhbAUIaW50ZXJ2YWwHBRtlcnJvck1lc3NhZ2VJbnZhbGlkSW50ZXJ2YWwDCQAAAgUUX2Fzc2VydFZhbGlkSW50ZXJ2YWwFFF9hc3NlcnRWYWxpZEludGVydmFsBAt1bmxvY2tCbG9jawkAZAIIBQlsYXN0QmxvY2sGaGVpZ2h0BQhpbnRlcnZhbAQLbmV3VXNlckxvY2sICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAGYW1vdW50BAxuZXdVc2VyVm90ZXMJAGsDBQtuZXdVc2VyTG9jawkBBHNxcnQEBQhpbnRlcnZhbAAAAAAFBUZMT09SBR5jeWNsZUR1cmF0aW9uSW5CbG9ja3NTcXJ0Rmxvb3IEE2NhbGxlclVubG9ja0tleVBhcnQJAKwCAgkArAICCQClCAEIBQppbnZvY2F0aW9uBmNhbGxlcgIBfAkApAMBBQt1bmxvY2tCbG9jawQOdW5sb2NrQmxvY2tLZXkJAKwCAgUTdW5sb2NrQmxvY2tFbnRyeUtleQUTY2FsbGVyVW5sb2NrS2V5UGFydAQWdG90YWxWYWxpZGF0b3JWb3Rlc0tleQkArAICBQ12b3Rlc0VudHJ5S2V5BQl2YWxpZGF0b3IEC3VzZXJWb3RlS2V5CQCsAgIFEHVzZXJWb3RlRW50cnlLZXkFE2NhbGxlclVubG9ja0tleVBhcnQEC3VzZXJMb2NrS2V5CQCsAgIFEHVzZXJMb2NrRW50cnlLZXkFE2NhbGxlclVubG9ja0tleVBhcnQECHVzZXJMb2NrCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQt1c2VyVm90ZUtleQAABQtuZXdVc2VyTG9jawQJdXNlclZvdGVzCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQt1c2VyTG9ja0tleQAABQxuZXdVc2VyVm90ZXMEE3RvdGFsVmFsaWRhdG9yVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUWdG90YWxWYWxpZGF0b3JWb3Rlc0tleQAABBdpZ25vcmVWYWxpZGF0b3JzQ2hhbmdlcwMJAAACCQEZZ2V0UmVnaXN0cmF0aW9uQ3ljbGVWYWx1ZQEFEHZhbGlkYXRvckFkZHJlc3MFDGN1cnJlbnRDeWNsZQkAzAgCCQEJVWludEVudHJ5AgUbY3VycmVudEN5Y2xlSWdub3JlZFZvdGVzS2V5CQBkAgUYY3VycmVudEN5Y2xlSWdub3JlZFZvdGVzBQxuZXdVc2VyVm90ZXMFA25pbAUDbmlsCQDOCAIFF2lnbm9yZVZhbGlkYXRvcnNDaGFuZ2VzCQDMCAIJAQlVaW50RW50cnkCBQt1c2VyVm90ZUtleQUJdXNlclZvdGVzCQDMCAIJAQlVaW50RW50cnkCBQt1c2VyTG9ja0tleQUIdXNlckxvY2sJAMwIAgkBC0JpbmFyeUVudHJ5AgUOdW5sb2NrQmxvY2tLZXkIBRB2YWxpZGF0b3JBZGRyZXNzBWJ5dGVzCQDMCAIJAQlVaW50RW50cnkCBRZ0b3RhbFZhbGlkYXRvclZvdGVzS2V5CQBkAgUTdG90YWxWYWxpZGF0b3JWb3RlcwUMbmV3VXNlclZvdGVzCQDMCAIJAQlVaW50RW50cnkCBRJ0b3RhbFZvdGVzRW50cnlLZXkJAGQCBQp0b3RhbFZvdGVzBQxuZXdVc2VyVm90ZXMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgppbnZvY2F0aW9uAQZyZWRlZW0BC3VubG9ja0Jsb2NrBBtfYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MJARphc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwADCQAAAgUbX2Fzc2VydExlYXNpbmdOb3RJblByb2dyZXNzBRtfYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MEE2NhbGxlclVubG9ja0tleVBhcnQJAKwCAgkArAICCQClCAEIBQppbnZvY2F0aW9uBmNhbGxlcgIBfAkApAMBBQt1bmxvY2tCbG9jawQOdW5sb2NrQmxvY2tLZXkJAKwCAgUTdW5sb2NrQmxvY2tFbnRyeUtleQUTY2FsbGVyVW5sb2NrS2V5UGFydAQLdXNlclZvdGVLZXkJAKwCAgUQdXNlclZvdGVFbnRyeUtleQUTY2FsbGVyVW5sb2NrS2V5UGFydAQLdXNlckxvY2tLZXkJAKwCAgUQdXNlckxvY2tFbnRyeUtleQUTY2FsbGVyVW5sb2NrS2V5UGFydAQQdmFsaWRhdG9yQWRkcmVzcwkBB0FkZHJlc3MBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKEIAQUOdW5sb2NrQmxvY2tLZXkFF2Vycm9yTWVzc2FnZVVua25vd25Mb2NrBBF2YWxpZGF0b3JWb3Rlc0tleQkArAICBQ12b3Rlc0VudHJ5S2V5CQDYBAEIBRB2YWxpZGF0b3JBZGRyZXNzBWJ5dGVzBBBfYXNzZXJ0Q2FuVW5sb2NrCQEPYXNzZXJ0Q2FuVW5sb2NrAgULdW5sb2NrQmxvY2sFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUQX2Fzc2VydENhblVubG9jawUQX2Fzc2VydENhblVubG9jawQJdXNlclZvdGVzCQERQGV4dHJOYXRpdmUoMTA1NSkBBQt1c2VyVm90ZUtleQQIdXNlckxvY2sJARFAZXh0ck5hdGl2ZSgxMDU1KQEFC3VzZXJMb2NrS2V5BAZzdGF0dXMJAQt2YWx1ZU9yRWxzZQIJARJnZXRWYWxpZGF0b3JTdGF0dXMBBRB2YWxpZGF0b3JBZGRyZXNzBwQMdm90ZXNDaGFuZ2VzAwUGc3RhdHVzCQDMCAIJAQlVaW50RW50cnkCBRF2YWxpZGF0b3JWb3Rlc0tleQkAZQIJARFAZXh0ck5hdGl2ZSgxMDU1KQEFEXZhbGlkYXRvclZvdGVzS2V5BQl1c2VyVm90ZXMJAMwIAgkBCVVpbnRFbnRyeQIFEnRvdGFsVm90ZXNFbnRyeUtleQkAZQIFCnRvdGFsVm90ZXMFCXVzZXJWb3RlcwUDbmlsBQNuaWwJAM4IAgUMdm90ZXNDaGFuZ2VzCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQppbnZvY2F0aW9uBmNhbGxlcgUIdXNlckxvY2sFC2Zsb3dBc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEFC3VzZXJWb3RlS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFDnVubG9ja0Jsb2NrS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFC3VzZXJMb2NrS2V5BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEHbGVhc2luZwEJdmFsaWRhdG9yBBB2YWxpZGF0b3JBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IEG19hc3NlcnRWYWxpZGF0b3JJc05vdEtpY2tlZAkBHmFzc2VydE5vdEtpY2tlZFZhbGlkYXRvclN0YXR1cwEFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUbX2Fzc2VydFZhbGlkYXRvcklzTm90S2lja2VkBRtfYXNzZXJ0VmFsaWRhdG9ySXNOb3RLaWNrZWQEG19hc3NlcnRWYWxpZGF0b3JJc0xlYXNlYWJsZQkBGmFzc2VydFZhbGlkYXRvcklzTGVhc2VhYmxlAQUQdmFsaWRhdG9yQWRkcmVzcwMJAAACBRtfYXNzZXJ0VmFsaWRhdG9ySXNMZWFzZWFibGUFG19hc3NlcnRWYWxpZGF0b3JJc0xlYXNlYWJsZQQTdmFsaWRhdG9yTGVhc2VJZEtleQkArAICBQ9sZWFzZUlkRW50cnlLZXkFCXZhbGlkYXRvcgQVbGF0ZXN0TGVhc2luZ0N5Y2xlS2V5CQCsAgIFI2xhdGVzdFZhbGlkYXRvckxlYXNpbmdDeWNsZUVudHJ5S2V5BQl2YWxpZGF0b3IEEnZhbGlkYXRvckxlYXNlc0tleQkArAICBRd2YWxpZGF0b3JMZWFzZXNFbnRyeUtleQUJdmFsaWRhdG9yBA9jdXJyZW50Q3ljbGVLZXkJAKQDAQUMY3VycmVudEN5Y2xlBB5jdXJyZW50UHJvY2Vzc2VkTGVhc2VzRW50cnlLZXkJAKwCAgUXcHJvY2Vzc2VkTGVhc2VzRW50cnlLZXkFD2N1cnJlbnRDeWNsZUtleQQfY3VycmVudExlYXNpbmdQb29sVmFsdWVFbnRyeUtleQkArAICBRhsZWFzaW5nUG9vbFZhbHVlRW50cnlLZXkFD2N1cnJlbnRDeWNsZUtleQQiaXNDdXJyZW50TGVhc2luZ0luUHJvZ3Jlc3NFbnRyeUtleQkArAICBRtpc0xlYXNpbmdJblByb2dyZXNzRW50cnlLZXkFD2N1cnJlbnRDeWNsZUtleQQOdmFsaWRhdG9yVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkArAICBQ12b3Rlc0VudHJ5S2V5BQl2YWxpZGF0b3IAAAQSY3VycmVudExlYXNlQW1vdW50CQELdmFsdWVPckVsc2UCCQCfCAEFEnZhbGlkYXRvckxlYXNlc0tleQAABAtjYW5jZWxMZWFzZQkBGmdldENhbmNlbExlYXNlRm9yVmFsaWRhdG9yAQUQdmFsaWRhdG9yQWRkcmVzcwQTX2NoZWNrTGVhc2luZ1N0YXR1cwkBBmFzc2VydAIJAQIhPQIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUVbGF0ZXN0TGVhc2luZ0N5Y2xlS2V5AP///////////wEFDGN1cnJlbnRDeWNsZQUZZXJyb3JNZXNzYWdlQWxyZWFkeUxlYXNlZAMJAAACBRNfY2hlY2tMZWFzaW5nU3RhdHVzBRNfY2hlY2tMZWFzaW5nU3RhdHVzBBdwcm9jY2Vzc2VkTGVhc2VzRW50cmllcwkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUeY3VycmVudFByb2Nlc3NlZExlYXNlc0VudHJ5S2V5AAAAAQQQbGVhc2luZ1Bvb2xWYWx1ZQkBC3ZhbHVlT3JFbHNlAgkAnwgBBR9jdXJyZW50TGVhc2luZ1Bvb2xWYWx1ZUVudHJ5S2V5CAkA7wcBBQR0aGlzB3JlZ3VsYXIEE2FmdGVyTGVhc2luZ1Byb2Nlc3MDCQBmAgUeYWN0aXZlVmFsaWRhdG9yc1dpdGhvdXRJZ25vcmVkBRdwcm9jY2Vzc2VkTGVhc2VzRW50cmllcwkAzAgCCQEMQm9vbGVhbkVudHJ5AgUiaXNDdXJyZW50TGVhc2luZ0luUHJvZ3Jlc3NFbnRyeUtleQYJAMwIAgkBCVVpbnRFbnRyeQIFHmN1cnJlbnRQcm9jZXNzZWRMZWFzZXNFbnRyeUtleQUXcHJvY2Nlc3NlZExlYXNlc0VudHJpZXMJAMwIAgkBCVVpbnRFbnRyeQIFH2N1cnJlbnRMZWFzaW5nUG9vbFZhbHVlRW50cnlLZXkFEGxlYXNpbmdQb29sVmFsdWUFA25pbAkAzAgCCQEJVWludEVudHJ5AgUhd2l0aGRyYXdXYXZlc0JhbGFuY2VTdGF0ZUVudHJ5S2V5BRBsZWFzaW5nUG9vbFZhbHVlCQDMCAIJAQlVaW50RW50cnkCBSN3aXRoZHJhd0ZXYXZlc1F1YW50aXR5U3RhdGVFbnRyeUtleQUOZldhdmVzUXVhbnRpdHkJAMwIAgkBDEludGVnZXJFbnRyeQIFGmxhdGVzdExlYXNpbmdDeWNsZUVudHJ5S2V5BQxjdXJyZW50Q3ljbGUJAMwIAgkBC0RlbGV0ZUVudHJ5AQUiaXNDdXJyZW50TGVhc2luZ0luUHJvZ3Jlc3NFbnRyeUtleQkAzAgCCQELRGVsZXRlRW50cnkBBR5jdXJyZW50UHJvY2Vzc2VkTGVhc2VzRW50cnlLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUfY3VycmVudExlYXNpbmdQb29sVmFsdWVFbnRyeUtleQkAzAgCCQELRGVsZXRlRW50cnkBBSBjdXJyZW50Q3ljbGVJZ25vcmVkVmFsaWRhdG9yc0tleQkAzAgCCQELRGVsZXRlRW50cnkBBRtjdXJyZW50Q3ljbGVJZ25vcmVkVm90ZXNLZXkFA25pbAQSZGVsZXRlTGVhc2VFbnRyaWVzAwkBCWlzRGVmaW5lZAEJAJ8IAQUSdmFsaWRhdG9yTGVhc2VzS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFEnZhbGlkYXRvckxlYXNlc0tleQkAzAgCCQELRGVsZXRlRW50cnkBBRN2YWxpZGF0b3JMZWFzZUlkS2V5BQNuaWwFA25pbAQRdGFyZ2V0TGVhc2VBbW91bnQJAGsDCQBlAgUQbGVhc2luZ1Bvb2xWYWx1ZQUbdG90YWxSZXF1ZXN0ZWRXYXZlc1dpdGhkcmF3BQ52YWxpZGF0b3JWb3RlcwUddG90YWxWb3Rlc1dpdGhvdXRJZ25vcmVkVm90ZXMDAwkBASEBBQ5jb250cmFjdFN0YXR1cwYJAAACBR10b3RhbFZvdGVzV2l0aG91dElnbm9yZWRWb3RlcwAACQDOCAIJAM4IAgULY2FuY2VsTGVhc2UFEmRlbGV0ZUxlYXNlRW50cmllcwUTYWZ0ZXJMZWFzaW5nUHJvY2VzcwMJAQIhPQIFEXRhcmdldExlYXNlQW1vdW50BRJjdXJyZW50TGVhc2VBbW91bnQEBWxlYXNlCQDECAIFEHZhbGlkYXRvckFkZHJlc3MFEXRhcmdldExlYXNlQW1vdW50BA5sZWFzaW5nUHJvY2VzcwMJAAACBRF0YXJnZXRMZWFzZUFtb3VudAAABRJkZWxldGVMZWFzZUVudHJpZXMJAMwIAgUFbGVhc2UJAMwIAgkBC0JpbmFyeUVudHJ5AgUTdmFsaWRhdG9yTGVhc2VJZEtleQkAuQgBBQVsZWFzZQkAzAgCCQEJVWludEVudHJ5AgUSdmFsaWRhdG9yTGVhc2VzS2V5BRF0YXJnZXRMZWFzZUFtb3VudAUDbmlsCQDNCAIJAM4IAgkAzggCBQtjYW5jZWxMZWFzZQUObGVhc2luZ1Byb2Nlc3MFE2FmdGVyTGVhc2luZ1Byb2Nlc3MJAQlVaW50RW50cnkCBRVsYXRlc3RMZWFzaW5nQ3ljbGVLZXkFDGN1cnJlbnRDeWNsZQkAzQgCBRNhZnRlckxlYXNpbmdQcm9jZXNzCQEJVWludEVudHJ5AgUVbGF0ZXN0TGVhc2luZ0N5Y2xlS2V5BQxjdXJyZW50Q3ljbGUJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4KaW52b2NhdGlvbgEPZW1lcmdlbmN5Vm90aW5nAQl2YWxpZGF0b3IEG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwkBGmFzc2VydExlYXNpbmdOb3RJblByb2dyZXNzAAMJAAACBRtfYXNzZXJ0TGVhc2luZ05vdEluUHJvZ3Jlc3MFG19hc3NlcnRMZWFzaW5nTm90SW5Qcm9ncmVzcwQbX2Fzc2VydENvbnRyYWN0QWN0aXZlU3RhdHVzCQEaYXNzZXJ0Q29udHJhY3RBY3RpdmVTdGF0dXMAAwkAAAIFG19hc3NlcnRDb250cmFjdEFjdGl2ZVN0YXR1cwUbX2Fzc2VydENvbnRyYWN0QWN0aXZlU3RhdHVzBBB2YWxpZGF0b3JBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQl2YWxpZGF0b3IEFV9hc3NldFZhbGlkYXRvclN0YXR1cwkBHmFzc2VydE5vdEtpY2tlZFZhbGlkYXRvclN0YXR1cwEFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUVX2Fzc2V0VmFsaWRhdG9yU3RhdHVzBRVfYXNzZXRWYWxpZGF0b3JTdGF0dXMEFl9hc3NlcnRPbmVQYXltZW50QXNzZXQJARVhc3NlcnRPbmVQYXltZW50QXNzZXQCBQppbnZvY2F0aW9uBQ1mV2F2ZXNBc3NldElkAwkAAAIFFl9hc3NlcnRPbmVQYXltZW50QXNzZXQFFl9hc3NlcnRPbmVQYXltZW50QXNzZXQECnZvdGVBbW91bnQICQCRAwIIBQppbnZvY2F0aW9uCHBheW1lbnRzAAAGYW1vdW50BAljYWxsZXJLZXkJAKUIAQgFCmludm9jYXRpb24GY2FsbGVyBAt1bmxvY2tCbG9jawkAZAIIBQlsYXN0QmxvY2sGaGVpZ2h0BRNlbWVyZ2VuY3lWb3RpbmdMb2NrBBFlbWVyZ2VuY3lWb3Rlc0tleQkArAICBRZlbWVyZ2VuY3lWb3Rlc0VudHJ5S2V5BQl2YWxpZGF0b3IEFWVtZXJnZW5jeVVzZXJWb3Rlc0tleQkArAICCQCsAgIJAKwCAgUaZW1lcmdlbmN5VXNlclZvdGVzRW50cnlLZXkFCWNhbGxlcktleQIBfAUJdmFsaWRhdG9yBBF2YWxpZGF0b3JWb3Rlc0tleQkArAICBQ12b3Rlc0VudHJ5S2V5BQl2YWxpZGF0b3IEE3ZhbGlkYXRvckxlYXNlSWRLZXkJAKwCAgUPbGVhc2VJZEVudHJ5S2V5BQl2YWxpZGF0b3IEFGVtZXJnZW5jeVVzZXJMb2NrS2V5CQCsAgIJAKwCAgkArAICBRllbWVyZ2VuY3lVc2VyTG9ja0VudHJ5S2V5BQljYWxsZXJLZXkCAXwJAKQDAQULdW5sb2NrQmxvY2sEDmVtZXJnZW5jeVZvdGVzCQBkAgUKdm90ZUFtb3VudAkBC3ZhbHVlT3JFbHNlAgkAnwgBBRFlbWVyZ2VuY3lWb3Rlc0tleQAABA5pc1ZhbGlkYXRvckJhZAkAZgIJAGkCCQBoAgUOZW1lcmdlbmN5Vm90ZXMAZAUOZldhdmVzUXVhbnRpdHkFGGVtZXJnZW5jeVZvdGluZ1RocmVzaG9sZAQKcHVuaXNobWVudAMFDmlzVmFsaWRhdG9yQmFkBAZjYW5jZWwJARpnZXRDYW5jZWxMZWFzZUZvclZhbGlkYXRvcgEFEHZhbGlkYXRvckFkZHJlc3MEE3RvdGFsVmFsaWRhdG9yVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQURdmFsaWRhdG9yVm90ZXNLZXkAAAQNY3VycmVudFN0YXR1cwkBF2dldFZhbGlkYXRvclN0YXR1c1ZhbHVlAQUQdmFsaWRhdG9yQWRkcmVzcwQabGVhc2VhYmxlVmFsaWRhdG9yc0NoYW5nZXMDBQ1jdXJyZW50U3RhdHVzCQDMCAIJAQlVaW50RW50cnkCBRhhY3RpdmVWYWxpZGF0b3JzRW50cnlLZXkJAGUCBRBhY3RpdmVWYWxpZGF0b3JzAAEFA25pbAUDbmlsBBN2YWxpZGF0b3JJZHNDaGFuZ2VzCQEWZ2V0VmFsaWRhdG9ySWRzQ2hhbmdlcwEFEHZhbGlkYXRvckFkZHJlc3MJAM4IAgkAzggCCQDOCAIFE3ZhbGlkYXRvcklkc0NoYW5nZXMFGmxlYXNlYWJsZVZhbGlkYXRvcnNDaGFuZ2VzBQZjYW5jZWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFDWZsb3dBc3NldEluZm8GaXNzdWVyBRJyZXF1aXJlZEZsb3dBbW91bnQFC2Zsb3dBc3NldElkCQDMCAIJAQlVaW50RW50cnkCBRJ0b3RhbFZvdGVzRW50cnlLZXkJAGUCBQp0b3RhbFZvdGVzBRN0b3RhbFZhbGlkYXRvclZvdGVzCQDMCAIJAQxCb29sZWFuRW50cnkCCQCsAgIFF3ZhbGlkYXRvclN0YXR1c0VudHJ5S2V5BQl2YWxpZGF0b3IHCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUXdmFsaWRhdG9yTGVhc2VzRW50cnlLZXkFCXZhbGlkYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBBRN2YWxpZGF0b3JMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUjbGF0ZXN0VmFsaWRhdG9yTGVhc2luZ0N5Y2xlRW50cnlLZXkFCXZhbGlkYXRvcgUDbmlsBQNuaWwJAM4IAgUKcHVuaXNobWVudAkAzAgCCQELQmluYXJ5RW50cnkCBRRlbWVyZ2VuY3lVc2VyTG9ja0tleQgFEHZhbGlkYXRvckFkZHJlc3MFYnl0ZXMJAMwIAgkBCVVpbnRFbnRyeQIFEWVtZXJnZW5jeVZvdGVzS2V5BQ5lbWVyZ2VuY3lWb3RlcwkAzAgCCQEJVWludEVudHJ5AgUVZW1lcmdlbmN5VXNlclZvdGVzS2V5CQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBRVlbWVyZ2VuY3lVc2VyVm90ZXNLZXkAAAUKdm90ZUFtb3VudAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCmludm9jYXRpb24BE3JlZGVlbUVtZXJnZW5jeVZvdGUBC3VubG9ja0Jsb2NrBAljYWxsZXJLZXkJAKUIAQgFCmludm9jYXRpb24GY2FsbGVyBBRlbWVyZ2VuY3lVc2VyTG9ja0tleQkArAICCQCsAgIJAKwCAgUZZW1lcmdlbmN5VXNlckxvY2tFbnRyeUtleQUJY2FsbGVyS2V5AgF8CQCkAwEFC3VubG9ja0Jsb2NrBBB2YWxpZGF0b3JBZGRyZXNzCQEHQWRkcmVzcwEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoQgBBRRlbWVyZ2VuY3lVc2VyTG9ja0tleQUXZXJyb3JNZXNzYWdlVW5rbm93bkxvY2sECXZhbGlkYXRvcgkApQgBBRB2YWxpZGF0b3JBZGRyZXNzBBBfYXNzZXJ0Q2FuVW5sb2NrCQEPYXNzZXJ0Q2FuVW5sb2NrAgULdW5sb2NrQmxvY2sFEHZhbGlkYXRvckFkZHJlc3MDCQAAAgUQX2Fzc2VydENhblVubG9jawUQX2Fzc2VydENhblVubG9jawQRZW1lcmdlbmN5Vm90ZXNLZXkJAKwCAgUWZW1lcmdlbmN5Vm90ZXNFbnRyeUtleQUJdmFsaWRhdG9yBBVlbWVyZ2VuY3lVc2VyVm90ZXNLZXkJAKwCAgkArAICCQCsAgIFGmVtZXJnZW5jeVVzZXJWb3Rlc0VudHJ5S2V5BQljYWxsZXJLZXkCAXwFCXZhbGlkYXRvcgQSZW1lcmdlbmN5VXNlclZvdGVzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQUVZW1lcmdlbmN5VXNlclZvdGVzS2V5BRxlcnJvck1lc3NhZ2VOb0VtZXJnZW5jeVZvdGVzBA5lbWVyZ2VuY3lWb3RlcwkAZQIJARFAZXh0ck5hdGl2ZSgxMDU1KQEFEWVtZXJnZW5jeVZvdGVzS2V5BRJlbWVyZ2VuY3lVc2VyVm90ZXMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFCmludm9jYXRpb24GY2FsbGVyBRJlbWVyZ2VuY3lVc2VyVm90ZXMFDWZXYXZlc0Fzc2V0SWQJAMwIAgkBCVVpbnRFbnRyeQIFEWVtZXJnZW5jeVZvdGVzS2V5BQ5lbWVyZ2VuY3lWb3RlcwkAzAgCCQELRGVsZXRlRW50cnkBBRVlbWVyZ2VuY3lVc2VyVm90ZXNLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUUZW1lcmdlbmN5VXNlckxvY2tLZXkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAEByRtYXRjaDAFAnR4AwkAAQIFByRtYXRjaDACFFNldFNjcmlwdFRyYW5zYWN0aW9uBAN0dHgFByRtYXRjaDAJAQEhAQkBCWlzRGVmaW5lZAEJAJ8IAQUSc3RhcnRCbG9ja0VudHJ5S2V5AwkAAQIFByRtYXRjaDACF0ludm9rZVNjcmlwdFRyYW5zYWN0aW9uBAN0dHgFByRtYXRjaDADAwkAAAIIBQN0dHgEZEFwcAUEdGhpcwkBD2NvbnRhaW5zRWxlbWVudAIFDWFkbWluTXVsdGlTaWcIBQN0dHgIZnVuY3Rpb24HBARzaWdBCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABQtmbG93TGVhc2VQawQEc2lnQgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAQUFYWRtaW4DBQRzaWdBBQRzaWdCBwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tlefAvGNA=", "height": 3584279, "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 flowLeasePk = base58'AH5C5BuUDF6hQVR5ncwg9cZPGVuyJiFfjnxSYgMJQuGC' | |
5 | + | ||
6 | + | let BP = 10000 | |
7 | + | ||
8 | + | let requiredFlowAmount = 10000000000 | |
9 | + | ||
10 | + | let cycleDurationInBlocks = 1000 | |
11 | + | ||
12 | + | let cycleDurationInBlocksSqrtFloor = 3 | |
13 | + | ||
14 | + | let minVoteCycleInterval = 1 | |
15 | + | ||
16 | + | let minVoteInterval = (cycleDurationInBlocks * minVoteCycleInterval) | |
17 | + | ||
18 | + | let maxVoteCycleInterval = 530 | |
19 | + | ||
20 | + | let maxVoteInterval = (cycleDurationInBlocks * maxVoteCycleInterval) | |
21 | + | ||
22 | + | let emergencyVotingThreshold = 10 | |
23 | + | ||
24 | + | let emergencyVotingLockInCycles = 10 | |
25 | + | ||
26 | + | let emergencyVotingLock = (emergencyVotingLockInCycles * cycleDurationInBlocks) | |
27 | + | ||
28 | + | let adminMultiSig = ["setStopManager", "setFeeCollector", "setAdmin", "setAdminFeeBP", "swapRewardTokens"] | |
29 | + | ||
30 | + | let validatorStatusEntryKey = "validatorStatus:" | |
31 | + | ||
32 | + | let activeValidatorsEntryKey = "activeValidators" | |
33 | + | ||
34 | + | let adminFeeBPEntryKey = "adminFeeBP" | |
35 | + | ||
36 | + | let leasingPoolValueEntryKey = "leasingPoolValue:" | |
37 | + | ||
38 | + | let cycleDurationInBlocksEntryKey = "cycleDurationInBlocks" | |
39 | + | ||
40 | + | let emergencyUserVotesEntryKey = "emergencyUserVotes:" | |
41 | + | ||
42 | + | let emergencyVotesEntryKey = "emergencyVotes:" | |
43 | + | ||
44 | + | let emergencyVotingThresholdEntryKey = "emergencyVotingThreshold" | |
45 | + | ||
46 | + | let emergencyUserLockEntryKey = "emergencyUserLock:" | |
47 | + | ||
48 | + | let isLeasingInProgressEntryKey = "isLeasingInProgress:" | |
49 | + | ||
50 | + | let latestLeasingCycleEntryKey = "latestLeasingCycle" | |
51 | + | ||
52 | + | let latestValidatorLeasingCycleEntryKey = "latestLeasingCycle:" | |
53 | + | ||
54 | + | let registrationCycleEntryKey = "registrationCycle:" | |
55 | + | ||
56 | + | let leaseIdEntryKey = "leaseId:" | |
57 | + | ||
58 | + | let processedLeasesEntryKey = "processedLeases:" | |
59 | + | ||
60 | + | let requestedFWavesWithdrawEntryKey = "requestedFWavesWithdraw:" | |
61 | + | ||
62 | + | let requestedWavesWithdrawEntryKey = "requestedWavesWithdraw:" | |
63 | + | ||
64 | + | let requiredFlowAmountEntryKey = "requiredFlowAmount" | |
65 | + | ||
66 | + | let startBlockEntryKey = "startBlock" | |
67 | + | ||
68 | + | let contractStatusEntryKey = "contractStatus" | |
69 | + | ||
70 | + | let stopManagerEntryKey = "stopManager" | |
71 | + | ||
72 | + | let totalRequestedWavesWithdrawEntryKey = "totalRequestedWavesWithdraw" | |
73 | + | ||
74 | + | let totalVotesEntryKey = "totalVotes" | |
75 | + | ||
76 | + | let unlockBlockEntryKey = "unlockBlock:" | |
77 | + | ||
78 | + | let userLockEntryKey = "userLock:" | |
79 | + | ||
80 | + | let userVoteEntryKey = "userVote:" | |
81 | + | ||
82 | + | let validatorMetaEntryKey = "validatorMeta:" | |
83 | + | ||
84 | + | let validatorAddressEntryKey = "validatorAddress:" | |
85 | + | ||
86 | + | let validatorIdEntryKey = "validatorId:" | |
87 | + | ||
88 | + | let validatorLeasesEntryKey = "validatorLeases:" | |
89 | + | ||
90 | + | let votesEntryKey = "votes:" | |
91 | + | ||
92 | + | let withdrawFWavesQuantityStateEntryKey = "withdrawFWavesQuantityState" | |
93 | + | ||
94 | + | let withdrawWavesBalanceStateEntryKey = "withdrawWavesBalanceState" | |
95 | + | ||
96 | + | let flowAssetIdEntryKey = "flowAssetId" | |
97 | + | ||
98 | + | let fWavesAssetIdEntryKey = "fWavesAssetId" | |
99 | + | ||
100 | + | let fWavesWrapperEntryKey = "fWavesWrapper" | |
101 | + | ||
102 | + | let adminFeeCollectorEntryKey = "adminFeeCollector" | |
103 | + | ||
104 | + | let ignoredVotesEntryKey = "ignoreVotes:" | |
105 | + | ||
106 | + | let ignoredValidatorsEntryKey = "ignoredValidators:" | |
107 | + | ||
108 | + | let adminPKEntryKey = "adminPK" | |
109 | + | ||
110 | + | let fWavesQuantityEntryKey = "fWavesQuantity" | |
111 | + | ||
112 | + | let puzzleSwapEntryKey = "puzzleSwap" | |
113 | + | ||
114 | + | let errorMessageUnreachable = "Unreachable" | |
115 | + | ||
116 | + | let errorMessageAlreadyInitialized = "Already initialized" | |
117 | + | ||
118 | + | let errorMessageAlreadyLeased = "Already leased" | |
119 | + | ||
120 | + | let errorMessageAlreadyRegistered = "Already registered" | |
121 | + | ||
122 | + | let errorMessageContractNotActive = "Contract is not active" | |
123 | + | ||
124 | + | let errorMessageInvalidInterval = "Invalid interval" | |
125 | + | ||
126 | + | let errorMessageInvalidFlowAmount = "Invalid Flow amount" | |
127 | + | ||
128 | + | let errorMessageLeasingInProgress = "Leasing in progress" | |
129 | + | ||
130 | + | let errorMessageNoEmergencyVotes = "No emergency votes for user" | |
131 | + | ||
132 | + | let errorMessageNoRequestedWithdraw = "No requested withdraw" | |
133 | + | ||
134 | + | let errorMessageNotOnePayment = "Not one payment" | |
135 | + | ||
136 | + | let errorMessageTooEarly = "Too early" | |
137 | + | ||
138 | + | let errorMessageUnauthorized = "Unauthorized" | |
139 | + | ||
140 | + | let errorMessageUnexpectedAssetId = "Unexpected asset id" | |
141 | + | ||
142 | + | let errorMessageUnknownLock = "Unknown lock" | |
143 | + | ||
144 | + | let errorMessageUnknownValidator = "Unknown validator" | |
145 | + | ||
146 | + | let errorMessageValidatorNotReadyToLease = "Validator is not ready to lease" | |
147 | + | ||
148 | + | let errorMessageWavesBalanceNotEnough = "Not enough WAVES. Please try later" | |
149 | + | ||
150 | + | let errorMessageValidatorWasKicked = "Validator was kicked" | |
151 | + | ||
152 | + | let errorMessageInvalidAdminFeeBP = "Invalid adminFeeBP" | |
153 | + | ||
154 | + | let errorMessageInvalidUint = "Invalid Uint" | |
155 | + | ||
156 | + | let available = wavesBalance(this).available | |
157 | + | ||
158 | + | let flowAssetId = getBinaryValue(flowAssetIdEntryKey) | |
159 | + | ||
160 | + | let fWavesAssetId = getBinaryValue(fWavesAssetIdEntryKey) | |
161 | + | ||
162 | + | let fWavesWrapper = Address(getBinaryValue(fWavesWrapperEntryKey)) | |
163 | + | ||
164 | + | let flowAssetInfo = valueOrErrorMessage(assetInfo(flowAssetId), errorMessageUnreachable) | |
165 | + | ||
166 | + | let fWavesQuantity = getIntegerValue(fWavesQuantityEntryKey) | |
167 | + | ||
168 | + | let currentCycle = ((lastBlock.height - getIntegerValue(startBlockEntryKey)) / cycleDurationInBlocks) | |
169 | + | ||
170 | + | let withdrawWavesBalanceState = valueOrElse(getInteger(withdrawWavesBalanceStateEntryKey), wavesBalance(this).regular) | |
171 | + | ||
172 | + | let withdrawFWavesQuantityState = valueOrElse(getInteger(withdrawFWavesQuantityStateEntryKey), fWavesQuantity) | |
173 | + | ||
174 | + | let currentCycleIgnoredVotesKey = (ignoredVotesEntryKey + toString(currentCycle)) | |
175 | + | ||
176 | + | let currentCycleIgnoredValidatorsKey = (ignoredValidatorsEntryKey + toString(currentCycle)) | |
177 | + | ||
178 | + | let currentCycleIgnoredVotes = valueOrElse(getInteger(currentCycleIgnoredVotesKey), 0) | |
179 | + | ||
180 | + | let currentCycleIgnoredValidators = valueOrElse(getInteger(currentCycleIgnoredValidatorsKey), 0) | |
181 | + | ||
182 | + | let totalVotes = getIntegerValue(totalVotesEntryKey) | |
183 | + | ||
184 | + | let totalVotesWithoutIgnoredVotes = (totalVotes - currentCycleIgnoredVotes) | |
185 | + | ||
186 | + | let totalRequestedWavesWithdraw = valueOrElse(getInteger(totalRequestedWavesWithdrawEntryKey), 0) | |
187 | + | ||
188 | + | let contractStatus = getBooleanValue(contractStatusEntryKey) | |
189 | + | ||
190 | + | let stopManager = getBinaryValue(stopManagerEntryKey) | |
191 | + | ||
192 | + | let admin = getBinaryValue(adminPKEntryKey) | |
193 | + | ||
194 | + | let adminFeeBP = valueOrElse(getInteger(adminFeeBPEntryKey), 50) | |
195 | + | ||
196 | + | let activeValidators = valueOrElse(getInteger(activeValidatorsEntryKey), 0) | |
197 | + | ||
198 | + | let activeValidatorsWithoutIgnored = (activeValidators - currentCycleIgnoredValidators) | |
199 | + | ||
200 | + | let puzzleSwap = Address(getBinaryValue(puzzleSwapEntryKey)) | |
201 | + | ||
202 | + | func assert (v,e) = if (v) | |
203 | + | then unit | |
204 | + | else throw(e) | |
205 | + | ||
206 | + | ||
207 | + | func boolToInt (b) = if (b) | |
208 | + | then 1 | |
209 | + | else 0 | |
210 | + | ||
211 | + | ||
212 | + | func UintEntry (key,v) = { | |
213 | + | let _assertUint = assert((v >= 0), errorMessageInvalidUint) | |
214 | + | if ((_assertUint == _assertUint)) | |
215 | + | then IntegerEntry(key, v) | |
216 | + | else throw("Strict value is not equal to itself.") | |
217 | + | } | |
218 | + | ||
219 | + | ||
220 | + | func getValidatorStatus (validatorAddress) = getBoolean((validatorStatusEntryKey + toString(validatorAddress))) | |
221 | + | ||
222 | + | ||
223 | + | func getValidatorStatusValue (validatorAddress) = valueOrErrorMessage(getValidatorStatus(validatorAddress), errorMessageUnknownValidator) | |
224 | + | ||
225 | + | ||
226 | + | func getCancelLeaseForValidator (validatorAddress) = { | |
227 | + | let validatorLeaseIdKey = (leaseIdEntryKey + toBase58String(validatorAddress.bytes)) | |
228 | + | match getBinary(validatorLeaseIdKey) { | |
229 | + | case id: ByteVector => | |
230 | + | [LeaseCancel(id)] | |
231 | + | case _: Unit => | |
232 | + | nil | |
233 | + | case _ => | |
234 | + | throw("Match error") | |
235 | + | } | |
236 | + | } | |
237 | + | ||
238 | + | ||
239 | + | func getRegistrationCycleValue (validatorAddress) = valueOrErrorMessage(getInteger((registrationCycleEntryKey + toString(validatorAddress))), errorMessageUnknownValidator) | |
240 | + | ||
241 | + | ||
242 | + | func getValidatorIdsChanges (validatorAddress) = { | |
243 | + | let thisValidatorIdKey = (validatorIdEntryKey + toString(validatorAddress)) | |
244 | + | let thisValidatorId = getIntegerValue(thisValidatorIdKey) | |
245 | + | let thisValidatorAddressKey = (validatorAddressEntryKey + toString(thisValidatorId)) | |
246 | + | if (if ((thisValidatorId == activeValidators)) | |
247 | + | then true | |
248 | + | else (activeValidators == 1)) | |
249 | + | then [DeleteEntry(thisValidatorIdKey), DeleteEntry(thisValidatorAddressKey)] | |
250 | + | else { | |
251 | + | let lastValidatorAddressKey = (validatorAddressEntryKey + toString(activeValidators)) | |
252 | + | let lastValidatorBytes = getBinaryValue(lastValidatorAddressKey) | |
253 | + | let lastValidatorIdKey = (validatorIdEntryKey + toBase58String(lastValidatorBytes)) | |
254 | + | [IntegerEntry(lastValidatorIdKey, thisValidatorId), BinaryEntry(thisValidatorAddressKey, lastValidatorBytes), DeleteEntry(thisValidatorIdKey), DeleteEntry(lastValidatorAddressKey)] | |
255 | + | } | |
256 | + | } | |
257 | + | ||
258 | + | ||
259 | + | func assertValidatorAddress (validatorAddress) = assert(isDefined(getString((validatorMetaEntryKey + toString(validatorAddress)))), errorMessageUnknownValidator) | |
260 | + | ||
261 | + | ||
262 | + | func assertOnePayment (invocation) = assert((size(invocation.payments) == 1), errorMessageNotOnePayment) | |
263 | + | ||
264 | + | ||
265 | + | func assertLeasingNotInProgress () = { | |
266 | + | let isLeasingInProgress = valueOrElse(getBoolean((isLeasingInProgressEntryKey + toString(currentCycle))), false) | |
267 | + | assert(!(isLeasingInProgress), errorMessageLeasingInProgress) | |
268 | + | } | |
269 | + | ||
270 | + | ||
271 | + | func assertPaymentAsset (invocation,expectedToken) = assert((invocation.payments[0].assetId == expectedToken), errorMessageUnexpectedAssetId) | |
272 | + | ||
273 | + | ||
274 | + | func assertOnePaymentAsset (invocation,expectedToken) = { | |
275 | + | let _assertOnePayment = assertOnePayment(invocation) | |
276 | + | if ((_assertOnePayment == _assertOnePayment)) | |
277 | + | then { | |
278 | + | let _assertPaymentAsset = assertPaymentAsset(invocation, expectedToken) | |
279 | + | if ((_assertPaymentAsset == _assertPaymentAsset)) | |
280 | + | then unit | |
281 | + | else throw("Strict value is not equal to itself.") | |
282 | + | } | |
283 | + | else throw("Strict value is not equal to itself.") | |
284 | + | } | |
285 | + | ||
286 | + | ||
287 | + | func assertNotKickedValidatorStatus (validatorAddress) = assert(getValidatorStatusValue(validatorAddress), errorMessageValidatorWasKicked) | |
288 | + | ||
289 | + | ||
290 | + | func assertValidatorIsLeaseable (validatorAddress) = assert((currentCycle > getRegistrationCycleValue(validatorAddress)), errorMessageValidatorNotReadyToLease) | |
291 | + | ||
292 | + | ||
293 | + | func assertContractActiveStatus () = assert(contractStatus, errorMessageContractNotActive) | |
294 | + | ||
295 | + | ||
296 | + | func assertCaller (invocation,expected) = assert((expected == invocation.caller.bytes), errorMessageUnauthorized) | |
297 | + | ||
298 | + | ||
299 | + | func assertCallerIsContract (invocation) = assertCaller(invocation, this.bytes) | |
300 | + | ||
301 | + | ||
302 | + | func assertCallerIsStopManager (invocation) = assertCaller(invocation, stopManager) | |
303 | + | ||
304 | + | ||
305 | + | func assertCallerIsAdmin (invocation) = assertCaller(invocation, admin) | |
306 | + | ||
307 | + | ||
308 | + | func assertCanUnlock (unlockBlock,validator) = assert(if ((lastBlock.height >= unlockBlock)) | |
309 | + | then true | |
310 | + | else !(valueOrElse(getValidatorStatus(validator), false)), errorMessageTooEarly) | |
311 | + | ||
312 | + | ||
313 | + | @Callable(invocation) | |
314 | + | func init (flowTokenId,adminPk,stopManager,feeCollector,puzzleSwap,fWavesWrapper) = { | |
315 | + | let callerCheck = assertCallerIsContract(invocation) | |
316 | + | if ((callerCheck == callerCheck)) | |
317 | + | then { | |
318 | + | let _assertNotInit = assert(!(isDefined(getInteger(startBlockEntryKey))), errorMessageAlreadyInitialized) | |
319 | + | if ((_assertNotInit == _assertNotInit)) | |
320 | + | then { | |
321 | + | let stopManagerAddress = addressFromStringValue(stopManager) | |
322 | + | let feeCollectorAddress = addressFromStringValue(feeCollector) | |
323 | + | let puzzleSwapAddress = addressFromStringValue(puzzleSwap) | |
324 | + | let fWavesWrapperAddress = addressFromStringValue(fWavesWrapper) | |
325 | + | let fWavesId = getBinaryValue(fWavesWrapperAddress, "fWavesAssetId") | |
326 | + | let adminPkBytes = fromBase58String(adminPk) | |
327 | + | let _checkAddress = addressFromPublicKey(adminPkBytes) | |
328 | + | if ((_checkAddress == _checkAddress)) | |
329 | + | then [UintEntry(totalVotesEntryKey, 0), UintEntry(fWavesQuantityEntryKey, 0), BooleanEntry(contractStatusEntryKey, true), BinaryEntry(flowAssetIdEntryKey, flowTokenId), BinaryEntry(fWavesAssetIdEntryKey, fWavesId), UintEntry(adminFeeBPEntryKey, adminFeeBP), BinaryEntry(adminPKEntryKey, adminPkBytes), UintEntry(totalRequestedWavesWithdrawEntryKey, 0), UintEntry(startBlockEntryKey, lastBlock.height), UintEntry(requiredFlowAmountEntryKey, requiredFlowAmount), BinaryEntry(stopManagerEntryKey, stopManagerAddress.bytes), UintEntry(cycleDurationInBlocksEntryKey, cycleDurationInBlocks), BinaryEntry(adminFeeCollectorEntryKey, feeCollectorAddress.bytes), UintEntry(emergencyVotingThresholdEntryKey, emergencyVotingThreshold), BinaryEntry(puzzleSwapEntryKey, puzzleSwapAddress.bytes), BinaryEntry(fWavesWrapperEntryKey, fWavesWrapperAddress.bytes)] | |
330 | + | else throw("Strict value is not equal to itself.") | |
331 | + | } | |
332 | + | else throw("Strict value is not equal to itself.") | |
333 | + | } | |
334 | + | else throw("Strict value is not equal to itself.") | |
335 | + | } | |
336 | + | ||
337 | + | ||
338 | + | ||
339 | + | @Callable(invocation) | |
340 | + | func stop () = { | |
341 | + | let callerCheck = assertCallerIsStopManager(invocation) | |
342 | + | if ((callerCheck == callerCheck)) | |
343 | + | then [BooleanEntry(contractStatusEntryKey, false)] | |
344 | + | else throw("Strict value is not equal to itself.") | |
345 | + | } | |
346 | + | ||
347 | + | ||
348 | + | ||
349 | + | @Callable(invocation) | |
350 | + | func setStopManager (newStopManager) = { | |
351 | + | let callerCheck = assertCallerIsContract(invocation) | |
352 | + | if ((callerCheck == callerCheck)) | |
353 | + | then { | |
354 | + | let newStopManagerAddress = addressFromStringValue(newStopManager) | |
355 | + | [BinaryEntry(stopManagerEntryKey, newStopManagerAddress.bytes)] | |
356 | + | } | |
357 | + | else throw("Strict value is not equal to itself.") | |
358 | + | } | |
359 | + | ||
360 | + | ||
361 | + | ||
362 | + | @Callable(invocation) | |
363 | + | func setFeeCollector (newFeeCollector) = { | |
364 | + | let callerCheck = assertCallerIsContract(invocation) | |
365 | + | if ((callerCheck == callerCheck)) | |
366 | + | then { | |
367 | + | let newFeeCollectorAddress = addressFromStringValue(newFeeCollector) | |
368 | + | [BinaryEntry(adminFeeCollectorEntryKey, newFeeCollectorAddress.bytes)] | |
369 | + | } | |
370 | + | else throw("Strict value is not equal to itself.") | |
371 | + | } | |
372 | + | ||
373 | + | ||
374 | + | ||
375 | + | @Callable(invocation) | |
376 | + | func setAdmin (newAdmin) = { | |
377 | + | let callerCheck = assertCallerIsContract(invocation) | |
378 | + | if ((callerCheck == callerCheck)) | |
379 | + | then { | |
380 | + | let newAdminBytes = fromBase58String(newAdmin) | |
381 | + | let _checkAddress = addressFromPublicKey(newAdminBytes) | |
382 | + | if ((_checkAddress == _checkAddress)) | |
383 | + | then [BinaryEntry(adminPKEntryKey, newAdminBytes)] | |
384 | + | else throw("Strict value is not equal to itself.") | |
385 | + | } | |
386 | + | else throw("Strict value is not equal to itself.") | |
387 | + | } | |
388 | + | ||
389 | + | ||
390 | + | ||
391 | + | @Callable(invocation) | |
392 | + | func setAdminFeeBP (newAdminFeeBP) = { | |
393 | + | let callerCheck = assertCallerIsContract(invocation) | |
394 | + | if ((callerCheck == callerCheck)) | |
395 | + | then { | |
396 | + | let _checkAdminFeeBP = assert(if ((newAdminFeeBP >= 0)) | |
397 | + | then (BP >= newAdminFeeBP) | |
398 | + | else false, errorMessageInvalidAdminFeeBP) | |
399 | + | if ((_checkAdminFeeBP == _checkAdminFeeBP)) | |
400 | + | then [UintEntry(adminFeeBPEntryKey, newAdminFeeBP)] | |
401 | + | else throw("Strict value is not equal to itself.") | |
402 | + | } | |
403 | + | else throw("Strict value is not equal to itself.") | |
404 | + | } | |
405 | + | ||
406 | + | ||
407 | + | ||
408 | + | @Callable(invocation) | |
409 | + | func swapRewardTokens (routesStr,amount,minToReceive) = { | |
410 | + | let callerCheck = assertCallerIsContract(invocation) | |
411 | + | if ((callerCheck == callerCheck)) | |
412 | + | then { | |
413 | + | let splittedRoute = split(takeRight(routesStr, 50), ",") | |
414 | + | let asset1Str = splittedRoute[(size(splittedRoute) - 1)] | |
415 | + | let asset1 = fromBase58String(asset1Str) | |
416 | + | let swaped = invoke(puzzleSwap, "swap", [routesStr, minToReceive], [AttachedPayment(asset1, amount)]) | |
417 | + | if ((swaped == swaped)) | |
418 | + | then nil | |
419 | + | else throw("Strict value is not equal to itself.") | |
420 | + | } | |
421 | + | else throw("Strict value is not equal to itself.") | |
422 | + | } | |
423 | + | ||
424 | + | ||
425 | + | ||
426 | + | @Callable(invocation) | |
427 | + | func register (metadataUrl) = { | |
428 | + | let _assertContractActiveStatus = assertContractActiveStatus() | |
429 | + | if ((_assertContractActiveStatus == _assertContractActiveStatus)) | |
430 | + | then { | |
431 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
432 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
433 | + | then { | |
434 | + | let _assertOnePaymentAsset = assertOnePaymentAsset(invocation, flowAssetId) | |
435 | + | if ((_assertOnePaymentAsset == _assertOnePaymentAsset)) | |
436 | + | then { | |
437 | + | let validator = toString(invocation.caller) | |
438 | + | let flowAmount = invocation.payments[0].amount | |
439 | + | let validatorKey = (validatorMetaEntryKey + validator) | |
440 | + | let registeredInCycleKey = (registrationCycleEntryKey + validator) | |
441 | + | let id = (activeValidators + 1) | |
442 | + | let validatorIdKey = (validatorIdEntryKey + validator) | |
443 | + | let validatorAddressKey = (validatorAddressEntryKey + toString(id)) | |
444 | + | let _assertNotRegistered = assert(!(isDefined(getString(validatorKey))), errorMessageAlreadyRegistered) | |
445 | + | if ((_assertNotRegistered == _assertNotRegistered)) | |
446 | + | then { | |
447 | + | let _assertEnoughFlow = assert((requiredFlowAmount == flowAmount), errorMessageInvalidFlowAmount) | |
448 | + | if ((_assertEnoughFlow == _assertEnoughFlow)) | |
449 | + | then [UintEntry(registeredInCycleKey, currentCycle), StringEntry(validatorKey, metadataUrl), BooleanEntry((validatorStatusEntryKey + validator), true), UintEntry(currentCycleIgnoredValidatorsKey, (currentCycleIgnoredValidators + 1)), UintEntry(activeValidatorsEntryKey, (activeValidators + 1)), IntegerEntry(validatorIdKey, id), BinaryEntry(validatorAddressKey, invocation.caller.bytes)] | |
450 | + | else throw("Strict value is not equal to itself.") | |
451 | + | } | |
452 | + | else throw("Strict value is not equal to itself.") | |
453 | + | } | |
454 | + | else throw("Strict value is not equal to itself.") | |
455 | + | } | |
456 | + | else throw("Strict value is not equal to itself.") | |
457 | + | } | |
458 | + | else throw("Strict value is not equal to itself.") | |
459 | + | } | |
460 | + | ||
461 | + | ||
462 | + | ||
463 | + | @Callable(invocation) | |
464 | + | func deregister () = { | |
465 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
466 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
467 | + | then { | |
468 | + | let validatorAddress = invocation.caller | |
469 | + | let validator = toString(invocation.caller) | |
470 | + | let validatorStatusKey = (validatorStatusEntryKey + validator) | |
471 | + | let validatorVotesKey = (votesEntryKey + validator) | |
472 | + | let registeredInCycleKey = (registrationCycleEntryKey + validator) | |
473 | + | let _assertValidatorAddress = assertValidatorAddress(validatorAddress) | |
474 | + | if ((_assertValidatorAddress == _assertValidatorAddress)) | |
475 | + | then { | |
476 | + | let validatorIdsChanges = getValidatorIdsChanges(validatorAddress) | |
477 | + | let validatorLeaseIdKey = (leaseIdEntryKey + validator) | |
478 | + | let cancel = getCancelLeaseForValidator(validatorAddress) | |
479 | + | let nonKickedChanges = if (getValidatorStatusValue(validatorAddress)) | |
480 | + | then { | |
481 | + | let validatorVotes = valueOrElse(getInteger(validatorVotesKey), 0) | |
482 | + | (validatorIdsChanges ++ [UintEntry(activeValidatorsEntryKey, (activeValidators - 1)), UintEntry(totalVotesEntryKey, (totalVotes - validatorVotes)), ScriptTransfer(validatorAddress, requiredFlowAmount, flowAssetId)]) | |
483 | + | } | |
484 | + | else nil | |
485 | + | let ignoredValidatorsChanges = if ((getRegistrationCycleValue(validatorAddress) == currentCycle)) | |
486 | + | then [UintEntry(currentCycleIgnoredValidatorsKey, (currentCycleIgnoredValidators - 1))] | |
487 | + | else nil | |
488 | + | (((nonKickedChanges ++ ignoredValidatorsChanges) ++ cancel) ++ [DeleteEntry(validatorVotesKey), DeleteEntry(registeredInCycleKey), DeleteEntry(validatorStatusKey), DeleteEntry((validatorMetaEntryKey + validator)), DeleteEntry((validatorLeasesEntryKey + validator)), DeleteEntry(validatorLeaseIdKey), DeleteEntry((latestValidatorLeasingCycleEntryKey + validator))]) | |
489 | + | } | |
490 | + | else throw("Strict value is not equal to itself.") | |
491 | + | } | |
492 | + | else throw("Strict value is not equal to itself.") | |
493 | + | } | |
494 | + | ||
495 | + | ||
496 | + | ||
497 | + | @Callable(invocation) | |
498 | + | func deposit () = { | |
499 | + | let _assertContractActiveStatus = assertContractActiveStatus() | |
500 | + | if ((_assertContractActiveStatus == _assertContractActiveStatus)) | |
501 | + | then { | |
502 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
503 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
504 | + | then { | |
505 | + | let _assertOnePaymentAsset = assertOnePaymentAsset(invocation, unit) | |
506 | + | if ((_assertOnePaymentAsset == _assertOnePaymentAsset)) | |
507 | + | then { | |
508 | + | let wavesAmount = invocation.payments[0].amount | |
509 | + | let fWavesAmount = if ((fWavesQuantity == 0)) | |
510 | + | then wavesAmount | |
511 | + | else fraction(wavesAmount, fWavesQuantity, (wavesBalance(this).regular - wavesAmount)) | |
512 | + | let adminFWavesAmount = fraction(fWavesAmount, adminFeeBP, BP, CEILING) | |
513 | + | let fWavesAmountWithoutAdminFee = (fWavesAmount - adminFWavesAmount) | |
514 | + | let adminFeeCollectorAddress = Address(getBinaryValue(adminFeeCollectorEntryKey)) | |
515 | + | let mint = invoke(fWavesWrapper, "mint", [fWavesAmount], nil) | |
516 | + | if ((mint == mint)) | |
517 | + | then [UintEntry(fWavesQuantityEntryKey, (fWavesQuantity + fWavesAmount)), ScriptTransfer(invocation.caller, fWavesAmountWithoutAdminFee, fWavesAssetId), ScriptTransfer(adminFeeCollectorAddress, adminFWavesAmount, fWavesAssetId)] | |
518 | + | else throw("Strict value is not equal to itself.") | |
519 | + | } | |
520 | + | else throw("Strict value is not equal to itself.") | |
521 | + | } | |
522 | + | else throw("Strict value is not equal to itself.") | |
523 | + | } | |
524 | + | else throw("Strict value is not equal to itself.") | |
525 | + | } | |
526 | + | ||
527 | + | ||
528 | + | ||
529 | + | @Callable(invocation) | |
530 | + | func requestWithdraw () = { | |
531 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
532 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
533 | + | then { | |
534 | + | let _assertOnePaymentAsset = assertOnePaymentAsset(invocation, fWavesAssetId) | |
535 | + | if ((_assertOnePaymentAsset == _assertOnePaymentAsset)) | |
536 | + | then { | |
537 | + | let fWavesAmount = invocation.payments[0].amount | |
538 | + | let wavesAmount = fraction(fWavesAmount, withdrawWavesBalanceState, withdrawFWavesQuantityState) | |
539 | + | let callerKey = toString(invocation.caller) | |
540 | + | let requestedFWavesWithdrawKey = (requestedFWavesWithdrawEntryKey + callerKey) | |
541 | + | let requestedWavesWithdrawKey = (requestedWavesWithdrawEntryKey + callerKey) | |
542 | + | let requestedFWavesWithdrawForCaller = valueOrElse(getInteger(requestedFWavesWithdrawKey), 0) | |
543 | + | let requestedWavesWithdrawForCaller = valueOrElse(getInteger(requestedWavesWithdrawKey), 0) | |
544 | + | [UintEntry(requestedFWavesWithdrawKey, (requestedFWavesWithdrawForCaller + fWavesAmount)), UintEntry(requestedWavesWithdrawKey, (requestedWavesWithdrawForCaller + wavesAmount)), UintEntry(totalRequestedWavesWithdrawEntryKey, (totalRequestedWavesWithdraw + wavesAmount))] | |
545 | + | } | |
546 | + | else throw("Strict value is not equal to itself.") | |
547 | + | } | |
548 | + | else throw("Strict value is not equal to itself.") | |
549 | + | } | |
550 | + | ||
551 | + | ||
552 | + | ||
553 | + | @Callable(invocation) | |
554 | + | func processWithdraw (recipient) = { | |
555 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
556 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
557 | + | then { | |
558 | + | let recipientAddress = addressFromStringValue(recipient) | |
559 | + | let requestedFWavesWithdrawKey = (requestedFWavesWithdrawEntryKey + recipient) | |
560 | + | let requestedWavesWithdrawKey = (requestedWavesWithdrawEntryKey + recipient) | |
561 | + | let requestedWavesWithdraw = valueOrErrorMessage(getInteger(requestedWavesWithdrawKey), errorMessageNoRequestedWithdraw) | |
562 | + | let requestedFWavesWithdraw = valueOrErrorMessage(getInteger(requestedFWavesWithdrawKey), errorMessageNoRequestedWithdraw) | |
563 | + | let _asserAvailable = assert((available >= requestedWavesWithdraw), errorMessageWavesBalanceNotEnough) | |
564 | + | if ((_asserAvailable == _asserAvailable)) | |
565 | + | then { | |
566 | + | let burn = invoke(fWavesWrapper, "burn", nil, [AttachedPayment(fWavesAssetId, requestedFWavesWithdraw)]) | |
567 | + | if ((burn == burn)) | |
568 | + | then [UintEntry(totalRequestedWavesWithdrawEntryKey, (totalRequestedWavesWithdraw - requestedWavesWithdraw)), DeleteEntry(requestedFWavesWithdrawKey), DeleteEntry(requestedWavesWithdrawKey), UintEntry(fWavesQuantityEntryKey, (fWavesQuantity - requestedFWavesWithdraw)), ScriptTransfer(recipientAddress, requestedWavesWithdraw, unit)] | |
569 | + | else throw("Strict value is not equal to itself.") | |
570 | + | } | |
571 | + | else throw("Strict value is not equal to itself.") | |
572 | + | } | |
573 | + | else throw("Strict value is not equal to itself.") | |
574 | + | } | |
575 | + | ||
576 | + | ||
577 | + | ||
578 | + | @Callable(invocation) | |
579 | + | func revokeWithdraw () = { | |
580 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
581 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
582 | + | then { | |
583 | + | let recipient = toString(invocation.caller) | |
584 | + | let requestedFWavesWithdrawKey = (requestedFWavesWithdrawEntryKey + recipient) | |
585 | + | let requestedWavesWithdrawKey = (requestedWavesWithdrawEntryKey + recipient) | |
586 | + | let requestedWavesWithdraw = valueOrErrorMessage(getInteger(requestedWavesWithdrawKey), errorMessageNoRequestedWithdraw) | |
587 | + | let requestedFWavesWithdraw = valueOrErrorMessage(getInteger(requestedFWavesWithdrawKey), errorMessageNoRequestedWithdraw) | |
588 | + | [UintEntry(totalRequestedWavesWithdrawEntryKey, (totalRequestedWavesWithdraw - requestedWavesWithdraw)), ScriptTransfer(invocation.caller, requestedFWavesWithdraw, fWavesAssetId), DeleteEntry(requestedFWavesWithdrawKey), DeleteEntry(requestedWavesWithdrawKey)] | |
589 | + | } | |
590 | + | else throw("Strict value is not equal to itself.") | |
591 | + | } | |
592 | + | ||
593 | + | ||
594 | + | ||
595 | + | @Callable(invocation) | |
596 | + | func vote (validator,interval) = { | |
597 | + | let _assertContractActiveStatus = assertContractActiveStatus() | |
598 | + | if ((_assertContractActiveStatus == _assertContractActiveStatus)) | |
599 | + | then { | |
600 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
601 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
602 | + | then { | |
603 | + | let validatorAddress = addressFromStringValue(validator) | |
604 | + | let _assetValidatorStatus = assertNotKickedValidatorStatus(validatorAddress) | |
605 | + | if ((_assetValidatorStatus == _assetValidatorStatus)) | |
606 | + | then { | |
607 | + | let _assertOnePaymentAsset = assertOnePaymentAsset(invocation, flowAssetId) | |
608 | + | if ((_assertOnePaymentAsset == _assertOnePaymentAsset)) | |
609 | + | then { | |
610 | + | let _assertValidInterval = assert(if ((interval >= minVoteInterval)) | |
611 | + | then (maxVoteInterval >= interval) | |
612 | + | else false, errorMessageInvalidInterval) | |
613 | + | if ((_assertValidInterval == _assertValidInterval)) | |
614 | + | then { | |
615 | + | let unlockBlock = (lastBlock.height + interval) | |
616 | + | let newUserLock = invocation.payments[0].amount | |
617 | + | let newUserVotes = fraction(newUserLock, sqrt(interval, 0, 0, FLOOR), cycleDurationInBlocksSqrtFloor) | |
618 | + | let callerUnlockKeyPart = ((toString(invocation.caller) + "|") + toString(unlockBlock)) | |
619 | + | let unlockBlockKey = (unlockBlockEntryKey + callerUnlockKeyPart) | |
620 | + | let totalValidatorVotesKey = (votesEntryKey + validator) | |
621 | + | let userVoteKey = (userVoteEntryKey + callerUnlockKeyPart) | |
622 | + | let userLockKey = (userLockEntryKey + callerUnlockKeyPart) | |
623 | + | let userLock = (valueOrElse(getInteger(userVoteKey), 0) + newUserLock) | |
624 | + | let userVotes = (valueOrElse(getInteger(userLockKey), 0) + newUserVotes) | |
625 | + | let totalValidatorVotes = valueOrElse(getInteger(totalValidatorVotesKey), 0) | |
626 | + | let ignoreValidatorsChanges = if ((getRegistrationCycleValue(validatorAddress) == currentCycle)) | |
627 | + | then [UintEntry(currentCycleIgnoredVotesKey, (currentCycleIgnoredVotes + newUserVotes))] | |
628 | + | else nil | |
629 | + | (ignoreValidatorsChanges ++ [UintEntry(userVoteKey, userVotes), UintEntry(userLockKey, userLock), BinaryEntry(unlockBlockKey, validatorAddress.bytes), UintEntry(totalValidatorVotesKey, (totalValidatorVotes + newUserVotes)), UintEntry(totalVotesEntryKey, (totalVotes + newUserVotes))]) | |
630 | + | } | |
631 | + | else throw("Strict value is not equal to itself.") | |
632 | + | } | |
633 | + | else throw("Strict value is not equal to itself.") | |
634 | + | } | |
635 | + | else throw("Strict value is not equal to itself.") | |
636 | + | } | |
637 | + | else throw("Strict value is not equal to itself.") | |
638 | + | } | |
639 | + | else throw("Strict value is not equal to itself.") | |
640 | + | } | |
641 | + | ||
642 | + | ||
643 | + | ||
644 | + | @Callable(invocation) | |
645 | + | func redeem (unlockBlock) = { | |
646 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
647 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
648 | + | then { | |
649 | + | let callerUnlockKeyPart = ((toString(invocation.caller) + "|") + toString(unlockBlock)) | |
650 | + | let unlockBlockKey = (unlockBlockEntryKey + callerUnlockKeyPart) | |
651 | + | let userVoteKey = (userVoteEntryKey + callerUnlockKeyPart) | |
652 | + | let userLockKey = (userLockEntryKey + callerUnlockKeyPart) | |
653 | + | let validatorAddress = Address(valueOrErrorMessage(getBinary(unlockBlockKey), errorMessageUnknownLock)) | |
654 | + | let validatorVotesKey = (votesEntryKey + toBase58String(validatorAddress.bytes)) | |
655 | + | let _assertCanUnlock = assertCanUnlock(unlockBlock, validatorAddress) | |
656 | + | if ((_assertCanUnlock == _assertCanUnlock)) | |
657 | + | then { | |
658 | + | let userVotes = getIntegerValue(userVoteKey) | |
659 | + | let userLock = getIntegerValue(userLockKey) | |
660 | + | let status = valueOrElse(getValidatorStatus(validatorAddress), false) | |
661 | + | let votesChanges = if (status) | |
662 | + | then [UintEntry(validatorVotesKey, (getIntegerValue(validatorVotesKey) - userVotes)), UintEntry(totalVotesEntryKey, (totalVotes - userVotes))] | |
663 | + | else nil | |
664 | + | (votesChanges ++ [ScriptTransfer(invocation.caller, userLock, flowAssetId), DeleteEntry(userVoteKey), DeleteEntry(unlockBlockKey), DeleteEntry(userLockKey)]) | |
665 | + | } | |
666 | + | else throw("Strict value is not equal to itself.") | |
667 | + | } | |
668 | + | else throw("Strict value is not equal to itself.") | |
669 | + | } | |
670 | + | ||
671 | + | ||
672 | + | ||
673 | + | @Callable(invocation) | |
674 | + | func leasing (validator) = { | |
675 | + | let validatorAddress = addressFromStringValue(validator) | |
676 | + | let _assertValidatorIsNotKicked = assertNotKickedValidatorStatus(validatorAddress) | |
677 | + | if ((_assertValidatorIsNotKicked == _assertValidatorIsNotKicked)) | |
678 | + | then { | |
679 | + | let _assertValidatorIsLeaseable = assertValidatorIsLeaseable(validatorAddress) | |
680 | + | if ((_assertValidatorIsLeaseable == _assertValidatorIsLeaseable)) | |
681 | + | then { | |
682 | + | let validatorLeaseIdKey = (leaseIdEntryKey + validator) | |
683 | + | let latestLeasingCycleKey = (latestValidatorLeasingCycleEntryKey + validator) | |
684 | + | let validatorLeasesKey = (validatorLeasesEntryKey + validator) | |
685 | + | let currentCycleKey = toString(currentCycle) | |
686 | + | let currentProcessedLeasesEntryKey = (processedLeasesEntryKey + currentCycleKey) | |
687 | + | let currentLeasingPoolValueEntryKey = (leasingPoolValueEntryKey + currentCycleKey) | |
688 | + | let isCurrentLeasingInProgressEntryKey = (isLeasingInProgressEntryKey + currentCycleKey) | |
689 | + | let validatorVotes = valueOrElse(getInteger((votesEntryKey + validator)), 0) | |
690 | + | let currentLeaseAmount = valueOrElse(getInteger(validatorLeasesKey), 0) | |
691 | + | let cancelLease = getCancelLeaseForValidator(validatorAddress) | |
692 | + | let _checkLeasingStatus = assert((valueOrElse(getInteger(latestLeasingCycleKey), -1) != currentCycle), errorMessageAlreadyLeased) | |
693 | + | if ((_checkLeasingStatus == _checkLeasingStatus)) | |
694 | + | then { | |
695 | + | let proccessedLeasesEntries = (valueOrElse(getInteger(currentProcessedLeasesEntryKey), 0) + 1) | |
696 | + | let leasingPoolValue = valueOrElse(getInteger(currentLeasingPoolValueEntryKey), wavesBalance(this).regular) | |
697 | + | let afterLeasingProcess = if ((activeValidatorsWithoutIgnored > proccessedLeasesEntries)) | |
698 | + | then [BooleanEntry(isCurrentLeasingInProgressEntryKey, true), UintEntry(currentProcessedLeasesEntryKey, proccessedLeasesEntries), UintEntry(currentLeasingPoolValueEntryKey, leasingPoolValue)] | |
699 | + | else [UintEntry(withdrawWavesBalanceStateEntryKey, leasingPoolValue), UintEntry(withdrawFWavesQuantityStateEntryKey, fWavesQuantity), IntegerEntry(latestLeasingCycleEntryKey, currentCycle), DeleteEntry(isCurrentLeasingInProgressEntryKey), DeleteEntry(currentProcessedLeasesEntryKey), DeleteEntry(currentLeasingPoolValueEntryKey), DeleteEntry(currentCycleIgnoredValidatorsKey), DeleteEntry(currentCycleIgnoredVotesKey)] | |
700 | + | let deleteLeaseEntries = if (isDefined(getInteger(validatorLeasesKey))) | |
701 | + | then [DeleteEntry(validatorLeasesKey), DeleteEntry(validatorLeaseIdKey)] | |
702 | + | else nil | |
703 | + | let targetLeaseAmount = fraction((leasingPoolValue - totalRequestedWavesWithdraw), validatorVotes, totalVotesWithoutIgnoredVotes) | |
704 | + | if (if (!(contractStatus)) | |
705 | + | then true | |
706 | + | else (totalVotesWithoutIgnoredVotes == 0)) | |
707 | + | then ((cancelLease ++ deleteLeaseEntries) ++ afterLeasingProcess) | |
708 | + | else if ((targetLeaseAmount != currentLeaseAmount)) | |
709 | + | then { | |
710 | + | let lease = Lease(validatorAddress, targetLeaseAmount) | |
711 | + | let leasingProcess = if ((targetLeaseAmount == 0)) | |
712 | + | then deleteLeaseEntries | |
713 | + | else [lease, BinaryEntry(validatorLeaseIdKey, calculateLeaseId(lease)), UintEntry(validatorLeasesKey, targetLeaseAmount)] | |
714 | + | (((cancelLease ++ leasingProcess) ++ afterLeasingProcess) :+ UintEntry(latestLeasingCycleKey, currentCycle)) | |
715 | + | } | |
716 | + | else (afterLeasingProcess :+ UintEntry(latestLeasingCycleKey, currentCycle)) | |
717 | + | } | |
718 | + | else throw("Strict value is not equal to itself.") | |
719 | + | } | |
720 | + | else throw("Strict value is not equal to itself.") | |
721 | + | } | |
722 | + | else throw("Strict value is not equal to itself.") | |
723 | + | } | |
724 | + | ||
725 | + | ||
726 | + | ||
727 | + | @Callable(invocation) | |
728 | + | func emergencyVoting (validator) = { | |
729 | + | let _assertLeasingNotInProgress = assertLeasingNotInProgress() | |
730 | + | if ((_assertLeasingNotInProgress == _assertLeasingNotInProgress)) | |
731 | + | then { | |
732 | + | let _assertContractActiveStatus = assertContractActiveStatus() | |
733 | + | if ((_assertContractActiveStatus == _assertContractActiveStatus)) | |
734 | + | then { | |
735 | + | let validatorAddress = addressFromStringValue(validator) | |
736 | + | let _assetValidatorStatus = assertNotKickedValidatorStatus(validatorAddress) | |
737 | + | if ((_assetValidatorStatus == _assetValidatorStatus)) | |
738 | + | then { | |
739 | + | let _assertOnePaymentAsset = assertOnePaymentAsset(invocation, fWavesAssetId) | |
740 | + | if ((_assertOnePaymentAsset == _assertOnePaymentAsset)) | |
741 | + | then { | |
742 | + | let voteAmount = invocation.payments[0].amount | |
743 | + | let callerKey = toString(invocation.caller) | |
744 | + | let unlockBlock = (lastBlock.height + emergencyVotingLock) | |
745 | + | let emergencyVotesKey = (emergencyVotesEntryKey + validator) | |
746 | + | let emergencyUserVotesKey = (((emergencyUserVotesEntryKey + callerKey) + "|") + validator) | |
747 | + | let validatorVotesKey = (votesEntryKey + validator) | |
748 | + | let validatorLeaseIdKey = (leaseIdEntryKey + validator) | |
749 | + | let emergencyUserLockKey = (((emergencyUserLockEntryKey + callerKey) + "|") + toString(unlockBlock)) | |
750 | + | let emergencyVotes = (voteAmount + valueOrElse(getInteger(emergencyVotesKey), 0)) | |
751 | + | let isValidatorBad = (((emergencyVotes * 100) / fWavesQuantity) > emergencyVotingThreshold) | |
752 | + | let punishment = if (isValidatorBad) | |
753 | + | then { | |
754 | + | let cancel = getCancelLeaseForValidator(validatorAddress) | |
755 | + | let totalValidatorVotes = valueOrElse(getInteger(validatorVotesKey), 0) | |
756 | + | let currentStatus = getValidatorStatusValue(validatorAddress) | |
757 | + | let leaseableValidatorsChanges = if (currentStatus) | |
758 | + | then [UintEntry(activeValidatorsEntryKey, (activeValidators - 1))] | |
759 | + | else nil | |
760 | + | let validatorIdsChanges = getValidatorIdsChanges(validatorAddress) | |
761 | + | (((validatorIdsChanges ++ leaseableValidatorsChanges) ++ cancel) ++ [ScriptTransfer(flowAssetInfo.issuer, requiredFlowAmount, flowAssetId), UintEntry(totalVotesEntryKey, (totalVotes - totalValidatorVotes)), BooleanEntry((validatorStatusEntryKey + validator), false), DeleteEntry((validatorLeasesEntryKey + validator)), DeleteEntry(validatorLeaseIdKey), DeleteEntry((latestValidatorLeasingCycleEntryKey + validator))]) | |
762 | + | } | |
763 | + | else nil | |
764 | + | (punishment ++ [BinaryEntry(emergencyUserLockKey, validatorAddress.bytes), UintEntry(emergencyVotesKey, emergencyVotes), UintEntry(emergencyUserVotesKey, (valueOrElse(getInteger(emergencyUserVotesKey), 0) + voteAmount))]) | |
765 | + | } | |
766 | + | else throw("Strict value is not equal to itself.") | |
767 | + | } | |
768 | + | else throw("Strict value is not equal to itself.") | |
769 | + | } | |
770 | + | else throw("Strict value is not equal to itself.") | |
771 | + | } | |
772 | + | else throw("Strict value is not equal to itself.") | |
773 | + | } | |
774 | + | ||
775 | + | ||
776 | + | ||
777 | + | @Callable(invocation) | |
778 | + | func redeemEmergencyVote (unlockBlock) = { | |
779 | + | let callerKey = toString(invocation.caller) | |
780 | + | let emergencyUserLockKey = (((emergencyUserLockEntryKey + callerKey) + "|") + toString(unlockBlock)) | |
781 | + | let validatorAddress = Address(valueOrErrorMessage(getBinary(emergencyUserLockKey), errorMessageUnknownLock)) | |
782 | + | let validator = toString(validatorAddress) | |
783 | + | let _assertCanUnlock = assertCanUnlock(unlockBlock, validatorAddress) | |
784 | + | if ((_assertCanUnlock == _assertCanUnlock)) | |
785 | + | then { | |
786 | + | let emergencyVotesKey = (emergencyVotesEntryKey + validator) | |
787 | + | let emergencyUserVotesKey = (((emergencyUserVotesEntryKey + callerKey) + "|") + validator) | |
788 | + | let emergencyUserVotes = valueOrErrorMessage(getInteger(emergencyUserVotesKey), errorMessageNoEmergencyVotes) | |
789 | + | let emergencyVotes = (getIntegerValue(emergencyVotesKey) - emergencyUserVotes) | |
790 | + | [ScriptTransfer(invocation.caller, emergencyUserVotes, fWavesAssetId), UintEntry(emergencyVotesKey, emergencyVotes), DeleteEntry(emergencyUserVotesKey), DeleteEntry(emergencyUserLockKey)] | |
791 | + | } | |
792 | + | else throw("Strict value is not equal to itself.") | |
793 | + | } | |
794 | + | ||
795 | + | ||
796 | + | @Verifier(tx) | |
797 | + | func verify () = match tx { | |
798 | + | case ttx: SetScriptTransaction => | |
799 | + | !(isDefined(getInteger(startBlockEntryKey))) | |
800 | + | case ttx: InvokeScriptTransaction => | |
801 | + | if (if ((ttx.dApp == this)) | |
802 | + | then containsElement(adminMultiSig, ttx.function) | |
803 | + | else false) | |
804 | + | then { | |
805 | + | let sigA = sigVerify(tx.bodyBytes, tx.proofs[0], flowLeasePk) | |
806 | + | let sigB = sigVerify(tx.bodyBytes, tx.proofs[1], admin) | |
807 | + | if (sigA) | |
808 | + | then sigB | |
809 | + | else false | |
810 | + | } | |
811 | + | else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
812 | + | case _ => | |
813 | + | sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
814 | + | } | |
815 | + |
github/deemru/w8io/169f3d6 41.58 ms ◑![]()