tx · F4ZRZKEp5Tdpuwvtz9A7MmyUEwa7FJwExVLEHZD3TyBT 3NAg2HDvKz7gwrNc2wnUxdK74NydBFUXTYP: -0.03300000 Waves 2024.12.09 16:58 [3407157] smart account 3NAg2HDvKz7gwrNc2wnUxdK74NydBFUXTYP > SELF 0.00000000 Waves
{ "type": 13, "id": "F4ZRZKEp5Tdpuwvtz9A7MmyUEwa7FJwExVLEHZD3TyBT", "fee": 3300000, "feeAssetId": null, "timestamp": 1733752673809, "version": 2, "chainId": 84, "sender": "3NAg2HDvKz7gwrNc2wnUxdK74NydBFUXTYP", "senderPublicKey": "BEbZF8zo7WjaQFZFFuPs7hqSLEgGwjwQFGg4tSidf9C3", "proofs": [ "5LvhauEw6qzaYyW7rRZQvQivmRydM9VcooxrxEXZeMnsjfjhmftRYRo3rR98tpiThLipMmMVZZfAvVwcCFAWqzYB" ], "script": "base64:BwJuCAISCAoGCAgICAgIEggKBggICAgICBIJCgcICAgICAgIEgUKAwgICBIDCgEIEgwKCggICAgICAgICAgSBgoECAgICBIFCgMBCAgSBQoDAQgIEgMKAQESAwoBCBIDCgEIEgASABIDCgEIEgMKAQhxAAlTRVBBUkFUT1ICAl9fAAxLRVlfTVVMVElTSUcCCE1VTFRJU0lHAApLRVlfU1RBVFVTAgZTVEFUVVMACEtFWV9JTklUAgRJTklUAApLRVlfUEFVU0VEAgZQQVVTRUQACktFWV9QQVVTRVICBlBBVVNFUgAMS0VZX0VYRUNVVE9SAghFWEVDVVRPUgATS0VZX0NBTExFUl9DT05UUkFDVAIPQ0FMTEVSX0NPTlRSQUNUAA9LRVlfV0FWRVNfVkFVTFQCC1dBVkVTX1ZBVUxUABNLRVlfQUNDT1VOVF9TVE9SQUdFAg9BQ0NPVU5UX1NUT1JBR0UACUtFWV9DSEFJTgIFQ0hBSU4AEktFWV9BU1NFVF9DVVJSRU5DWQIOQVNTRVRfQ1VSUkVOQ1kAEktFWV9BU1NFVF9SRVNFUlZFUwIOQVNTRVRfUkVTRVJWRVMAGUtFWV9BU1NFVF9SRVNFUlZFU19MT0NLRUQCFUFTU0VUX1JFU0VSVkVTX0xPQ0tFRAAYS0VZX1VTRVJfTE9DS0VEX0NVUlJFTkNZAhRVU0VSX0xPQ0tFRF9DVVJSRU5DWQAVS0VZX0NVUlJFTkNZX1JFU0VSVkVTAhFDVVJSRU5DWV9SRVNFUlZFUwAbS0VZX1JFUVVFU1RfV0lUSERSQVdBTF9TSVpFAhdSRVFVRVNUX1dJVEhEUkFXQUxfU0laRQAWS0VZX1JFUVVFU1RfV0lUSERSQVdBTAISUkVRVUVTVF9XSVRIRFJBV0FMACJLRVlfUkVRVUVTVF9XSVRIRFJBV0FMX0JMT0NLX0RFTEFZAh5SRVFVRVNUX1dJVEhEUkFXQUxfQkxPQ0tfREVMQVkADUtFWV9TRVFVRU5DRVICCVNFUVVFTkNFUgATS0VZX1dJVEhEUkFXQUxfSEFTSAIPV0lUSERSQVdBTF9IQVNIABFLRVlfVkFVTFRfQURBUFRFUgINVkFVTFRfQURBUFRFUgAWS0VZX1JFV0FSRF9ESVNUUklCVVRPUgISUkVXQVJEX0RJU1RSSUJVVE9SABlLRVlfUkVMQVlFUl9GRUVfUkVDSVBJRU5UAhVSRUxBWUVSX0ZFRV9SRUNJUElFTlQADEZVTkNfREVQT1NJVAIHZGVwb3NpdAAVRlVOQ19HRVRfVVNFUl9CQUxBTkNFAg5nZXRVc2VyQmFsYW5jZQAWRlVOQ19JTlRFUk5BTF9UUkFOU0ZFUgIQaW50ZXJuYWxUcmFuc2ZlcgANRlVOQ19XSVRIRFJBVwIId2l0aGRyYXcAG0ZVTkNfREVQT1NJVF9TVEFLSU5HX1JFV0FSRAIUZGVwb3NpdFN0YWtpbmdSZXdhcmQAFlJFUVVFU1RfU1RBVFVTX0NSRUFURUQAAAATUkVRVUVTVF9TVEFUVVNfRE9ORQABABdSRVFVRVNUX1NUQVRVU19SRUpFQ1RFRAACAAVXQVZFUwIFV0FWRVMAC1NQT1RfV0FMTEVUAgRTUE9UAAdNQVhfSU5UAP//////////fwALWkVST19CSUdJTlQJALYCAQAAAApPTkVfQklHSU5UCQC2AgEAAQAHT05FX0RBWQCAuJkpAA5BTEdfVFlQRV9XQVZFUwABAAxBTEdfVFlQRV9FVk0AAgAMV0FWRVNfUFJFRklYAQT///8BABRFVk1fU0lHTkFUVVJFX1BSRUZJWAEcGUV0aGVyZXVtIFNpZ25lZCBNZXNzYWdlOgozMgEQX3ZhbGlkYXRlQWRkcmVzcwIIYWRkcmVzc18EZXJyXwQHJG1hdGNoMAkApggBBQhhZGRyZXNzXwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAFhBQckbWF0Y2gwBgkAAgEFBGVycl8BDF92YWxpZGF0ZUludAQEdmFsXw5sb3dlckJvdW5kYXJ5Xw51cHBlckJvdW5kYXJ5XwRlcnJfAwMJAGYCBQ5sb3dlckJvdW5kYXJ5XwUEdmFsXwYJAGYCBQR2YWxfBQ51cHBlckJvdW5kYXJ5XwkAAgEFBGVycl8GAQ9fdmFsaWRhdGVCaWdJbnQDBHZhbF8ObG93ZXJCb3VuZGFyeV8EZXJyXwMJAL8CAgUObG93ZXJCb3VuZGFyeV8FBHZhbF8JAAIBBQRlcnJfBgERX3ZhbGlkYXRlQmlnSW50XzIEBHZhbF8ObG93ZXJCb3VuZGFyeV8OdXBwZXJCb3VuZGFyeV8EZXJyXwMDCQC/AgIFDmxvd2VyQm91bmRhcnlfBQR2YWxfBgkAvwICBQR2YWxfBQ51cHBlckJvdW5kYXJ5XwkAAgEFBGVycl8GAQ9fdmFsaWRhdGVTdHJpbmcCBHZhbF8EZXJyXwMDCQBnAgAACQCxAgEFBHZhbF8GCQEIY29udGFpbnMCBQR2YWxfBQlTRVBBUkFUT1IJAAIBBQRlcnJfBgEUX3ZhbGlkYXRlU3RyaW5nRXF1YWwDBXZhbDFfBXZhbDJfBGVycl8DCQECIT0CBQV2YWwxXwUFdmFsMl8JAAIBBQRlcnJfBgEJX2xvYWRJbml0AAQHJG1hdGNoMAkAoAgBBQhLRVlfSU5JVAMJAAECBQckbWF0Y2gwAgdCb29sZWFuBAFhBQckbWF0Y2gwBQFhBwEJX3NhdmVJbml0AQdpc0luaXRfCQDMCAIJAQxCb29sZWFuRW50cnkCBQhLRVlfSU5JVAUHaXNJbml0XwUDbmlsAQpfbG9hZFBhdXNlAAQHJG1hdGNoMAkAoAgBBQpLRVlfUEFVU0VEAwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EAWEFByRtYXRjaDAFAWEHAQpfc2F2ZVBhdXNlAQlpc1BhdXNlZF8JAMwIAgkBDEJvb2xlYW5FbnRyeQIFCktFWV9QQVVTRUQFCWlzUGF1c2VkXwUDbmlsAQtfbG9hZFBhdXNlcgAEByRtYXRjaDAJAKIIAQUKS0VZX1BBVVNFUgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAWEJAQdBZGRyZXNzAQEAAQtfc2F2ZVBhdXNlcgEHcGF1c2VyXwkAzAgCCQELU3RyaW5nRW50cnkCBQpLRVlfUEFVU0VSCQClCAEFB3BhdXNlcl8FA25pbAENX2xvYWRNdWx0aXNpZwAEByRtYXRjaDAJAKIIAQUMS0VZX01VTFRJU0lHAwkAAQIFByRtYXRjaDACBlN0cmluZwQBYQUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQUBYQkBB0FkZHJlc3MBAQABDV9zYXZlTXVsdGlzaWcBCW11bHRpc2lnXwkAzAgCCQELU3RyaW5nRW50cnkCBQxLRVlfTVVMVElTSUcJAKUIAQUJbXVsdGlzaWdfBQNuaWwBE19sb2FkQ2FsbGVyQ29udHJhY3QBCGNoYWluSWRfBAckbWF0Y2gwCQCiCAEJALkJAgkAzAgCBRNLRVlfQ0FMTEVSX0NPTlRSQUNUCQDMCAIJAKQDAQUIY2hhaW5JZF8FA25pbAUJU0VQQVJBVE9SAwkAAQIFByRtYXRjaDACBlN0cmluZwQBYQUHJG1hdGNoMAUBYQIAARNfc2F2ZUNhbGxlckNvbnRyYWN0AghjaGFpbklkXw9jYWxsZXJDb250cmFjdF8JAMwIAgkBC1N0cmluZ0VudHJ5AgkAuQkCCQDMCAIFE0tFWV9DQUxMRVJfQ09OVFJBQ1QJAMwIAgkApAMBBQhjaGFpbklkXwUDbmlsBQlTRVBBUkFUT1IFD2NhbGxlckNvbnRyYWN0XwUDbmlsAQ1fbG9hZEV4ZWN1dG9yAAQHJG1hdGNoMAkAoggBBQxLRVlfRVhFQ1VUT1IDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBBQFhCQEHQWRkcmVzcwEBAAENX3NhdmVFeGVjdXRvcgEJZXhlY3V0b3JfCQDMCAIJAQtTdHJpbmdFbnRyeQIFDEtFWV9FWEVDVVRPUgkApQgBBQlleGVjdXRvcl8FA25pbAETX2xvYWRBY2NvdW50U3RvcmFnZQAEByRtYXRjaDAJAKIIAQUTS0VZX0FDQ09VTlRfU1RPUkFHRQMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAWEJAQdBZGRyZXNzAQEAARNfc2F2ZUFjY291bnRTdG9yYWdlAQ9hY2NvdW50U3RvcmFnZV8JAMwIAgkBC1N0cmluZ0VudHJ5AgUTS0VZX0FDQ09VTlRfU1RPUkFHRQkApQgBBQ9hY2NvdW50U3RvcmFnZV8FA25pbAEPX2xvYWRXYXZlc1ZhdWx0AAQHJG1hdGNoMAkAoggBBQ9LRVlfV0FWRVNfVkFVTFQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBBQFhCQEHQWRkcmVzcwEBAAEPX3NhdmVXYXZlc1ZhdWx0AQt3YXZlc1ZhdWx0XwkAzAgCCQELU3RyaW5nRW50cnkCBQ9LRVlfV0FWRVNfVkFVTFQJAKUIAQULd2F2ZXNWYXVsdF8FA25pbAEKX2xvYWRDaGFpbgEIY2hhaW5JZF8EByRtYXRjaDAJAKIIAQkAuQkCCQDMCAIFCUtFWV9DSEFJTgkAzAgCCQCkAwEFCGNoYWluSWRfBQNuaWwFCVNFUEFSQVRPUgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAFAWECAAEKX3NhdmVDaGFpbgIIY2hhaW5JZF8FbmFtZV8JAMwIAgkBC1N0cmluZ0VudHJ5AgkAuQkCCQDMCAIFCUtFWV9DSEFJTgkAzAgCCQCkAwEFCGNoYWluSWRfBQNuaWwFCVNFUEFSQVRPUgUFbmFtZV8FA25pbAESX2xvYWRBc3NldEN1cnJlbmN5AghjaGFpbklkXwZhc3NldF8EByRtYXRjaDAJAKIIAQkAuQkCCQDMCAIFEktFWV9BU1NFVF9DVVJSRU5DWQkAzAgCCQCkAwEFCGNoYWluSWRfCQDMCAIFBmFzc2V0XwUDbmlsBQlTRVBBUkFUT1IDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwBQFhAgABEl9zYXZlQXNzZXRDdXJyZW5jeQMIY2hhaW5JZF8GYXNzZXRfCWN1cnJlbmN5XwkAzAgCCQELU3RyaW5nRW50cnkCCQC5CQIJAMwIAgUSS0VZX0FTU0VUX0NVUlJFTkNZCQDMCAIJAKQDAQUIY2hhaW5JZF8JAMwIAgUGYXNzZXRfBQNuaWwFCVNFUEFSQVRPUgUJY3VycmVuY3lfBQNuaWwBEl9sb2FkQXNzZXRSZXNlcnZlcwIIY2hhaW5JZF8GYXNzZXRfBAckbWF0Y2gwCQCiCAEJALkJAgkAzAgCBRJLRVlfQVNTRVRfUkVTRVJWRVMJAMwIAgkApAMBBQhjaGFpbklkXwkAzAgCBQZhc3NldF8FA25pbAUJU0VQQVJBVE9SAwkAAQIFByRtYXRjaDACBlN0cmluZwQBYQUHJG1hdGNoMAkApwMBBQFhBQtaRVJPX0JJR0lOVAESX3NhdmVBc3NldFJlc2VydmVzAwhjaGFpbklkXwZhc3NldF8JcmVzZXJ2ZXNfCQDMCAIJAQtTdHJpbmdFbnRyeQIJALkJAgkAzAgCBRJLRVlfQVNTRVRfUkVTRVJWRVMJAMwIAgkApAMBBQhjaGFpbklkXwkAzAgCBQZhc3NldF8FA25pbAUJU0VQQVJBVE9SCQCmAwEFCXJlc2VydmVzXwUDbmlsARhfbG9hZEFzc2V0UmVzZXJ2ZXNMb2NrZWQCCGNoYWluSWRfBmFzc2V0XwQHJG1hdGNoMAkAoggBCQC5CQIJAMwIAgUZS0VZX0FTU0VUX1JFU0VSVkVTX0xPQ0tFRAkAzAgCCQCkAwEFCGNoYWluSWRfCQDMCAIFBmFzc2V0XwUDbmlsBQlTRVBBUkFUT1IDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwCQCnAwEFAWEFC1pFUk9fQklHSU5UARhfc2F2ZUFzc2V0UmVzZXJ2ZXNMb2NrZWQDCGNoYWluSWRfBmFzc2V0XwlyZXNlcnZlc18JAMwIAgkBC1N0cmluZ0VudHJ5AgkAuQkCCQDMCAIFGUtFWV9BU1NFVF9SRVNFUlZFU19MT0NLRUQJAMwIAgkApAMBBQhjaGFpbklkXwkAzAgCBQZhc3NldF8FA25pbAUJU0VQQVJBVE9SCQCmAwEFCXJlc2VydmVzXwUDbmlsARdfbG9hZFVzZXJMb2NrZWRDdXJyZW5jeQIJY3VycmVuY3lfBXVzZXJfBAckbWF0Y2gwCQCiCAEJALkJAgkAzAgCBRhLRVlfVVNFUl9MT0NLRURfQ1VSUkVOQ1kJAMwIAgUJY3VycmVuY3lfCQDMCAIFBXVzZXJfBQNuaWwFCVNFUEFSQVRPUgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAJAKcDAQUBYQULWkVST19CSUdJTlQBF19zYXZlVXNlckxvY2tlZEN1cnJlbmN5AwljdXJyZW5jeV8FdXNlcl8HYW1vdW50XwkAzAgCCQELU3RyaW5nRW50cnkCCQC5CQIJAMwIAgUYS0VZX1VTRVJfTE9DS0VEX0NVUlJFTkNZCQDMCAIFCWN1cnJlbmN5XwkAzAgCBQV1c2VyXwUDbmlsBQlTRVBBUkFUT1IJAKYDAQUHYW1vdW50XwUDbmlsARVfbG9hZEN1cnJlbmN5UmVzZXJ2ZXMBCWN1cnJlbmN5XwQHJG1hdGNoMAkAoggBCQC5CQIJAMwIAgUVS0VZX0NVUlJFTkNZX1JFU0VSVkVTCQDMCAIFCWN1cnJlbmN5XwUDbmlsBQlTRVBBUkFUT1IDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwCQCnAwEFAWEFC1pFUk9fQklHSU5UARVfc2F2ZUN1cnJlbmN5UmVzZXJ2ZXMCCWN1cnJlbmN5XwlyZXNlcnZlc18JAMwIAgkBC1N0cmluZ0VudHJ5AgkAuQkCCQDMCAIFFUtFWV9DVVJSRU5DWV9SRVNFUlZFUwkAzAgCBQljdXJyZW5jeV8FA25pbAUJU0VQQVJBVE9SCQCmAwEFCXJlc2VydmVzXwUDbmlsARpfbG9hZFJlcXVlc3RXaXRoZHJhd2FsU2l6ZQAEByRtYXRjaDAJAJ8IAQUbS0VZX1JFUVVFU1RfV0lUSERSQVdBTF9TSVpFAwkAAQIFByRtYXRjaDACA0ludAQBYQUHJG1hdGNoMAUBYQAAARpfc2F2ZVJlcXVlc3RXaXRoZHJhd2FsU2l6ZQEEdmFsXwkAzAgCCQEMSW50ZWdlckVudHJ5AgUbS0VZX1JFUVVFU1RfV0lUSERSQVdBTF9TSVpFBQR2YWxfBQNuaWwBFl9sb2FkUmVxdWVzdFdpdGhkcmF3YWwBBmluZGV4XwQHJG1hdGNoMAkAoggBCQC5CQIJAMwIAgUWS0VZX1JFUVVFU1RfV0lUSERSQVdBTAkAzAgCCQCkAwEFBmluZGV4XwUDbmlsBQlTRVBBUkFUT1IDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwBAZzdHJ1Y3QJALUJAgUBYQUJU0VQQVJBVE9SCQCaCggJAJEDAgUGc3RydWN0AAAJAJEDAgUGc3RydWN0AAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZzdHJ1Y3QAAgkAkQMCBQZzdHJ1Y3QAAwkApwMBCQCRAwIFBnN0cnVjdAAECQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGc3RydWN0AAUJAJEDAgUGc3RydWN0AAYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZzdHJ1Y3QABwkAmgoIAgACAAAAAgAFC1pFUk9fQklHSU5UAAACAAUWUkVRVUVTVF9TVEFUVVNfQ1JFQVRFRAEWX3NhdmVSZXF1ZXN0V2l0aGRyYXdhbAIGaW5kZXhfCHJlcXVlc3RfCQDMCAIJAQtTdHJpbmdFbnRyeQIJALkJAgkAzAgCBRZLRVlfUkVRVUVTVF9XSVRIRFJBV0FMCQDMCAIJAKQDAQUGaW5kZXhfBQNuaWwFCVNFUEFSQVRPUgkAuQkCCQDMCAIIBQhyZXF1ZXN0XwJfMQkAzAgCCAUIcmVxdWVzdF8CXzIJAMwIAgkApAMBCAUIcmVxdWVzdF8CXzMJAMwIAggFCHJlcXVlc3RfAl80CQDMCAIJAKYDAQgFCHJlcXVlc3RfAl81CQDMCAIJAKQDAQgFCHJlcXVlc3RfAl82CQDMCAIIBQhyZXF1ZXN0XwJfNwkAzAgCCQCkAwEIBQhyZXF1ZXN0XwJfOAUDbmlsBQlTRVBBUkFUT1IFA25pbAEgX2xvYWRSZXF1ZXN0V2l0aGRyYXdhbEJsb2NrRGVsYXkABAckbWF0Y2gwCQCfCAEFIktFWV9SRVFVRVNUX1dJVEhEUkFXQUxfQkxPQ0tfREVMQVkDCQABAgUHJG1hdGNoMAIDSW50BAFhBQckbWF0Y2gwBQFhAAABIF9zYXZlUmVxdWVzdFdpdGhkcmF3YWxCbG9ja0RlbGF5AQZkZWxheV8JAMwIAgkBDEludGVnZXJFbnRyeQIFIktFWV9SRVFVRVNUX1dJVEhEUkFXQUxfQkxPQ0tfREVMQVkFBmRlbGF5XwUDbmlsAQ5fbG9hZFNlcXVlbmNlcgAEByRtYXRjaDAJAKIIAQUNS0VZX1NFUVVFTkNFUgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAWEJAQdBZGRyZXNzAQEAAQ5fc2F2ZVNlcXVlbmNlcgEKc2VxdWVuY2VyXwkAzAgCCQELU3RyaW5nRW50cnkCBQ1LRVlfU0VRVUVOQ0VSCQClCAEFCnNlcXVlbmNlcl8FA25pbAETX2xvYWRXaXRoZHJhd2FsSGFzaAEPd2l0aGRyYXdhbEhhc2hfBAckbWF0Y2gwCQCiCAEJALkJAgkAzAgCBRNLRVlfV0lUSERSQVdBTF9IQVNICQDMCAIJANgEAQUPd2l0aGRyYXdhbEhhc2hfBQNuaWwFCVNFUEFSQVRPUgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAFAWECAAETX3NhdmVXaXRoZHJhd2FsSGFzaAIPd2l0aGRyYXdhbEhhc2hfBXR4SWRfCQDMCAIJAQtTdHJpbmdFbnRyeQIJALkJAgkAzAgCBRNLRVlfV0lUSERSQVdBTF9IQVNICQDMCAIJANgEAQUPd2l0aGRyYXdhbEhhc2hfBQNuaWwFCVNFUEFSQVRPUgUFdHhJZF8FA25pbAERX2xvYWRWYXVsdEFkYXB0ZXIABAckbWF0Y2gwCQCiCAEFEUtFWV9WQVVMVF9BREFQVEVSAwkAAQIFByRtYXRjaDACBlN0cmluZwQBYQUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQUBYQkBB0FkZHJlc3MBAQABEV9zYXZlVmF1bHRBZGFwdGVyAQ12YXVsdEFkYXB0ZXJfCQDMCAIJAQtTdHJpbmdFbnRyeQIFEUtFWV9WQVVMVF9BREFQVEVSCQClCAEFDXZhdWx0QWRhcHRlcl8FA25pbAEWX2xvYWRSZXdhcmREaXN0cmlidXRvcgAEByRtYXRjaDAJAKIIAQUWS0VZX1JFV0FSRF9ESVNUUklCVVRPUgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAFAWECAAEWX3NhdmVSZXdhcmREaXN0cmlidXRvcgEMZGlzdHJpYnV0b3JfCQDMCAIJAQtTdHJpbmdFbnRyeQIFFktFWV9SRVdBUkRfRElTVFJJQlVUT1IFDGRpc3RyaWJ1dG9yXwUDbmlsARhfbG9hZFJlbGF5ZXJGZWVSZWNpcGllbnQABAckbWF0Y2gwCQCiCAEFGUtFWV9SRUxBWUVSX0ZFRV9SRUNJUElFTlQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwBQFhAgABGF9zYXZlUmVsYXllckZlZVJlY2lwaWVudAEUcmVsYXllckZlZVJlY2lwaWVudF8JAMwIAgkBC1N0cmluZ0VudHJ5AgUZS0VZX1JFTEFZRVJfRkVFX1JFQ0lQSUVOVAUUcmVsYXllckZlZVJlY2lwaWVudF8FA25pbAERX29ubHlUaGlzQ29udHJhY3QBB2NhbGxlcl8DCQECIT0CBQdjYWxsZXJfBQR0aGlzCQACAQIZX29ubHlUaGlzQ29udHJhY3Q6IHJldmVydAYBEF93aGVuTXVsdGlzaWdTZXQAAwkAAAIJAQ1fbG9hZE11bHRpc2lnAAkBB0FkZHJlc3MBAQAJAAIBAhhfd2hlbk11bHRpc2lnU2V0OiByZXZlcnQGARNfd2hlbk5vdEluaXRpYWxpemVkAAMJAQlfbG9hZEluaXQACQACAQIbX3doZW5Ob3RJbml0aWFsaXplZDogcmV2ZXJ0BgEQX3doZW5Jbml0aWFsaXplZAADCQEBIQEJAQlfbG9hZEluaXQACQACAQIYX3doZW5Jbml0aWFsaXplZDogcmV2ZXJ0BgEOX3doZW5Ob3RQYXVzZWQAAwkBCl9sb2FkUGF1c2UACQACAQIWX3doZW5Ob3RQYXVzZWQ6IHJldmVydAYBC193aGVuUGF1c2VkAAMJAQEhAQkBCl9sb2FkUGF1c2UACQACAQITX3doZW5QYXVzZWQ6IHJldmVydAYBC19vbmx5UGF1c2VyAQdjYWxsZXJfAwkBAiE9AgUHY2FsbGVyXwkBC19sb2FkUGF1c2VyAAkAAgECE19vbmx5UGF1c2VyOiByZXZlcnQGARFfdmFsaWRhdGVFeGVjdXRvcgIEdmFsXwRlcnJfAwkBAiE9AgUEdmFsXwkBDV9sb2FkRXhlY3V0b3IACQACAQUEZXJyXwYBF192YWxpZGF0ZUNhbGxlckNvbnRyYWN0AwhjaGFpbklkXw9jYWxsZXJDb250cmFjdF8EZXJyXwMJAQIhPQIJARNfbG9hZENhbGxlckNvbnRyYWN0AQUIY2hhaW5JZF8FD2NhbGxlckNvbnRyYWN0XwkAAgEFBGVycl8GAQxfY2hhaW5FeGlzdHMCCGNoYWluSWRfBGVycl8DCQBnAgAACQCxAgEJAQpfbG9hZENoYWluAQUIY2hhaW5JZF8JAAIBBQRlcnJfBgEOX2NoYWluTm90RXhpc3QCCGNoYWluSWRfBGVycl8DCQBmAgkAsQIBCQEKX2xvYWRDaGFpbgEFCGNoYWluSWRfAAAJAAIBBQRlcnJfBgEUX2Fzc2V0Q3VycmVuY3lFeGlzdHMDCGNoYWluSWRfBmFzc2V0XwRlcnJfAwkAZwIAAAkAsQIBCQESX2xvYWRBc3NldEN1cnJlbmN5AgUIY2hhaW5JZF8FBmFzc2V0XwkAAgEFBGVycl8GARZfYXNzZXRDdXJyZW5jeU5vdEV4aXN0AwhjaGFpbklkXwZhc3NldF8EZXJyXwMJAGYCCQCxAgEJARJfbG9hZEFzc2V0Q3VycmVuY3kCBQhjaGFpbklkXwUGYXNzZXRfAAAJAAIBBQRlcnJfBgETX3ZhbGlkYXRlV2F2ZXNWYXVsdAIGY2FsbGVyBGVycl8DCQECIT0CCQEPX2xvYWRXYXZlc1ZhdWx0AAUGY2FsbGVyCQACAQUEZXJyXwYBEV9yZXF1ZXN0SXNDcmVhdGVkAgdzdGF0dXNfBGVycl8DCQECIT0CBQdzdGF0dXNfBRZSRVFVRVNUX1NUQVRVU19DUkVBVEVECQACAQUEZXJyXwYBEl92YWxpZGF0ZVNlcXVlbmNlcgIGY2FsbGVyBGVycl8DCQECIT0CCQEOX2xvYWRTZXF1ZW5jZXIABQZjYWxsZXIJAAIBBQRlcnJfBgEcX2NoZWNrV2l0aGRyYXdhbEhhc2hOb3RFeGlzdAIPd2l0aGRyYXdhbEhhc2hfBGVycl8DCQBmAgkAsQIBCQETX2xvYWRXaXRoZHJhd2FsSGFzaAEFD3dpdGhkcmF3YWxIYXNoXwAACQACAQUEZXJyXwYBGF92YWxpZGF0ZVNpZ25hdHVyZUZvcm1hdAMKc2lnbmF0dXJlXwRhbGdfBGVycl8DCQAAAgUEYWxnXwUOQUxHX1RZUEVfV0FWRVMDCQECIT0CCQDIAQEFCnNpZ25hdHVyZV8AQAkAAgEFBGVycl8GAwkAAAIFBGFsZ18FDEFMR19UWVBFX0VWTQMJAQIhPQIJAMgBAQUKc2lnbmF0dXJlXwBBCQACAQUEZXJyXwYJAAIBCQCsAgIFBGVycl8CCTogaW52IGFsZwEPX3ZhbGlkYXRlV2ViM0lkAwd3ZWIzSWRfBGFsZ18EZXJyXwMJAAACBQRhbGdfBQ5BTEdfVFlQRV9XQVZFUwMJAQIhPQIJAMgBAQUHd2ViM0lkXwAgCQACAQUEZXJyXwYDCQAAAgUEYWxnXwUMQUxHX1RZUEVfRVZNAwkBAiE9AgkAyAEBBQd3ZWIzSWRfABQJAAIBBQRlcnJfBgkAAgEJAKwCAgUEZXJyXwIJOiBpbnYgYWxnARxfdmFsaWRhdGVXaXRoZHJhd2FsU2lnbmF0dXJlBQ93aXRoZHJhd2FsSGFzaF8Kc2lnbmF0dXJlXwd3ZWIzSWRfBGFsZ18EZXJyXwQGcmVzdWx0AwkAAAIFBGFsZ18FDkFMR19UWVBFX1dBVkVTBA5oYXNoV2l0aFByZWZpeAkAjBUBCQDLAQIFDFdBVkVTX1BSRUZJWAkAmwMBCQDYBAEFD3dpdGhkcmF3YWxIYXNoXwkA9AMDBQ5oYXNoV2l0aFByZWZpeAUKc2lnbmF0dXJlXwUHd2ViM0lkXwMJAAACBQRhbGdfBQxBTEdfVFlQRV9FVk0EDmhhc2hXaXRoUHJlZml4CQCMFQEJAMsBAgUURVZNX1NJR05BVFVSRV9QUkVGSVgFD3dpdGhkcmF3YWxIYXNoXwkAAAIJAMwBAgkAjBUBCQCEBwIFDmhhc2hXaXRoUHJlZml4BQpzaWduYXR1cmVfABQFB3dlYjNJZF8JAAIBCQCsAgIFBGVycl8CCTogaW52IGFsZwMJAQEhAQUGcmVzdWx0CQACAQUEZXJyXwYBHV92YWxpZGF0ZVdlYjNJZE1hdGNoZXNBZGRyZXNzBAd3ZWIzSWRfBWZyb21fBGFsZ18EZXJyXwQHYWRkcmVzcwMJAAACBQRhbGdfBQ5BTEdfVFlQRV9XQVZFUwkApQgBCQCnCAEFB3dlYjNJZF8DCQAAAgUEYWxnXwUMQUxHX1RZUEVfRVZNCQCsAgICAjB4CQDcBAEFB3dlYjNJZF8JAAIBCQCsAgIFBGVycl8CCTogaW52IGFsZwMJAQIhPQIFB2FkZHJlc3MFBWZyb21fCQACAQUEZXJyXwYQAWkBBGluaXQGCWV4ZWN1dG9yXwdwYXVzZXJfD2FjY291bnRTdG9yYWdlXwt3YXZlc1ZhdWx0XwpzZXF1ZW5jZXJfDXZhdWx0QWRhcHRlcl8EA2VycgMDAwMDAwMDCQERX29ubHlUaGlzQ29udHJhY3QBCAUBaQZjYWxsZXIJARNfd2hlbk5vdEluaXRpYWxpemVkAAcJARBfd2hlbk11bHRpc2lnU2V0AAcJARBfdmFsaWRhdGVBZGRyZXNzAgUJZXhlY3V0b3JfAhZpbml0OiBpbnZhbGlkIGV4ZWN1dG9yBwkBEF92YWxpZGF0ZUFkZHJlc3MCBQdwYXVzZXJfAhRpbml0OiBpbnZhbGlkIHBhdXNlcgcJARBfdmFsaWRhdGVBZGRyZXNzAgUPYWNjb3VudFN0b3JhZ2VfAhxpbml0OiBpbnZhbGlkIGFjY291bnRTdG9yYWdlBwkBEF92YWxpZGF0ZUFkZHJlc3MCBQt3YXZlc1ZhdWx0XwIYaW5pdDogaW52YWxpZCB3YXZlc1ZhdWx0BwkBEF92YWxpZGF0ZUFkZHJlc3MCBQpzZXF1ZW5jZXJfAhdpbml0OiBpbnZhbGlkIHNlcXVlbmNlcgcJARBfdmFsaWRhdGVBZGRyZXNzAgUNdmF1bHRBZGFwdGVyXwIaaW5pdDogaW52YWxpZCB2YXVsdEFkYXB0ZXIHAwkAAAIFA2VycgUDZXJyCQCUCgIJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAQlfc2F2ZUluaXQBBgkBDV9zYXZlRXhlY3V0b3IBCQERQGV4dHJOYXRpdmUoMTA2MikBBQlleGVjdXRvcl8JAQtfc2F2ZVBhdXNlcgEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB3BhdXNlcl8JARNfc2F2ZUFjY291bnRTdG9yYWdlAQkBEUBleHRyTmF0aXZlKDEwNjIpAQUPYWNjb3VudFN0b3JhZ2VfCQEPX3NhdmVXYXZlc1ZhdWx0AQkBEUBleHRyTmF0aXZlKDEwNjIpAQULd2F2ZXNWYXVsdF8JAQ5fc2F2ZVNlcXVlbmNlcgEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCnNlcXVlbmNlcl8JARFfc2F2ZVZhdWx0QWRhcHRlcgEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDXZhdWx0QWRhcHRlcl8FBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHZGVwb3NpdAYPY2FsbGVyQ29udHJhY3RfBWZyb21fA3RvXwhjaGFpbklkXwZhc3NldF8HYW1vdW50XwQHY2hhaW5JZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFCGNoYWluSWRfAhhkZXBvc2l0OiBjaGFpbklkIG5vdCBpbnQEBmFtb3VudAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCoAwEFB2Ftb3VudF8CF2RlcG9zaXQ6IGFtb3VudCBub3QgaW50BANlcnIDAwMDAwMJARBfd2hlbkluaXRpYWxpemVkAAkBDl93aGVuTm90UGF1c2VkAAcJAQxfY2hhaW5FeGlzdHMCBQdjaGFpbklkAhhkZXBvc2l0OiBpbnZhbGlkIGNoYWluSWQHCQEPX3ZhbGlkYXRlU3RyaW5nAgUFZnJvbV8CFWRlcG9zaXQ6IGludmFsaWQgZnJvbQcJAQ9fdmFsaWRhdGVTdHJpbmcCBQN0b18CE2RlcG9zaXQ6IGludmFsaWQgdG8HCQEUX2Fzc2V0Q3VycmVuY3lFeGlzdHMDBQdjaGFpbklkBQZhc3NldF8CFmRlcG9zaXQ6IGludmFsaWQgYXNzZXQHCQEPX3ZhbGlkYXRlQmlnSW50AwUGYW1vdW50BQtaRVJPX0JJR0lOVAIXZGVwb3NpdDogaW52YWxpZCBhbW91bnQHAwkAAAIFA2VycgUDZXJyBARlcnIxAwkAAAIJAQpfbG9hZENoYWluAQUHY2hhaW5JZAUFV0FWRVMJARNfdmFsaWRhdGVXYXZlc1ZhdWx0AggFAWkGY2FsbGVyAhxkZXBvc2l0OiBpbnZhbGlkIHdhdmVzIHZhdWx0AwkBEV92YWxpZGF0ZUV4ZWN1dG9yAggFAWkGY2FsbGVyAhlkZXBvc2l0OiBpbnZhbGlkIGV4ZWN1dG9yCQEXX3ZhbGlkYXRlQ2FsbGVyQ29udHJhY3QDBQdjaGFpbklkBQ9jYWxsZXJDb250cmFjdF8CIGRlcG9zaXQ6IGludmFsaWQgY2FsbGVyIGNvbnRyYWN0BwMJAAACBQRlcnIxBQRlcnIxBBBuZXdBc3NldFJlc2VydmVzCQC3AgIJARJfbG9hZEFzc2V0UmVzZXJ2ZXMCBQdjaGFpbklkBQZhc3NldF8FBmFtb3VudAQIY3VycmVuY3kJARJfbG9hZEFzc2V0Q3VycmVuY3kCBQdjaGFpbklkBQZhc3NldF8EE25ld0N1cnJlbmN5UmVzZXJ2ZXMJALcCAgkBFV9sb2FkQ3VycmVuY3lSZXNlcnZlcwEFCGN1cnJlbmN5BQZhbW91bnQECmludm9jYXRpb24JAPwHBAkBE19sb2FkQWNjb3VudFN0b3JhZ2UABQxGVU5DX0RFUE9TSVQJAMwIAgUDdG9fCQDMCAIFCGN1cnJlbmN5CQDMCAIFB2Ftb3VudF8FA25pbAUDbmlsAwkAAAIFCmludm9jYXRpb24FCmludm9jYXRpb24JAJQKAgkAzggCCQESX3NhdmVBc3NldFJlc2VydmVzAwUHY2hhaW5JZAUGYXNzZXRfBRBuZXdBc3NldFJlc2VydmVzCQEVX3NhdmVDdXJyZW5jeVJlc2VydmVzAgUIY3VycmVuY3kFE25ld0N1cnJlbmN5UmVzZXJ2ZXMFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERcmVxdWVzdFdpdGhkcmF3YWwHD2NhbGxlckNvbnRyYWN0XwVmcm9tXwN0b18MZnJvbUNoYWluSWRfCnRvQ2hhaW5JZF8GYXNzZXRfB2Ftb3VudF8EC2Zyb21DaGFpbklkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQUMZnJvbUNoYWluSWRfAiZyZXF1ZXN0V2l0aGRyYXdhbDogZnJvbUNoYWluSWQgbm90IGludAQJdG9DaGFpbklkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQUKdG9DaGFpbklkXwIkcmVxdWVzdFdpdGhkcmF3YWw6IHRvQ2hhaW5JZCBub3QgaW50BAZhbW91bnQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAqAMBBQdhbW91bnRfAiFyZXF1ZXN0V2l0aGRyYXdhbDogYW1vdW50IG5vdCBpbnQEA2VycgMDAwMDAwkBEF93aGVuSW5pdGlhbGl6ZWQACQEMX2NoYWluRXhpc3RzAgULZnJvbUNoYWluSWQCJnJlcXVlc3RXaXRoZHJhd2FsOiBpbnZhbGlkIGZyb21DaGFpbklkBwkBDF9jaGFpbkV4aXN0cwIFCXRvQ2hhaW5JZAIkcmVxdWVzdFdpdGhkcmF3YWw6IGludmFsaWQgdG9DaGFpbklkBwkBD192YWxpZGF0ZVN0cmluZwIFBWZyb21fAh9yZXF1ZXN0V2l0aGRyYXdhbDogaW52YWxpZCBmcm9tBwkBD192YWxpZGF0ZVN0cmluZwIFA3RvXwIdcmVxdWVzdFdpdGhkcmF3YWw6IGludmFsaWQgdG8HCQEUX2Fzc2V0Q3VycmVuY3lFeGlzdHMDBQl0b0NoYWluSWQFBmFzc2V0XwIgcmVxdWVzdFdpdGhkcmF3YWw6IGludmFsaWQgYXNzZXQHCQEPX3ZhbGlkYXRlQmlnSW50AwUGYW1vdW50BQtaRVJPX0JJR0lOVAIhcmVxdWVzdFdpdGhkcmF3YWw6IGludmFsaWQgYW1vdW50BwMJAAACBQNlcnIFA2VycgQEZXJyMQMJAAACCQEKX2xvYWRDaGFpbgEFC2Zyb21DaGFpbklkBQVXQVZFUwkBE192YWxpZGF0ZVdhdmVzVmF1bHQCCAUBaQZjYWxsZXICJnJlcXVlc3RXaXRoZHJhd2FsOiBpbnZhbGlkIHdhdmVzIHZhdWx0AwkBEV92YWxpZGF0ZUV4ZWN1dG9yAggFAWkGY2FsbGVyAiNyZXF1ZXN0V2l0aGRyYXdhbDogaW52YWxpZCBleGVjdXRvcgkBF192YWxpZGF0ZUNhbGxlckNvbnRyYWN0AwULZnJvbUNoYWluSWQFD2NhbGxlckNvbnRyYWN0XwIqcmVxdWVzdFdpdGhkcmF3YWw6IGludmFsaWQgY2FsbGVyIGNvbnRyYWN0BwMJAAACBQRlcnIxBQRlcnIxBAhjdXJyZW5jeQkBEl9sb2FkQXNzZXRDdXJyZW5jeQIFCXRvQ2hhaW5JZAUGYXNzZXRfBBBhdmFpbGFibGVCYWxhbmNlBAckbWF0Y2gwCQD8BwQJARNfbG9hZEFjY291bnRTdG9yYWdlAAUVRlVOQ19HRVRfVVNFUl9CQUxBTkNFCQDMCAIFBWZyb21fCQDMCAIFC1NQT1RfV0FMTEVUCQDMCAIFCGN1cnJlbmN5BQNuaWwFA25pbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAJAKcDAQUBYQkAAgECPHJlcXVlc3RXaXRoZHJhd2FsOiBjYW4ndCB0YWtlIGF2YWlsYWJsZSBiYWxhbmNlIGZyb20gc3RvcmFnZQMJAAACBRBhdmFpbGFibGVCYWxhbmNlBRBhdmFpbGFibGVCYWxhbmNlBA5sb2NrZWRSZXNlcnZlcwkBGF9sb2FkQXNzZXRSZXNlcnZlc0xvY2tlZAIFCXRvQ2hhaW5JZAUGYXNzZXRfBBJ1c2VyTG9ja2VkQ3VycmVuY3kJARdfbG9hZFVzZXJMb2NrZWRDdXJyZW5jeQIFCGN1cnJlbmN5BQVmcm9tXwQNJHQwMTk0MzcxOTg5MgMDCQDAAgIJALgCAgUQYXZhaWxhYmxlQmFsYW5jZQUSdXNlckxvY2tlZEN1cnJlbmN5BQZhbW91bnQJAMACAgkAuAICCQESX2xvYWRBc3NldFJlc2VydmVzAgUJdG9DaGFpbklkBQZhc3NldF8FDmxvY2tlZFJlc2VydmVzBQZhbW91bnQHCQCUCgIFFlJFUVVFU1RfU1RBVFVTX0NSRUFURUQJAM4IAgkBGF9zYXZlQXNzZXRSZXNlcnZlc0xvY2tlZAMFCXRvQ2hhaW5JZAUGYXNzZXRfCQC3AgIFDmxvY2tlZFJlc2VydmVzBQZhbW91bnQJARdfc2F2ZVVzZXJMb2NrZWRDdXJyZW5jeQMFCGN1cnJlbmN5BQVmcm9tXwkAtwICBQZhbW91bnQFEnVzZXJMb2NrZWRDdXJyZW5jeQkAlAoCBRdSRVFVRVNUX1NUQVRVU19SRUpFQ1RFRAUDbmlsBA1yZXF1ZXN0U3RhdHVzCAUNJHQwMTk0MzcxOTg5MgJfMQQPcmVzZXJ2ZXNBY3Rpb25zCAUNJHQwMTk0MzcxOTg5MgJfMgQVcmVxdWVzdFdpdGhkcmF3YWxTaXplCQEaX2xvYWRSZXF1ZXN0V2l0aGRyYXdhbFNpemUABBFyZXF1ZXN0V2l0aGRyYXdhbAkAmgoIBQVmcm9tXwUDdG9fBQl0b0NoYWluSWQFBmFzc2V0XwUGYW1vdW50BQZoZWlnaHQJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAUNcmVxdWVzdFN0YXR1cwkAlAoCCQDOCAIJAM4IAgkBFl9zYXZlUmVxdWVzdFdpdGhkcmF3YWwCBRVyZXF1ZXN0V2l0aGRyYXdhbFNpemUFEXJlcXVlc3RXaXRoZHJhd2FsCQEaX3NhdmVSZXF1ZXN0V2l0aGRyYXdhbFNpemUBCQBkAgUVcmVxdWVzdFdpdGhkcmF3YWxTaXplAAEFD3Jlc2VydmVzQWN0aW9ucwUVcmVxdWVzdFdpdGhkcmF3YWxTaXplCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEWV4ZWN1dGVXaXRoZHJhd2FsAw9jYWxsZXJDb250cmFjdF8IY2hhaW5JZF8UcmVxdWVzdFdpdGhkcmF3YWxJZF8EB2NoYWluSWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBBQhjaGFpbklkXwIiZXhlY3V0ZVdpdGhkcmF3YWw6IGNoYWluSWQgbm90IGludAQTcmVxdWVzdFdpdGhkcmF3YWxJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFFHJlcXVlc3RXaXRoZHJhd2FsSWRfAi5leGVjdXRlV2l0aGRyYXdhbDogcmVxdWVzdFdpdGhkcmF3YWxJZCBub3QgaW50BBVyZXF1ZXN0V2l0aGRyYXdhbFNpemUJARpfbG9hZFJlcXVlc3RXaXRoZHJhd2FsU2l6ZQAEA2VycgMDCQEQX3doZW5Jbml0aWFsaXplZAAJAQxfY2hhaW5FeGlzdHMCBQdjaGFpbklkAiJleGVjdXRlV2l0aGRyYXdhbDogaW52YWxpZCBjaGFpbklkBwkBDF92YWxpZGF0ZUludAQFE3JlcXVlc3RXaXRoZHJhd2FsSWQAAAkAZQIFFXJlcXVlc3RXaXRoZHJhd2FsU2l6ZQABAi5leGVjdXRlV2l0aGRyYXdhbDogaW52YWxpZCByZXF1ZXN0V2l0aGRyYXdhbElkBwMJAAACBQNlcnIFA2VycgQEZXJyMQMJAAACCQEKX2xvYWRDaGFpbgEFB2NoYWluSWQFBVdBVkVTCQETX3ZhbGlkYXRlV2F2ZXNWYXVsdAIIBQFpBmNhbGxlcgImZXhlY3V0ZVdpdGhkcmF3YWw6IGludmFsaWQgd2F2ZXMgdmF1bHQDCQERX3ZhbGlkYXRlRXhlY3V0b3ICCAUBaQZjYWxsZXICI2V4ZWN1dGVXaXRoZHJhd2FsOiBpbnZhbGlkIGV4ZWN1dG9yCQEXX3ZhbGlkYXRlQ2FsbGVyQ29udHJhY3QDBQdjaGFpbklkBQ9jYWxsZXJDb250cmFjdF8CKmV4ZWN1dGVXaXRoZHJhd2FsOiBpbnZhbGlkIGNhbGxlciBjb250cmFjdAcDCQAAAgUEZXJyMQUEZXJyMQQHcmVxdWVzdAkBFl9sb2FkUmVxdWVzdFdpdGhkcmF3YWwBBRNyZXF1ZXN0V2l0aGRyYXdhbElkBAtyZXF1ZXN0RnJvbQgFB3JlcXVlc3QCXzEECXJlcXVlc3RUbwgFB3JlcXVlc3QCXzIEEHJlcXVlc3RUb0NoYWluSWQIBQdyZXF1ZXN0Al8zBAxyZXF1ZXN0QXNzZXQIBQdyZXF1ZXN0Al80BA1yZXF1ZXN0QW1vdW50CAUHcmVxdWVzdAJfNQQNcmVxdWVzdEhlaWdodAgFB3JlcXVlc3QCXzYEDXJlcXVlc3RTdGF0dXMIBQdyZXF1ZXN0Al84BBBuZXdBc3NldFJlc2VydmVzCQC4AgIJARJfbG9hZEFzc2V0UmVzZXJ2ZXMCBRByZXF1ZXN0VG9DaGFpbklkBQxyZXF1ZXN0QXNzZXQFDXJlcXVlc3RBbW91bnQEFm5ld0Fzc2V0UmVzZXJ2ZXNMb2NrZWQJALgCAgkBGF9sb2FkQXNzZXRSZXNlcnZlc0xvY2tlZAIFEHJlcXVlc3RUb0NoYWluSWQFDHJlcXVlc3RBc3NldAUNcmVxdWVzdEFtb3VudAQIY3VycmVuY3kJARJfbG9hZEFzc2V0Q3VycmVuY3kCBRByZXF1ZXN0VG9DaGFpbklkBQxyZXF1ZXN0QXNzZXQEE25ld0N1cnJlbmN5UmVzZXJ2ZXMJALgCAgkBFV9sb2FkQ3VycmVuY3lSZXNlcnZlcwEFCGN1cnJlbmN5BQ1yZXF1ZXN0QW1vdW50BBVuZXdVc2VyTG9ja2VkQ3VycmVuY3kJALgCAgkBF19sb2FkVXNlckxvY2tlZEN1cnJlbmN5AgUIY3VycmVuY3kFC3JlcXVlc3RGcm9tBQ1yZXF1ZXN0QW1vdW50BARlcnIyAwMDAwMJAQ9fdmFsaWRhdGVCaWdJbnQDBRBuZXdBc3NldFJlc2VydmVzBQtaRVJPX0JJR0lOVAIsZXhlY3V0ZVdpdGhkcmF3YWw6IG5lZ2F0aXZlIG5ld0Fzc2V0UmVzZXJ2ZXMJAQ9fdmFsaWRhdGVCaWdJbnQDBRZuZXdBc3NldFJlc2VydmVzTG9ja2VkBQtaRVJPX0JJR0lOVAIyZXhlY3V0ZVdpdGhkcmF3YWw6IG5lZ2F0aXZlIG5ld0Fzc2V0UmVzZXJ2ZXNMb2NrZWQHCQEPX3ZhbGlkYXRlQmlnSW50AwUTbmV3Q3VycmVuY3lSZXNlcnZlcwULWkVST19CSUdJTlQCL2V4ZWN1dGVXaXRoZHJhd2FsOiBuZWdhdGl2ZSBuZXdDdXJyZW5jeVJlc2VydmVzBwkBD192YWxpZGF0ZUJpZ0ludAMFFW5ld1VzZXJMb2NrZWRDdXJyZW5jeQULWkVST19CSUdJTlQCMWV4ZWN1dGVXaXRoZHJhd2FsOiBuZWdhdGl2ZSBuZXdVc2VyTG9ja2VkQ3VycmVuY3kHCQEMX3ZhbGlkYXRlSW50BAkAZQIFBmhlaWdodAUNcmVxdWVzdEhlaWdodAkBIF9sb2FkUmVxdWVzdFdpdGhkcmF3YWxCbG9ja0RlbGF5AAUHTUFYX0lOVAInZXhlY3V0ZVdpdGhkcmF3YWw6IHRvbyBlYXJseSB0byBleGVjdXRlBwkBEV9yZXF1ZXN0SXNDcmVhdGVkAgUNcmVxdWVzdFN0YXR1cwImZXhlY3V0ZVdpdGhkcmF3YWw6IHJlcXVlc3QgaXMgcmVzb2x2ZWQHAwkAAAIFBGVycjIFBGVycjIEEXN0b3JhZ2VJbnZvY2F0aW9uCQD8BwQJARNfbG9hZEFjY291bnRTdG9yYWdlAAUNRlVOQ19XSVRIRFJBVwkAzAgCBQtyZXF1ZXN0RnJvbQkAzAgCBQhjdXJyZW5jeQkAzAgCCQCmAwEFDXJlcXVlc3RBbW91bnQFA25pbAUDbmlsAwkAAAIFEXN0b3JhZ2VJbnZvY2F0aW9uBRFzdG9yYWdlSW52b2NhdGlvbgQSd2l0aGRyYXdJbnZvY2F0aW9uAwkAAAIJAQpfbG9hZENoYWluAQUQcmVxdWVzdFRvQ2hhaW5JZAUFV0FWRVMJAPwHBAkBD19sb2FkV2F2ZXNWYXVsdAAFDUZVTkNfV0lUSERSQVcJAMwIAgUJcmVxdWVzdFRvCQDMCAIFDHJlcXVlc3RBc3NldAkAzAgCCQCmAwEFDXJlcXVlc3RBbW91bnQFA25pbAUDbmlsCQD8BwQJARFfbG9hZFZhdWx0QWRhcHRlcgAFDUZVTkNfV0lUSERSQVcJAMwIAgUQcmVxdWVzdFRvQ2hhaW5JZAkAzAgCBQxyZXF1ZXN0QXNzZXQJAMwIAgkApgMBBQ1yZXF1ZXN0QW1vdW50CQDMCAIFCXJlcXVlc3RUbwUDbmlsBQNuaWwDCQAAAgUSd2l0aGRyYXdJbnZvY2F0aW9uBRJ3aXRoZHJhd0ludm9jYXRpb24EDnJlcXVlc3RVcGRhdGVkCQCaCggIBQdyZXF1ZXN0Al8xCAUHcmVxdWVzdAJfMggFB3JlcXVlc3QCXzMIBQdyZXF1ZXN0Al80CAUHcmVxdWVzdAJfNQgFB3JlcXVlc3QCXzYIBQdyZXF1ZXN0Al83BRNSRVFVRVNUX1NUQVRVU19ET05FCQCUCgIJAM4IAgkAzggCCQDOCAIJAM4IAgkBEl9zYXZlQXNzZXRSZXNlcnZlcwMFEHJlcXVlc3RUb0NoYWluSWQFDHJlcXVlc3RBc3NldAUQbmV3QXNzZXRSZXNlcnZlcwkBGF9zYXZlQXNzZXRSZXNlcnZlc0xvY2tlZAMFEHJlcXVlc3RUb0NoYWluSWQFDHJlcXVlc3RBc3NldAUWbmV3QXNzZXRSZXNlcnZlc0xvY2tlZAkBFV9zYXZlQ3VycmVuY3lSZXNlcnZlcwIFCGN1cnJlbmN5BRNuZXdDdXJyZW5jeVJlc2VydmVzCQEXX3NhdmVVc2VyTG9ja2VkQ3VycmVuY3kDBQhjdXJyZW5jeQULcmVxdWVzdEZyb20FFW5ld1VzZXJMb2NrZWRDdXJyZW5jeQkBFl9zYXZlUmVxdWVzdFdpdGhkcmF3YWwCBRNyZXF1ZXN0V2l0aGRyYXdhbElkBQ5yZXF1ZXN0VXBkYXRlZAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARByZWplY3RXaXRoZHJhd2FsARRyZXF1ZXN0V2l0aGRyYXdhbElkXwQTcmVxdWVzdFdpdGhkcmF3YWxJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFFHJlcXVlc3RXaXRoZHJhd2FsSWRfAi1yZWplY3RXaXRoZHJhd2FsOiByZXF1ZXN0V2l0aGRyYXdhbElkIG5vdCBpbnQEFXJlcXVlc3RXaXRoZHJhd2FsU2l6ZQkBGl9sb2FkUmVxdWVzdFdpdGhkcmF3YWxTaXplAAQDZXJyAwMJARBfd2hlbkluaXRpYWxpemVkAAkBEl92YWxpZGF0ZVNlcXVlbmNlcgIIBQFpBmNhbGxlcgIjcmVqZWN0V2l0aGRyYXdhbDogaW52YWxpZCBzZXF1ZW5jZXIHCQEMX3ZhbGlkYXRlSW50BAUTcmVxdWVzdFdpdGhkcmF3YWxJZAAACQBlAgUVcmVxdWVzdFdpdGhkcmF3YWxTaXplAAECLXJlamVjdFdpdGhkcmF3YWw6IGludmFsaWQgcmVxdWVzdFdpdGhkcmF3YWxJZAcDCQAAAgUDZXJyBQNlcnIEB3JlcXVlc3QJARZfbG9hZFJlcXVlc3RXaXRoZHJhd2FsAQUTcmVxdWVzdFdpdGhkcmF3YWxJZAQLcmVxdWVzdEZyb20IBQdyZXF1ZXN0Al8xBAlyZXF1ZXN0VG8IBQdyZXF1ZXN0Al8yBBByZXF1ZXN0VG9DaGFpbklkCAUHcmVxdWVzdAJfMwQMcmVxdWVzdEFzc2V0CAUHcmVxdWVzdAJfNAQNcmVxdWVzdEFtb3VudAgFB3JlcXVlc3QCXzUEDXJlcXVlc3RIZWlnaHQIBQdyZXF1ZXN0Al82BA1yZXF1ZXN0U3RhdHVzCAUHcmVxdWVzdAJfOAQIY3VycmVuY3kJARJfbG9hZEFzc2V0Q3VycmVuY3kCBRByZXF1ZXN0VG9DaGFpbklkBQxyZXF1ZXN0QXNzZXQEFm5ld0Fzc2V0UmVzZXJ2ZXNMb2NrZWQJALgCAgkBGF9sb2FkQXNzZXRSZXNlcnZlc0xvY2tlZAIFEHJlcXVlc3RUb0NoYWluSWQFDHJlcXVlc3RBc3NldAUNcmVxdWVzdEFtb3VudAQVbmV3VXNlckxvY2tlZEN1cnJlbmN5CQC4AgIJARdfbG9hZFVzZXJMb2NrZWRDdXJyZW5jeQIFCGN1cnJlbmN5BQtyZXF1ZXN0RnJvbQUNcmVxdWVzdEFtb3VudAQEZXJyMQMDCQEPX3ZhbGlkYXRlQmlnSW50AwUWbmV3QXNzZXRSZXNlcnZlc0xvY2tlZAULWkVST19CSUdJTlQCMXJlamVjdFdpdGhkcmF3YWw6IG5lZ2F0aXZlIG5ld0Fzc2V0UmVzZXJ2ZXNMb2NrZWQJAQ9fdmFsaWRhdGVCaWdJbnQDBRVuZXdVc2VyTG9ja2VkQ3VycmVuY3kFC1pFUk9fQklHSU5UAjByZWplY3RXaXRoZHJhd2FsOiBuZWdhdGl2ZSBuZXdVc2VyTG9ja2VkQ3VycmVuY3kHCQERX3JlcXVlc3RJc0NyZWF0ZWQCBQ1yZXF1ZXN0U3RhdHVzAiVyZWplY3RXaXRoZHJhd2FsOiByZXF1ZXN0IGlzIHJlc29sdmVkBwMJAAACBQRlcnIxBQRlcnIxBBBhdmFpbGFibGVCYWxhbmNlBAckbWF0Y2gwCQD8BwQJARNfbG9hZEFjY291bnRTdG9yYWdlAAUVRlVOQ19HRVRfVVNFUl9CQUxBTkNFCQDMCAIFC3JlcXVlc3RGcm9tCQDMCAIFC1NQT1RfV0FMTEVUCQDMCAIFCGN1cnJlbmN5BQNuaWwFA25pbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAJAKcDAQUBYQkAAgECO3JlamVjdFdpdGhkcmF3YWw6IGNhbid0IHRha2UgYXZhaWxhYmxlIGJhbGFuY2UgZnJvbSBzdG9yYWdlAwkAAAIFEGF2YWlsYWJsZUJhbGFuY2UFEGF2YWlsYWJsZUJhbGFuY2UDCQC/AgIFDXJlcXVlc3RBbW91bnQFEGF2YWlsYWJsZUJhbGFuY2UEDnJlcXVlc3RVcGRhdGVkCQCaCggIBQdyZXF1ZXN0Al8xCAUHcmVxdWVzdAJfMggFB3JlcXVlc3QCXzMIBQdyZXF1ZXN0Al80CAUHcmVxdWVzdAJfNQgFB3JlcXVlc3QCXzYIBQdyZXF1ZXN0Al83BRdSRVFVRVNUX1NUQVRVU19SRUpFQ1RFRAkAlAoCCQDOCAIJAM4IAgkBGF9zYXZlQXNzZXRSZXNlcnZlc0xvY2tlZAMFEHJlcXVlc3RUb0NoYWluSWQFDHJlcXVlc3RBc3NldAUWbmV3QXNzZXRSZXNlcnZlc0xvY2tlZAkBF19zYXZlVXNlckxvY2tlZEN1cnJlbmN5AwUIY3VycmVuY3kFC3JlcXVlc3RGcm9tBRVuZXdVc2VyTG9ja2VkQ3VycmVuY3kJARZfc2F2ZVJlcXVlc3RXaXRoZHJhd2FsAgUTcmVxdWVzdFdpdGhkcmF3YWxJZAUOcmVxdWVzdFVwZGF0ZWQGCQCUCgIFA25pbAcJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEId2l0aGRyYXcKBWZyb21fA3RvXwp0b0NoYWluSWRfBmFzc2V0XwdhbW91bnRfC3JlbGF5ZXJGZWVfCnRpbWVzdGFtcF8Hd2ViM0lkXwRhbGdfCnNpZ25hdHVyZV8ECXRvQ2hhaW5JZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFCnRvQ2hhaW5JZF8CG3dpdGhkcmF3OiB0b0NoYWluSWQgbm90IGludAQGYW1vdW50CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKgDAQUHYW1vdW50XwIYd2l0aGRyYXc6IGFtb3VudCBub3QgaW50BApyZWxheWVyRmVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKgDAQULcmVsYXllckZlZV8CHHdpdGhkcmF3OiByZWxheWVyRmVlIG5vdCBpbnQECXRpbWVzdGFtcAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFCnRpbWVzdGFtcF8CG3dpdGhkcmF3OiB0aW1lc3RhbXAgbm90IGludAQDYWxnCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQUEYWxnXwIVd2l0aGRyYXc6IGFsZyBub3QgaW50BAZ3ZWIzSWQJANkEAQUHd2ViM0lkXwQJc2lnbmF0dXJlCQDZBAEFCnNpZ25hdHVyZV8EA2VycgMDAwMDAwMDAwMDCQEQX3doZW5Jbml0aWFsaXplZAAJARJfdmFsaWRhdGVTZXF1ZW5jZXICCAUBaQZjYWxsZXICG3dpdGhkcmF3OiBpbnZhbGlkIHNlcXVlbmNlcgcJAQ9fdmFsaWRhdGVTdHJpbmcCBQVmcm9tXwIWd2l0aGRyYXc6IGludmFsaWQgZnJvbQcJAQ9fdmFsaWRhdGVTdHJpbmcCBQN0b18CFHdpdGhkcmF3OiBpbnZhbGlkIHRvBwkBDF9jaGFpbkV4aXN0cwIFCXRvQ2hhaW5JZAIbd2l0aGRyYXc6IGludmFsaWQgdG9DaGFpbklkBwkBFF9hc3NldEN1cnJlbmN5RXhpc3RzAwUJdG9DaGFpbklkBQZhc3NldF8CF3dpdGhkcmF3OiBpbnZhbGlkIGFzc2V0BwkBD192YWxpZGF0ZUJpZ0ludAMFBmFtb3VudAULWkVST19CSUdJTlQCGHdpdGhkcmF3OiBpbnZhbGlkIGFtb3VudAcJARFfdmFsaWRhdGVCaWdJbnRfMgQFCnJlbGF5ZXJGZWUFC1pFUk9fQklHSU5UBQZhbW91bnQCHHdpdGhkcmF3OiBpbnZhbGlkIHJlbGF5ZXJGZWUHCQEMX3ZhbGlkYXRlSW50BAkAZAIFCXRpbWVzdGFtcAUHT05FX0RBWQgFCWxhc3RCbG9jawl0aW1lc3RhbXAFB01BWF9JTlQCG3dpdGhkcmF3OiBpbnZhbGlkIHRpbWVzdGFtcAcJAQ9fdmFsaWRhdGVXZWIzSWQDBQZ3ZWIzSWQFA2FsZwIUd2l0aGRyYXc6IGludiB3ZWIzSWQHCQEYX3ZhbGlkYXRlU2lnbmF0dXJlRm9ybWF0AwUJc2lnbmF0dXJlBQNhbGcCGHdpdGhkcmF3OiBpbnYgc2lnIGZvcm1hdAcJAR1fdmFsaWRhdGVXZWIzSWRNYXRjaGVzQWRkcmVzcwQFBndlYjNJZAUFZnJvbV8FA2FsZwIZd2l0aGRyYXc6IHdlYjNJZCBtaXNtYXRjaAcDCQAAAgUDZXJyBQNlcnIED3dpdGhkcmF3YWxCeXRlcwkAywECCQDLAQIJAMsBAgkAywECCQDLAQIJAMsBAgkAywECCQDLAQIJAMsBAgkAywECCQDLAQIJAJoDAQkAsQIBBQVmcm9tXwkAmwMBBQVmcm9tXwkAmgMBCQCxAgEFA3RvXwkAmwMBBQN0b18JAJoDAQUJdG9DaGFpbklkCQCaAwEJALECAQUGYXNzZXRfCQCbAwEFBmFzc2V0XwkAnQMBBQZhbW91bnQJAJ0DAQUKcmVsYXllckZlZQkAmgMBBQl0aW1lc3RhbXAFBndlYjNJZAkAmgMBBQNhbGcEDndpdGhkcmF3YWxIYXNoCQCMFQEFD3dpdGhkcmF3YWxCeXRlcwQIY3VycmVuY3kJARJfbG9hZEFzc2V0Q3VycmVuY3kCBQl0b0NoYWluSWQFBmFzc2V0XwQQYXZhaWxhYmxlQmFsYW5jZQQHJG1hdGNoMAkA/AcECQETX2xvYWRBY2NvdW50U3RvcmFnZQAFFUZVTkNfR0VUX1VTRVJfQkFMQU5DRQkAzAgCBQVmcm9tXwkAzAgCBQtTUE9UX1dBTExFVAkAzAgCBQhjdXJyZW5jeQUDbmlsBQNuaWwDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwCQCnAwEFAWEJAAIBAjN3aXRoZHJhdzogY2FuJ3QgdGFrZSBhdmFpbGFibGUgYmFsYW5jZSBmcm9tIHN0b3JhZ2UDCQAAAgUQYXZhaWxhYmxlQmFsYW5jZQUQYXZhaWxhYmxlQmFsYW5jZQQNYXNzZXRSZXNlcnZlcwkBEl9sb2FkQXNzZXRSZXNlcnZlcwIFCXRvQ2hhaW5JZAUGYXNzZXRfBA5sb2NrZWRSZXNlcnZlcwkBGF9sb2FkQXNzZXRSZXNlcnZlc0xvY2tlZAIFCXRvQ2hhaW5JZAUGYXNzZXRfBAxhbW91bnRUb1NlbmQJALgCAgUGYW1vdW50BQpyZWxheWVyRmVlBA9hbW91bnRUb1NlbmRTdHIJAKYDAQUMYW1vdW50VG9TZW5kBARlcnIxAwMDCQEcX3ZhbGlkYXRlV2l0aGRyYXdhbFNpZ25hdHVyZQUFDndpdGhkcmF3YWxIYXNoBQlzaWduYXR1cmUFBndlYjNJZAUDYWxnAhV3aXRoZHJhdzogaW52YWxpZCBzaWcJARxfY2hlY2tXaXRoZHJhd2FsSGFzaE5vdEV4aXN0AgUOd2l0aGRyYXdhbEhhc2gCGndpdGhkcmF3OiBhbHJlYWR5IGV4ZWN1dGVkBwkBD192YWxpZGF0ZUJpZ0ludAMFEGF2YWlsYWJsZUJhbGFuY2UFDGFtb3VudFRvU2VuZAIed2l0aGRyYXc6IGluc3VmZmljaWVudCBiYWxhbmNlBwkBD192YWxpZGF0ZUJpZ0ludAMJALgCAgUNYXNzZXRSZXNlcnZlcwUObG9ja2VkUmVzZXJ2ZXMFDGFtb3VudFRvU2VuZAIfd2l0aGRyYXc6IGluc3VmZmljaWVudCByZXNlcnZlcwcDCQAAAgUEZXJyMQUEZXJyMQQQbmV3QXNzZXRSZXNlcnZlcwkAuAICBQ1hc3NldFJlc2VydmVzBQxhbW91bnRUb1NlbmQEE25ld0N1cnJlbmN5UmVzZXJ2ZXMJALgCAgkBFV9sb2FkQ3VycmVuY3lSZXNlcnZlcwEFCGN1cnJlbmN5BQxhbW91bnRUb1NlbmQEBGVycjIDCQEPX3ZhbGlkYXRlQmlnSW50AwUQbmV3QXNzZXRSZXNlcnZlcwULWkVST19CSUdJTlQCI3dpdGhkcmF3OiBuZWdhdGl2ZSBuZXdBc3NldFJlc2VydmVzCQEPX3ZhbGlkYXRlQmlnSW50AwUTbmV3Q3VycmVuY3lSZXNlcnZlcwULWkVST19CSUdJTlQCJndpdGhkcmF3OiBuZWdhdGl2ZSBuZXdDdXJyZW5jeVJlc2VydmVzBwMJAAACBQRlcnIyBQRlcnIyBBJzdG9yYWdlSW52b2NhdGlvbjEJAPwHBAkBE19sb2FkQWNjb3VudFN0b3JhZ2UABQ1GVU5DX1dJVEhEUkFXCQDMCAIFBWZyb21fCQDMCAIFCGN1cnJlbmN5CQDMCAIFB2Ftb3VudF8FA25pbAUDbmlsAwkAAAIFEnN0b3JhZ2VJbnZvY2F0aW9uMQUSc3RvcmFnZUludm9jYXRpb24xBBJzdG9yYWdlSW52b2NhdGlvbjIJAPwHBAkBE19sb2FkQWNjb3VudFN0b3JhZ2UABQxGVU5DX0RFUE9TSVQJAMwIAgkBGF9sb2FkUmVsYXllckZlZVJlY2lwaWVudAAJAMwIAgUIY3VycmVuY3kJAMwIAgULcmVsYXllckZlZV8FA25pbAUDbmlsAwkAAAIFEnN0b3JhZ2VJbnZvY2F0aW9uMgUSc3RvcmFnZUludm9jYXRpb24yBBJ3aXRoZHJhd0ludm9jYXRpb24DCQAAAgkBCl9sb2FkQ2hhaW4BBQl0b0NoYWluSWQFBVdBVkVTCQD8BwQJAQ9fbG9hZFdhdmVzVmF1bHQABQ1GVU5DX1dJVEhEUkFXCQDMCAIFA3RvXwkAzAgCBQZhc3NldF8JAMwIAgUPYW1vdW50VG9TZW5kU3RyBQNuaWwFA25pbAkA/AcECQERX2xvYWRWYXVsdEFkYXB0ZXIABQ1GVU5DX1dJVEhEUkFXCQDMCAIFCXRvQ2hhaW5JZAkAzAgCBQZhc3NldF8JAMwIAgUPYW1vdW50VG9TZW5kU3RyCQDMCAIFA3RvXwkAzAgCBQtyZWxheWVyRmVlXwUDbmlsBQNuaWwDCQAAAgUSd2l0aGRyYXdJbnZvY2F0aW9uBRJ3aXRoZHJhd0ludm9jYXRpb24JAJQKAgkAzggCCQDOCAIJARJfc2F2ZUFzc2V0UmVzZXJ2ZXMDBQl0b0NoYWluSWQFBmFzc2V0XwUQbmV3QXNzZXRSZXNlcnZlcwkBFV9zYXZlQ3VycmVuY3lSZXNlcnZlcwIFCGN1cnJlbmN5BRNuZXdDdXJyZW5jeVJlc2VydmVzCQETX3NhdmVXaXRoZHJhd2FsSGFzaAIFDndpdGhkcmF3YWxIYXNoCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEUZGVwb3NpdFN0YWtpbmdSZXdhcmQED2NhbGxlckNvbnRyYWN0XwhjaGFpbklkXwZhc3NldF8HYW1vdW50XwQHY2hhaW5JZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFCGNoYWluSWRfAiVkZXBvc2l0U3Rha2luZ1Jld2FyZDogY2hhaW5JZCBub3QgaW50BAZhbW91bnQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAqAMBBQdhbW91bnRfAiRkZXBvc2l0U3Rha2luZ1Jld2FyZDogYW1vdW50IG5vdCBpbnQEA2VycgMDAwMJARBfd2hlbkluaXRpYWxpemVkAAkBDl93aGVuTm90UGF1c2VkAAcJAQxfY2hhaW5FeGlzdHMCBQdjaGFpbklkAiVkZXBvc2l0U3Rha2luZ1Jld2FyZDogaW52YWxpZCBjaGFpbklkBwkBFF9hc3NldEN1cnJlbmN5RXhpc3RzAwUHY2hhaW5JZAUGYXNzZXRfAiNkZXBvc2l0U3Rha2luZ1Jld2FyZDogaW52YWxpZCBhc3NldAcJAQ9fdmFsaWRhdGVCaWdJbnQDBQZhbW91bnQFC1pFUk9fQklHSU5UAiRkZXBvc2l0U3Rha2luZ1Jld2FyZDogaW52YWxpZCBhbW91bnQHAwkAAAIFA2VycgUDZXJyBARlcnIxAwkAAAIJAQpfbG9hZENoYWluAQUHY2hhaW5JZAUFV0FWRVMJARNfdmFsaWRhdGVXYXZlc1ZhdWx0AggFAWkGY2FsbGVyAilkZXBvc2l0U3Rha2luZ1Jld2FyZDogaW52YWxpZCB3YXZlcyB2YXVsdAMJARFfdmFsaWRhdGVFeGVjdXRvcgIIBQFpBmNhbGxlcgImZGVwb3NpdFN0YWtpbmdSZXdhcmQ6IGludmFsaWQgZXhlY3V0b3IJARdfdmFsaWRhdGVDYWxsZXJDb250cmFjdAMFB2NoYWluSWQFD2NhbGxlckNvbnRyYWN0XwItZGVwb3NpdFN0YWtpbmdSZXdhcmQ6IGludmFsaWQgY2FsbGVyIGNvbnRyYWN0BwMJAAACBQRlcnIxBQRlcnIxBBBuZXdBc3NldFJlc2VydmVzCQC3AgIJARJfbG9hZEFzc2V0UmVzZXJ2ZXMCBQdjaGFpbklkBQZhc3NldF8FBmFtb3VudAQIY3VycmVuY3kJARJfbG9hZEFzc2V0Q3VycmVuY3kCBQdjaGFpbklkBQZhc3NldF8EE25ld0N1cnJlbmN5UmVzZXJ2ZXMJALcCAgkBFV9sb2FkQ3VycmVuY3lSZXNlcnZlcwEFCGN1cnJlbmN5BQZhbW91bnQECmludm9jYXRpb24JAPwHBAkBE19sb2FkQWNjb3VudFN0b3JhZ2UABRtGVU5DX0RFUE9TSVRfU1RBS0lOR19SRVdBUkQJAMwIAgkBFl9sb2FkUmV3YXJkRGlzdHJpYnV0b3IACQDMCAIFCGN1cnJlbmN5CQDMCAIFB2Ftb3VudF8FA25pbAUDbmlsAwkAAAIFCmludm9jYXRpb24FCmludm9jYXRpb24JAJQKAgkAzggCCQESX3NhdmVBc3NldFJlc2VydmVzAwUHY2hhaW5JZAUGYXNzZXRfBRBuZXdBc3NldFJlc2VydmVzCQEVX3NhdmVDdXJyZW5jeVJlc2VydmVzAgUIY3VycmVuY3kFE25ld0N1cnJlbmN5UmVzZXJ2ZXMFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEIYWRkQ2hhaW4DCGNoYWluSWRfBW5hbWVfD2NhbGxlckNvbnRyYWN0XwQDZXJyAwMDAwMJARFfb25seVRoaXNDb250cmFjdAEIBQFpBmNhbGxlcgkBEF93aGVuSW5pdGlhbGl6ZWQABwkBDF92YWxpZGF0ZUludAQFCGNoYWluSWRfAAAFB01BWF9JTlQCGWFkZENoYWluOiBpbnZhbGlkIGNoYWluSWQHCQEPX3ZhbGlkYXRlU3RyaW5nAgUFbmFtZV8CFmFkZENoYWluOiBpbnZhbGlkIG5hbWUHCQEPX3ZhbGlkYXRlU3RyaW5nAgUPY2FsbGVyQ29udHJhY3RfAiBhZGRDaGFpbjogaW52YWxpZCBjYWxsZXJDb250cmFjdAcJAQ5fY2hhaW5Ob3RFeGlzdAIFCGNoYWluSWRfAhhhZGRDaGFpbjogYWxyZWFkeSBleGlzdHMHAwkAAAIFA2VycgUDZXJyCQCUCgIJAM4IAgkBCl9zYXZlQ2hhaW4CBQhjaGFpbklkXwUFbmFtZV8JARNfc2F2ZUNhbGxlckNvbnRyYWN0AgUIY2hhaW5JZF8FD2NhbGxlckNvbnRyYWN0XwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhhZGRBc3NldAMIY2hhaW5JZF8GYXNzZXRfCWN1cnJlbmN5XwQDZXJyAwMDAwMJARFfb25seVRoaXNDb250cmFjdAEIBQFpBmNhbGxlcgkBEF93aGVuSW5pdGlhbGl6ZWQABwkBDF9jaGFpbkV4aXN0cwIFCGNoYWluSWRfAhlhZGRBc3NldDogaW52YWxpZCBjaGFpbklkBwkBD192YWxpZGF0ZVN0cmluZwIFBmFzc2V0XwIXYWRkQXNzZXQ6IGludmFsaWQgYXNzZXQHCQEPX3ZhbGlkYXRlU3RyaW5nAgUJY3VycmVuY3lfAhphZGRBc3NldDogaW52YWxpZCBjdXJyZW5jeQcJARZfYXNzZXRDdXJyZW5jeU5vdEV4aXN0AwUIY2hhaW5JZF8FBmFzc2V0XwIYYWRkQXNzZXQ6IGFscmVhZHkgZXhpc3RzBwMJAAACBQNlcnIFA2VycgkAlAoCCQESX3NhdmVBc3NldEN1cnJlbmN5AwUIY2hhaW5JZF8FBmFzc2V0XwUJY3VycmVuY3lfBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBHnNldFJlcXVlc3RXaXRoZHJhd2FsQmxvY2tEZWxheQEGZGVsYXlfBANlcnIDAwkBEV9vbmx5VGhpc0NvbnRyYWN0AQgFAWkGY2FsbGVyCQEQX3doZW5Jbml0aWFsaXplZAAHCQEMX3ZhbGlkYXRlSW50BAUGZGVsYXlfAAAFB01BWF9JTlQCLXNldFJlcXVlc3RXaXRoZHJhd2FsQmxvY2tEZWxheTogaW52YWxpZCBkZWxheQcDCQAAAgUDZXJyBQNlcnIJAJQKAgkBIF9zYXZlUmVxdWVzdFdpdGhkcmF3YWxCbG9ja0RlbGF5AQUGZGVsYXlfBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBF3VwZGF0ZVJld2FyZERpc3RyaWJ1dG9yARJyZXdhcmREaXN0cmlidXRvcl8EA2VycgMDCQERX29ubHlUaGlzQ29udHJhY3QBCAUBaQZjYWxsZXIJARBfd2hlbkluaXRpYWxpemVkAAcJAQ9fdmFsaWRhdGVTdHJpbmcCBRJyZXdhcmREaXN0cmlidXRvcl8CMnVwZGF0ZVJld2FyZERpc3RyaWJ1dG9yOiBpbnZhbGlkIHJld2FyZERpc3RyaWJ1dG9yBwMJAAACBQNlcnIFA2VycgkAlAoCCQEWX3NhdmVSZXdhcmREaXN0cmlidXRvcgEFEnJld2FyZERpc3RyaWJ1dG9yXwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARl1cGRhdGVSZWxheWVyRmVlUmVjaXBpZW50ARRyZWxheWVyRmVlUmVjaXBpZW50XwQDZXJyAwMJARFfb25seVRoaXNDb250cmFjdAEIBQFpBmNhbGxlcgkBEF93aGVuSW5pdGlhbGl6ZWQABwkBD192YWxpZGF0ZVN0cmluZwIFFHJlbGF5ZXJGZWVSZWNpcGllbnRfAjZ1cGRhdGVSZWxheWVyRmVlUmVjaXBpZW50OiBpbnZhbGlkIHJlbGF5ZXJGZWVSZWNpcGllbnQHAwkAAAIFA2VycgUDZXJyCQCUCgIJARhfc2F2ZVJlbGF5ZXJGZWVSZWNpcGllbnQBBRRyZWxheWVyRmVlUmVjaXBpZW50XwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQVwYXVzZQAEA2VycgMDCQELX29ubHlQYXVzZXIBCAUBaQZjYWxsZXIJARBfd2hlbkluaXRpYWxpemVkAAcJAQ5fd2hlbk5vdFBhdXNlZAAHAwkAAAIFA2VycgUDZXJyCQCUCgIJAQpfc2F2ZVBhdXNlAQYFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHdW5wYXVzZQAEA2VycgMDCQELX29ubHlQYXVzZXIBCAUBaQZjYWxsZXIJARBfd2hlbkluaXRpYWxpemVkAAcJAQtfd2hlblBhdXNlZAAHAwkAAAIFA2VycgUDZXJyCQCUCgIJAQpfc2F2ZVBhdXNlAQcFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMdXBkYXRlUGF1c2VyAQdwYXVzZXJfBANlcnIDAwkBEV9vbmx5VGhpc0NvbnRyYWN0AQgFAWkGY2FsbGVyCQEQX3doZW5Jbml0aWFsaXplZAAHCQEQX3ZhbGlkYXRlQWRkcmVzcwIFB3BhdXNlcl8CHHVwZGF0ZVBhdXNlcjogaW52YWxpZCBwYXVzZXIHAwkAAAIFA2VycgUDZXJyCQCUCgIJAQtfc2F2ZVBhdXNlcgEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB3BhdXNlcl8FBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELc2V0TXVsdGlzaWcBCW11bHRpc2lnXwQDZXJyAwkBEV9vbmx5VGhpc0NvbnRyYWN0AQgFAWkGY2FsbGVyCQEQX3ZhbGlkYXRlQWRkcmVzcwIFCW11bHRpc2lnXwIdc2V0TXVsdGlzaWc6IGludmFsaWQgbXVsdGlzaWcHAwkAAAIFA2VycgUDZXJyCQCUCgIJAQ1fc2F2ZU11bHRpc2lnAQkBEUBleHRyTmF0aXZlKDEwNjIpAQUJbXVsdGlzaWdfBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAQHJG1hdGNoMAkAoggBBQxLRVlfTVVMVElTSUcDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAhtdWx0aXNpZwUHJG1hdGNoMAkBC3ZhbHVlT3JFbHNlAgkAmwgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQhtdWx0aXNpZwkAuQkCCQDMCAIFCktFWV9TVEFUVVMJAMwIAgkApQgBBQR0aGlzCQDMCAIJANgEAQgFAnR4AmlkBQNuaWwFCVNFUEFSQVRPUgcJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXl0QOf/", "height": 3407157, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: HfrtsyoqcdEVaFxU5r5WYqxKStbNaMKKcXtUkx3P5Yxf Next: 74rf9Vdqi9f8SHdP9ipAKhpd68m8VwbfeMKCcNExBi45 Diff:
Old | New | Differences | |
---|---|---|---|
80 | 80 | let ALG_TYPE_WAVES = 1 | |
81 | 81 | ||
82 | 82 | let ALG_TYPE_EVM = 2 | |
83 | + | ||
84 | + | let WAVES_PREFIX = base58'7YXq4t' | |
83 | 85 | ||
84 | 86 | let EVM_SIGNATURE_PREFIX = base58'G5Nu92G2p7moXW9qjjN3na7gtq4dWCeVdaSjry' | |
85 | 87 | ||
474 | 476 | ||
475 | 477 | func _validateWithdrawalSignature (withdrawalHash_,signature_,web3Id_,alg_,err_) = { | |
476 | 478 | let result = if ((alg_ == ALG_TYPE_WAVES)) | |
477 | - | then sigVerify(withdrawalHash_, signature_, web3Id_) | |
479 | + | then { | |
480 | + | let hashWithPrefix = keccak256_16Kb((WAVES_PREFIX + toBytes(toBase58String(withdrawalHash_)))) | |
481 | + | sigVerify(hashWithPrefix, signature_, web3Id_) | |
482 | + | } | |
478 | 483 | else if ((alg_ == ALG_TYPE_EVM)) | |
479 | 484 | then { | |
480 | 485 | let hashWithPrefix = keccak256_16Kb((EVM_SIGNATURE_PREFIX + withdrawalHash_)) | |
604 | 609 | then { | |
605 | 610 | let lockedReserves = _loadAssetReservesLocked(toChainId, asset_) | |
606 | 611 | let userLockedCurrency = _loadUserLockedCurrency(currency, from_) | |
607 | - | let $ | |
612 | + | let $t01943719892 = if (if (((availableBalance - userLockedCurrency) >= amount)) | |
608 | 613 | then ((_loadAssetReserves(toChainId, asset_) - lockedReserves) >= amount) | |
609 | 614 | else false) | |
610 | 615 | then $Tuple2(REQUEST_STATUS_CREATED, (_saveAssetReservesLocked(toChainId, asset_, (lockedReserves + amount)) ++ _saveUserLockedCurrency(currency, from_, (amount + userLockedCurrency)))) | |
611 | 616 | else $Tuple2(REQUEST_STATUS_REJECTED, nil) | |
612 | - | let requestStatus = $ | |
613 | - | let reservesActions = $ | |
617 | + | let requestStatus = $t01943719892._1 | |
618 | + | let reservesActions = $t01943719892._2 | |
614 | 619 | let requestWithdrawalSize = _loadRequestWithdrawalSize() | |
615 | 620 | let requestWithdrawal = $Tuple8(from_, to_, toChainId, asset_, amount, height, toBase58String(i.transactionId), requestStatus) | |
616 | 621 | $Tuple2(((_saveRequestWithdrawal(requestWithdrawalSize, requestWithdrawal) ++ _saveRequestWithdrawalSize((requestWithdrawalSize + 1))) ++ reservesActions), requestWithdrawalSize) |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 7 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let SEPARATOR = "__" | |
5 | 5 | ||
6 | 6 | let KEY_MULTISIG = "MULTISIG" | |
7 | 7 | ||
8 | 8 | let KEY_STATUS = "STATUS" | |
9 | 9 | ||
10 | 10 | let KEY_INIT = "INIT" | |
11 | 11 | ||
12 | 12 | let KEY_PAUSED = "PAUSED" | |
13 | 13 | ||
14 | 14 | let KEY_PAUSER = "PAUSER" | |
15 | 15 | ||
16 | 16 | let KEY_EXECUTOR = "EXECUTOR" | |
17 | 17 | ||
18 | 18 | let KEY_CALLER_CONTRACT = "CALLER_CONTRACT" | |
19 | 19 | ||
20 | 20 | let KEY_WAVES_VAULT = "WAVES_VAULT" | |
21 | 21 | ||
22 | 22 | let KEY_ACCOUNT_STORAGE = "ACCOUNT_STORAGE" | |
23 | 23 | ||
24 | 24 | let KEY_CHAIN = "CHAIN" | |
25 | 25 | ||
26 | 26 | let KEY_ASSET_CURRENCY = "ASSET_CURRENCY" | |
27 | 27 | ||
28 | 28 | let KEY_ASSET_RESERVES = "ASSET_RESERVES" | |
29 | 29 | ||
30 | 30 | let KEY_ASSET_RESERVES_LOCKED = "ASSET_RESERVES_LOCKED" | |
31 | 31 | ||
32 | 32 | let KEY_USER_LOCKED_CURRENCY = "USER_LOCKED_CURRENCY" | |
33 | 33 | ||
34 | 34 | let KEY_CURRENCY_RESERVES = "CURRENCY_RESERVES" | |
35 | 35 | ||
36 | 36 | let KEY_REQUEST_WITHDRAWAL_SIZE = "REQUEST_WITHDRAWAL_SIZE" | |
37 | 37 | ||
38 | 38 | let KEY_REQUEST_WITHDRAWAL = "REQUEST_WITHDRAWAL" | |
39 | 39 | ||
40 | 40 | let KEY_REQUEST_WITHDRAWAL_BLOCK_DELAY = "REQUEST_WITHDRAWAL_BLOCK_DELAY" | |
41 | 41 | ||
42 | 42 | let KEY_SEQUENCER = "SEQUENCER" | |
43 | 43 | ||
44 | 44 | let KEY_WITHDRAWAL_HASH = "WITHDRAWAL_HASH" | |
45 | 45 | ||
46 | 46 | let KEY_VAULT_ADAPTER = "VAULT_ADAPTER" | |
47 | 47 | ||
48 | 48 | let KEY_REWARD_DISTRIBUTOR = "REWARD_DISTRIBUTOR" | |
49 | 49 | ||
50 | 50 | let KEY_RELAYER_FEE_RECIPIENT = "RELAYER_FEE_RECIPIENT" | |
51 | 51 | ||
52 | 52 | let FUNC_DEPOSIT = "deposit" | |
53 | 53 | ||
54 | 54 | let FUNC_GET_USER_BALANCE = "getUserBalance" | |
55 | 55 | ||
56 | 56 | let FUNC_INTERNAL_TRANSFER = "internalTransfer" | |
57 | 57 | ||
58 | 58 | let FUNC_WITHDRAW = "withdraw" | |
59 | 59 | ||
60 | 60 | let FUNC_DEPOSIT_STAKING_REWARD = "depositStakingReward" | |
61 | 61 | ||
62 | 62 | let REQUEST_STATUS_CREATED = 0 | |
63 | 63 | ||
64 | 64 | let REQUEST_STATUS_DONE = 1 | |
65 | 65 | ||
66 | 66 | let REQUEST_STATUS_REJECTED = 2 | |
67 | 67 | ||
68 | 68 | let WAVES = "WAVES" | |
69 | 69 | ||
70 | 70 | let SPOT_WALLET = "SPOT" | |
71 | 71 | ||
72 | 72 | let MAX_INT = 9223372036854775807 | |
73 | 73 | ||
74 | 74 | let ZERO_BIGINT = toBigInt(0) | |
75 | 75 | ||
76 | 76 | let ONE_BIGINT = toBigInt(1) | |
77 | 77 | ||
78 | 78 | let ONE_DAY = 86400000 | |
79 | 79 | ||
80 | 80 | let ALG_TYPE_WAVES = 1 | |
81 | 81 | ||
82 | 82 | let ALG_TYPE_EVM = 2 | |
83 | + | ||
84 | + | let WAVES_PREFIX = base58'7YXq4t' | |
83 | 85 | ||
84 | 86 | let EVM_SIGNATURE_PREFIX = base58'G5Nu92G2p7moXW9qjjN3na7gtq4dWCeVdaSjry' | |
85 | 87 | ||
86 | 88 | func _validateAddress (address_,err_) = match addressFromString(address_) { | |
87 | 89 | case a: Address => | |
88 | 90 | true | |
89 | 91 | case _ => | |
90 | 92 | throw(err_) | |
91 | 93 | } | |
92 | 94 | ||
93 | 95 | ||
94 | 96 | func _validateInt (val_,lowerBoundary_,upperBoundary_,err_) = if (if ((lowerBoundary_ > val_)) | |
95 | 97 | then true | |
96 | 98 | else (val_ > upperBoundary_)) | |
97 | 99 | then throw(err_) | |
98 | 100 | else true | |
99 | 101 | ||
100 | 102 | ||
101 | 103 | func _validateBigInt (val_,lowerBoundary_,err_) = if ((lowerBoundary_ > val_)) | |
102 | 104 | then throw(err_) | |
103 | 105 | else true | |
104 | 106 | ||
105 | 107 | ||
106 | 108 | func _validateBigInt_2 (val_,lowerBoundary_,upperBoundary_,err_) = if (if ((lowerBoundary_ > val_)) | |
107 | 109 | then true | |
108 | 110 | else (val_ > upperBoundary_)) | |
109 | 111 | then throw(err_) | |
110 | 112 | else true | |
111 | 113 | ||
112 | 114 | ||
113 | 115 | func _validateString (val_,err_) = if (if ((0 >= size(val_))) | |
114 | 116 | then true | |
115 | 117 | else contains(val_, SEPARATOR)) | |
116 | 118 | then throw(err_) | |
117 | 119 | else true | |
118 | 120 | ||
119 | 121 | ||
120 | 122 | func _validateStringEqual (val1_,val2_,err_) = if ((val1_ != val2_)) | |
121 | 123 | then throw(err_) | |
122 | 124 | else true | |
123 | 125 | ||
124 | 126 | ||
125 | 127 | func _loadInit () = match getBoolean(KEY_INIT) { | |
126 | 128 | case a: Boolean => | |
127 | 129 | a | |
128 | 130 | case _ => | |
129 | 131 | false | |
130 | 132 | } | |
131 | 133 | ||
132 | 134 | ||
133 | 135 | func _saveInit (isInit_) = [BooleanEntry(KEY_INIT, isInit_)] | |
134 | 136 | ||
135 | 137 | ||
136 | 138 | func _loadPause () = match getBoolean(KEY_PAUSED) { | |
137 | 139 | case a: Boolean => | |
138 | 140 | a | |
139 | 141 | case _ => | |
140 | 142 | false | |
141 | 143 | } | |
142 | 144 | ||
143 | 145 | ||
144 | 146 | func _savePause (isPaused_) = [BooleanEntry(KEY_PAUSED, isPaused_)] | |
145 | 147 | ||
146 | 148 | ||
147 | 149 | func _loadPauser () = match getString(KEY_PAUSER) { | |
148 | 150 | case a: String => | |
149 | 151 | addressFromStringValue(a) | |
150 | 152 | case _ => | |
151 | 153 | Address(base58'') | |
152 | 154 | } | |
153 | 155 | ||
154 | 156 | ||
155 | 157 | func _savePauser (pauser_) = [StringEntry(KEY_PAUSER, toString(pauser_))] | |
156 | 158 | ||
157 | 159 | ||
158 | 160 | func _loadMultisig () = match getString(KEY_MULTISIG) { | |
159 | 161 | case a: String => | |
160 | 162 | addressFromStringValue(a) | |
161 | 163 | case _ => | |
162 | 164 | Address(base58'') | |
163 | 165 | } | |
164 | 166 | ||
165 | 167 | ||
166 | 168 | func _saveMultisig (multisig_) = [StringEntry(KEY_MULTISIG, toString(multisig_))] | |
167 | 169 | ||
168 | 170 | ||
169 | 171 | func _loadCallerContract (chainId_) = match getString(makeString([KEY_CALLER_CONTRACT, toString(chainId_)], SEPARATOR)) { | |
170 | 172 | case a: String => | |
171 | 173 | a | |
172 | 174 | case _ => | |
173 | 175 | "" | |
174 | 176 | } | |
175 | 177 | ||
176 | 178 | ||
177 | 179 | func _saveCallerContract (chainId_,callerContract_) = [StringEntry(makeString([KEY_CALLER_CONTRACT, toString(chainId_)], SEPARATOR), callerContract_)] | |
178 | 180 | ||
179 | 181 | ||
180 | 182 | func _loadExecutor () = match getString(KEY_EXECUTOR) { | |
181 | 183 | case a: String => | |
182 | 184 | addressFromStringValue(a) | |
183 | 185 | case _ => | |
184 | 186 | Address(base58'') | |
185 | 187 | } | |
186 | 188 | ||
187 | 189 | ||
188 | 190 | func _saveExecutor (executor_) = [StringEntry(KEY_EXECUTOR, toString(executor_))] | |
189 | 191 | ||
190 | 192 | ||
191 | 193 | func _loadAccountStorage () = match getString(KEY_ACCOUNT_STORAGE) { | |
192 | 194 | case a: String => | |
193 | 195 | addressFromStringValue(a) | |
194 | 196 | case _ => | |
195 | 197 | Address(base58'') | |
196 | 198 | } | |
197 | 199 | ||
198 | 200 | ||
199 | 201 | func _saveAccountStorage (accountStorage_) = [StringEntry(KEY_ACCOUNT_STORAGE, toString(accountStorage_))] | |
200 | 202 | ||
201 | 203 | ||
202 | 204 | func _loadWavesVault () = match getString(KEY_WAVES_VAULT) { | |
203 | 205 | case a: String => | |
204 | 206 | addressFromStringValue(a) | |
205 | 207 | case _ => | |
206 | 208 | Address(base58'') | |
207 | 209 | } | |
208 | 210 | ||
209 | 211 | ||
210 | 212 | func _saveWavesVault (wavesVault_) = [StringEntry(KEY_WAVES_VAULT, toString(wavesVault_))] | |
211 | 213 | ||
212 | 214 | ||
213 | 215 | func _loadChain (chainId_) = match getString(makeString([KEY_CHAIN, toString(chainId_)], SEPARATOR)) { | |
214 | 216 | case a: String => | |
215 | 217 | a | |
216 | 218 | case _ => | |
217 | 219 | "" | |
218 | 220 | } | |
219 | 221 | ||
220 | 222 | ||
221 | 223 | func _saveChain (chainId_,name_) = [StringEntry(makeString([KEY_CHAIN, toString(chainId_)], SEPARATOR), name_)] | |
222 | 224 | ||
223 | 225 | ||
224 | 226 | func _loadAssetCurrency (chainId_,asset_) = match getString(makeString([KEY_ASSET_CURRENCY, toString(chainId_), asset_], SEPARATOR)) { | |
225 | 227 | case a: String => | |
226 | 228 | a | |
227 | 229 | case _ => | |
228 | 230 | "" | |
229 | 231 | } | |
230 | 232 | ||
231 | 233 | ||
232 | 234 | func _saveAssetCurrency (chainId_,asset_,currency_) = [StringEntry(makeString([KEY_ASSET_CURRENCY, toString(chainId_), asset_], SEPARATOR), currency_)] | |
233 | 235 | ||
234 | 236 | ||
235 | 237 | func _loadAssetReserves (chainId_,asset_) = match getString(makeString([KEY_ASSET_RESERVES, toString(chainId_), asset_], SEPARATOR)) { | |
236 | 238 | case a: String => | |
237 | 239 | parseBigIntValue(a) | |
238 | 240 | case _ => | |
239 | 241 | ZERO_BIGINT | |
240 | 242 | } | |
241 | 243 | ||
242 | 244 | ||
243 | 245 | func _saveAssetReserves (chainId_,asset_,reserves_) = [StringEntry(makeString([KEY_ASSET_RESERVES, toString(chainId_), asset_], SEPARATOR), toString(reserves_))] | |
244 | 246 | ||
245 | 247 | ||
246 | 248 | func _loadAssetReservesLocked (chainId_,asset_) = match getString(makeString([KEY_ASSET_RESERVES_LOCKED, toString(chainId_), asset_], SEPARATOR)) { | |
247 | 249 | case a: String => | |
248 | 250 | parseBigIntValue(a) | |
249 | 251 | case _ => | |
250 | 252 | ZERO_BIGINT | |
251 | 253 | } | |
252 | 254 | ||
253 | 255 | ||
254 | 256 | func _saveAssetReservesLocked (chainId_,asset_,reserves_) = [StringEntry(makeString([KEY_ASSET_RESERVES_LOCKED, toString(chainId_), asset_], SEPARATOR), toString(reserves_))] | |
255 | 257 | ||
256 | 258 | ||
257 | 259 | func _loadUserLockedCurrency (currency_,user_) = match getString(makeString([KEY_USER_LOCKED_CURRENCY, currency_, user_], SEPARATOR)) { | |
258 | 260 | case a: String => | |
259 | 261 | parseBigIntValue(a) | |
260 | 262 | case _ => | |
261 | 263 | ZERO_BIGINT | |
262 | 264 | } | |
263 | 265 | ||
264 | 266 | ||
265 | 267 | func _saveUserLockedCurrency (currency_,user_,amount_) = [StringEntry(makeString([KEY_USER_LOCKED_CURRENCY, currency_, user_], SEPARATOR), toString(amount_))] | |
266 | 268 | ||
267 | 269 | ||
268 | 270 | func _loadCurrencyReserves (currency_) = match getString(makeString([KEY_CURRENCY_RESERVES, currency_], SEPARATOR)) { | |
269 | 271 | case a: String => | |
270 | 272 | parseBigIntValue(a) | |
271 | 273 | case _ => | |
272 | 274 | ZERO_BIGINT | |
273 | 275 | } | |
274 | 276 | ||
275 | 277 | ||
276 | 278 | func _saveCurrencyReserves (currency_,reserves_) = [StringEntry(makeString([KEY_CURRENCY_RESERVES, currency_], SEPARATOR), toString(reserves_))] | |
277 | 279 | ||
278 | 280 | ||
279 | 281 | func _loadRequestWithdrawalSize () = match getInteger(KEY_REQUEST_WITHDRAWAL_SIZE) { | |
280 | 282 | case a: Int => | |
281 | 283 | a | |
282 | 284 | case _ => | |
283 | 285 | 0 | |
284 | 286 | } | |
285 | 287 | ||
286 | 288 | ||
287 | 289 | func _saveRequestWithdrawalSize (val_) = [IntegerEntry(KEY_REQUEST_WITHDRAWAL_SIZE, val_)] | |
288 | 290 | ||
289 | 291 | ||
290 | 292 | func _loadRequestWithdrawal (index_) = match getString(makeString([KEY_REQUEST_WITHDRAWAL, toString(index_)], SEPARATOR)) { | |
291 | 293 | case a: String => | |
292 | 294 | let struct = split(a, SEPARATOR) | |
293 | 295 | $Tuple8(struct[0], struct[1], parseIntValue(struct[2]), struct[3], parseBigIntValue(struct[4]), parseIntValue(struct[5]), struct[6], parseIntValue(struct[7])) | |
294 | 296 | case _ => | |
295 | 297 | $Tuple8("", "", 0, "", ZERO_BIGINT, 0, "", REQUEST_STATUS_CREATED) | |
296 | 298 | } | |
297 | 299 | ||
298 | 300 | ||
299 | 301 | func _saveRequestWithdrawal (index_,request_) = [StringEntry(makeString([KEY_REQUEST_WITHDRAWAL, toString(index_)], SEPARATOR), makeString([request_._1, request_._2, toString(request_._3), request_._4, toString(request_._5), toString(request_._6), request_._7, toString(request_._8)], SEPARATOR))] | |
300 | 302 | ||
301 | 303 | ||
302 | 304 | func _loadRequestWithdrawalBlockDelay () = match getInteger(KEY_REQUEST_WITHDRAWAL_BLOCK_DELAY) { | |
303 | 305 | case a: Int => | |
304 | 306 | a | |
305 | 307 | case _ => | |
306 | 308 | 0 | |
307 | 309 | } | |
308 | 310 | ||
309 | 311 | ||
310 | 312 | func _saveRequestWithdrawalBlockDelay (delay_) = [IntegerEntry(KEY_REQUEST_WITHDRAWAL_BLOCK_DELAY, delay_)] | |
311 | 313 | ||
312 | 314 | ||
313 | 315 | func _loadSequencer () = match getString(KEY_SEQUENCER) { | |
314 | 316 | case a: String => | |
315 | 317 | addressFromStringValue(a) | |
316 | 318 | case _ => | |
317 | 319 | Address(base58'') | |
318 | 320 | } | |
319 | 321 | ||
320 | 322 | ||
321 | 323 | func _saveSequencer (sequencer_) = [StringEntry(KEY_SEQUENCER, toString(sequencer_))] | |
322 | 324 | ||
323 | 325 | ||
324 | 326 | func _loadWithdrawalHash (withdrawalHash_) = match getString(makeString([KEY_WITHDRAWAL_HASH, toBase58String(withdrawalHash_)], SEPARATOR)) { | |
325 | 327 | case a: String => | |
326 | 328 | a | |
327 | 329 | case _ => | |
328 | 330 | "" | |
329 | 331 | } | |
330 | 332 | ||
331 | 333 | ||
332 | 334 | func _saveWithdrawalHash (withdrawalHash_,txId_) = [StringEntry(makeString([KEY_WITHDRAWAL_HASH, toBase58String(withdrawalHash_)], SEPARATOR), txId_)] | |
333 | 335 | ||
334 | 336 | ||
335 | 337 | func _loadVaultAdapter () = match getString(KEY_VAULT_ADAPTER) { | |
336 | 338 | case a: String => | |
337 | 339 | addressFromStringValue(a) | |
338 | 340 | case _ => | |
339 | 341 | Address(base58'') | |
340 | 342 | } | |
341 | 343 | ||
342 | 344 | ||
343 | 345 | func _saveVaultAdapter (vaultAdapter_) = [StringEntry(KEY_VAULT_ADAPTER, toString(vaultAdapter_))] | |
344 | 346 | ||
345 | 347 | ||
346 | 348 | func _loadRewardDistributor () = match getString(KEY_REWARD_DISTRIBUTOR) { | |
347 | 349 | case a: String => | |
348 | 350 | a | |
349 | 351 | case _ => | |
350 | 352 | "" | |
351 | 353 | } | |
352 | 354 | ||
353 | 355 | ||
354 | 356 | func _saveRewardDistributor (distributor_) = [StringEntry(KEY_REWARD_DISTRIBUTOR, distributor_)] | |
355 | 357 | ||
356 | 358 | ||
357 | 359 | func _loadRelayerFeeRecipient () = match getString(KEY_RELAYER_FEE_RECIPIENT) { | |
358 | 360 | case a: String => | |
359 | 361 | a | |
360 | 362 | case _ => | |
361 | 363 | "" | |
362 | 364 | } | |
363 | 365 | ||
364 | 366 | ||
365 | 367 | func _saveRelayerFeeRecipient (relayerFeeRecipient_) = [StringEntry(KEY_RELAYER_FEE_RECIPIENT, relayerFeeRecipient_)] | |
366 | 368 | ||
367 | 369 | ||
368 | 370 | func _onlyThisContract (caller_) = if ((caller_ != this)) | |
369 | 371 | then throw("_onlyThisContract: revert") | |
370 | 372 | else true | |
371 | 373 | ||
372 | 374 | ||
373 | 375 | func _whenMultisigSet () = if ((_loadMultisig() == Address(base58''))) | |
374 | 376 | then throw("_whenMultisigSet: revert") | |
375 | 377 | else true | |
376 | 378 | ||
377 | 379 | ||
378 | 380 | func _whenNotInitialized () = if (_loadInit()) | |
379 | 381 | then throw("_whenNotInitialized: revert") | |
380 | 382 | else true | |
381 | 383 | ||
382 | 384 | ||
383 | 385 | func _whenInitialized () = if (!(_loadInit())) | |
384 | 386 | then throw("_whenInitialized: revert") | |
385 | 387 | else true | |
386 | 388 | ||
387 | 389 | ||
388 | 390 | func _whenNotPaused () = if (_loadPause()) | |
389 | 391 | then throw("_whenNotPaused: revert") | |
390 | 392 | else true | |
391 | 393 | ||
392 | 394 | ||
393 | 395 | func _whenPaused () = if (!(_loadPause())) | |
394 | 396 | then throw("_whenPaused: revert") | |
395 | 397 | else true | |
396 | 398 | ||
397 | 399 | ||
398 | 400 | func _onlyPauser (caller_) = if ((caller_ != _loadPauser())) | |
399 | 401 | then throw("_onlyPauser: revert") | |
400 | 402 | else true | |
401 | 403 | ||
402 | 404 | ||
403 | 405 | func _validateExecutor (val_,err_) = if ((val_ != _loadExecutor())) | |
404 | 406 | then throw(err_) | |
405 | 407 | else true | |
406 | 408 | ||
407 | 409 | ||
408 | 410 | func _validateCallerContract (chainId_,callerContract_,err_) = if ((_loadCallerContract(chainId_) != callerContract_)) | |
409 | 411 | then throw(err_) | |
410 | 412 | else true | |
411 | 413 | ||
412 | 414 | ||
413 | 415 | func _chainExists (chainId_,err_) = if ((0 >= size(_loadChain(chainId_)))) | |
414 | 416 | then throw(err_) | |
415 | 417 | else true | |
416 | 418 | ||
417 | 419 | ||
418 | 420 | func _chainNotExist (chainId_,err_) = if ((size(_loadChain(chainId_)) > 0)) | |
419 | 421 | then throw(err_) | |
420 | 422 | else true | |
421 | 423 | ||
422 | 424 | ||
423 | 425 | func _assetCurrencyExists (chainId_,asset_,err_) = if ((0 >= size(_loadAssetCurrency(chainId_, asset_)))) | |
424 | 426 | then throw(err_) | |
425 | 427 | else true | |
426 | 428 | ||
427 | 429 | ||
428 | 430 | func _assetCurrencyNotExist (chainId_,asset_,err_) = if ((size(_loadAssetCurrency(chainId_, asset_)) > 0)) | |
429 | 431 | then throw(err_) | |
430 | 432 | else true | |
431 | 433 | ||
432 | 434 | ||
433 | 435 | func _validateWavesVault (caller,err_) = if ((_loadWavesVault() != caller)) | |
434 | 436 | then throw(err_) | |
435 | 437 | else true | |
436 | 438 | ||
437 | 439 | ||
438 | 440 | func _requestIsCreated (status_,err_) = if ((status_ != REQUEST_STATUS_CREATED)) | |
439 | 441 | then throw(err_) | |
440 | 442 | else true | |
441 | 443 | ||
442 | 444 | ||
443 | 445 | func _validateSequencer (caller,err_) = if ((_loadSequencer() != caller)) | |
444 | 446 | then throw(err_) | |
445 | 447 | else true | |
446 | 448 | ||
447 | 449 | ||
448 | 450 | func _checkWithdrawalHashNotExist (withdrawalHash_,err_) = if ((size(_loadWithdrawalHash(withdrawalHash_)) > 0)) | |
449 | 451 | then throw(err_) | |
450 | 452 | else true | |
451 | 453 | ||
452 | 454 | ||
453 | 455 | func _validateSignatureFormat (signature_,alg_,err_) = if ((alg_ == ALG_TYPE_WAVES)) | |
454 | 456 | then if ((size(signature_) != 64)) | |
455 | 457 | then throw(err_) | |
456 | 458 | else true | |
457 | 459 | else if ((alg_ == ALG_TYPE_EVM)) | |
458 | 460 | then if ((size(signature_) != 65)) | |
459 | 461 | then throw(err_) | |
460 | 462 | else true | |
461 | 463 | else throw((err_ + ": inv alg")) | |
462 | 464 | ||
463 | 465 | ||
464 | 466 | func _validateWeb3Id (web3Id_,alg_,err_) = if ((alg_ == ALG_TYPE_WAVES)) | |
465 | 467 | then if ((size(web3Id_) != 32)) | |
466 | 468 | then throw(err_) | |
467 | 469 | else true | |
468 | 470 | else if ((alg_ == ALG_TYPE_EVM)) | |
469 | 471 | then if ((size(web3Id_) != 20)) | |
470 | 472 | then throw(err_) | |
471 | 473 | else true | |
472 | 474 | else throw((err_ + ": inv alg")) | |
473 | 475 | ||
474 | 476 | ||
475 | 477 | func _validateWithdrawalSignature (withdrawalHash_,signature_,web3Id_,alg_,err_) = { | |
476 | 478 | let result = if ((alg_ == ALG_TYPE_WAVES)) | |
477 | - | then sigVerify(withdrawalHash_, signature_, web3Id_) | |
479 | + | then { | |
480 | + | let hashWithPrefix = keccak256_16Kb((WAVES_PREFIX + toBytes(toBase58String(withdrawalHash_)))) | |
481 | + | sigVerify(hashWithPrefix, signature_, web3Id_) | |
482 | + | } | |
478 | 483 | else if ((alg_ == ALG_TYPE_EVM)) | |
479 | 484 | then { | |
480 | 485 | let hashWithPrefix = keccak256_16Kb((EVM_SIGNATURE_PREFIX + withdrawalHash_)) | |
481 | 486 | (takeRight(keccak256_16Kb(ecrecover(hashWithPrefix, signature_)), 20) == web3Id_) | |
482 | 487 | } | |
483 | 488 | else throw((err_ + ": inv alg")) | |
484 | 489 | if (!(result)) | |
485 | 490 | then throw(err_) | |
486 | 491 | else true | |
487 | 492 | } | |
488 | 493 | ||
489 | 494 | ||
490 | 495 | func _validateWeb3IdMatchesAddress (web3Id_,from_,alg_,err_) = { | |
491 | 496 | let address = if ((alg_ == ALG_TYPE_WAVES)) | |
492 | 497 | then toString(addressFromPublicKey(web3Id_)) | |
493 | 498 | else if ((alg_ == ALG_TYPE_EVM)) | |
494 | 499 | then ("0x" + toBase16String(web3Id_)) | |
495 | 500 | else throw((err_ + ": inv alg")) | |
496 | 501 | if ((address != from_)) | |
497 | 502 | then throw(err_) | |
498 | 503 | else true | |
499 | 504 | } | |
500 | 505 | ||
501 | 506 | ||
502 | 507 | @Callable(i) | |
503 | 508 | func init (executor_,pauser_,accountStorage_,wavesVault_,sequencer_,vaultAdapter_) = { | |
504 | 509 | let err = if (if (if (if (if (if (if (if (_onlyThisContract(i.caller)) | |
505 | 510 | then _whenNotInitialized() | |
506 | 511 | else false) | |
507 | 512 | then _whenMultisigSet() | |
508 | 513 | else false) | |
509 | 514 | then _validateAddress(executor_, "init: invalid executor") | |
510 | 515 | else false) | |
511 | 516 | then _validateAddress(pauser_, "init: invalid pauser") | |
512 | 517 | else false) | |
513 | 518 | then _validateAddress(accountStorage_, "init: invalid accountStorage") | |
514 | 519 | else false) | |
515 | 520 | then _validateAddress(wavesVault_, "init: invalid wavesVault") | |
516 | 521 | else false) | |
517 | 522 | then _validateAddress(sequencer_, "init: invalid sequencer") | |
518 | 523 | else false) | |
519 | 524 | then _validateAddress(vaultAdapter_, "init: invalid vaultAdapter") | |
520 | 525 | else false | |
521 | 526 | if ((err == err)) | |
522 | 527 | then $Tuple2(((((((_saveInit(true) ++ _saveExecutor(addressFromStringValue(executor_))) ++ _savePauser(addressFromStringValue(pauser_))) ++ _saveAccountStorage(addressFromStringValue(accountStorage_))) ++ _saveWavesVault(addressFromStringValue(wavesVault_))) ++ _saveSequencer(addressFromStringValue(sequencer_))) ++ _saveVaultAdapter(addressFromStringValue(vaultAdapter_))), unit) | |
523 | 528 | else throw("Strict value is not equal to itself.") | |
524 | 529 | } | |
525 | 530 | ||
526 | 531 | ||
527 | 532 | ||
528 | 533 | @Callable(i) | |
529 | 534 | func deposit (callerContract_,from_,to_,chainId_,asset_,amount_) = { | |
530 | 535 | let chainId = valueOrErrorMessage(parseInt(chainId_), "deposit: chainId not int") | |
531 | 536 | let amount = valueOrErrorMessage(parseBigInt(amount_), "deposit: amount not int") | |
532 | 537 | let err = if (if (if (if (if (if (_whenInitialized()) | |
533 | 538 | then _whenNotPaused() | |
534 | 539 | else false) | |
535 | 540 | then _chainExists(chainId, "deposit: invalid chainId") | |
536 | 541 | else false) | |
537 | 542 | then _validateString(from_, "deposit: invalid from") | |
538 | 543 | else false) | |
539 | 544 | then _validateString(to_, "deposit: invalid to") | |
540 | 545 | else false) | |
541 | 546 | then _assetCurrencyExists(chainId, asset_, "deposit: invalid asset") | |
542 | 547 | else false) | |
543 | 548 | then _validateBigInt(amount, ZERO_BIGINT, "deposit: invalid amount") | |
544 | 549 | else false | |
545 | 550 | if ((err == err)) | |
546 | 551 | then { | |
547 | 552 | let err1 = if ((_loadChain(chainId) == WAVES)) | |
548 | 553 | then _validateWavesVault(i.caller, "deposit: invalid waves vault") | |
549 | 554 | else if (_validateExecutor(i.caller, "deposit: invalid executor")) | |
550 | 555 | then _validateCallerContract(chainId, callerContract_, "deposit: invalid caller contract") | |
551 | 556 | else false | |
552 | 557 | if ((err1 == err1)) | |
553 | 558 | then { | |
554 | 559 | let newAssetReserves = (_loadAssetReserves(chainId, asset_) + amount) | |
555 | 560 | let currency = _loadAssetCurrency(chainId, asset_) | |
556 | 561 | let newCurrencyReserves = (_loadCurrencyReserves(currency) + amount) | |
557 | 562 | let invocation = invoke(_loadAccountStorage(), FUNC_DEPOSIT, [to_, currency, amount_], nil) | |
558 | 563 | if ((invocation == invocation)) | |
559 | 564 | then $Tuple2((_saveAssetReserves(chainId, asset_, newAssetReserves) ++ _saveCurrencyReserves(currency, newCurrencyReserves)), unit) | |
560 | 565 | else throw("Strict value is not equal to itself.") | |
561 | 566 | } | |
562 | 567 | else throw("Strict value is not equal to itself.") | |
563 | 568 | } | |
564 | 569 | else throw("Strict value is not equal to itself.") | |
565 | 570 | } | |
566 | 571 | ||
567 | 572 | ||
568 | 573 | ||
569 | 574 | @Callable(i) | |
570 | 575 | func requestWithdrawal (callerContract_,from_,to_,fromChainId_,toChainId_,asset_,amount_) = { | |
571 | 576 | let fromChainId = valueOrErrorMessage(parseInt(fromChainId_), "requestWithdrawal: fromChainId not int") | |
572 | 577 | let toChainId = valueOrErrorMessage(parseInt(toChainId_), "requestWithdrawal: toChainId not int") | |
573 | 578 | let amount = valueOrErrorMessage(parseBigInt(amount_), "requestWithdrawal: amount not int") | |
574 | 579 | let err = if (if (if (if (if (if (_whenInitialized()) | |
575 | 580 | then _chainExists(fromChainId, "requestWithdrawal: invalid fromChainId") | |
576 | 581 | else false) | |
577 | 582 | then _chainExists(toChainId, "requestWithdrawal: invalid toChainId") | |
578 | 583 | else false) | |
579 | 584 | then _validateString(from_, "requestWithdrawal: invalid from") | |
580 | 585 | else false) | |
581 | 586 | then _validateString(to_, "requestWithdrawal: invalid to") | |
582 | 587 | else false) | |
583 | 588 | then _assetCurrencyExists(toChainId, asset_, "requestWithdrawal: invalid asset") | |
584 | 589 | else false) | |
585 | 590 | then _validateBigInt(amount, ZERO_BIGINT, "requestWithdrawal: invalid amount") | |
586 | 591 | else false | |
587 | 592 | if ((err == err)) | |
588 | 593 | then { | |
589 | 594 | let err1 = if ((_loadChain(fromChainId) == WAVES)) | |
590 | 595 | then _validateWavesVault(i.caller, "requestWithdrawal: invalid waves vault") | |
591 | 596 | else if (_validateExecutor(i.caller, "requestWithdrawal: invalid executor")) | |
592 | 597 | then _validateCallerContract(fromChainId, callerContract_, "requestWithdrawal: invalid caller contract") | |
593 | 598 | else false | |
594 | 599 | if ((err1 == err1)) | |
595 | 600 | then { | |
596 | 601 | let currency = _loadAssetCurrency(toChainId, asset_) | |
597 | 602 | let availableBalance = match invoke(_loadAccountStorage(), FUNC_GET_USER_BALANCE, [from_, SPOT_WALLET, currency], nil) { | |
598 | 603 | case a: String => | |
599 | 604 | parseBigIntValue(a) | |
600 | 605 | case _ => | |
601 | 606 | throw("requestWithdrawal: can't take available balance from storage") | |
602 | 607 | } | |
603 | 608 | if ((availableBalance == availableBalance)) | |
604 | 609 | then { | |
605 | 610 | let lockedReserves = _loadAssetReservesLocked(toChainId, asset_) | |
606 | 611 | let userLockedCurrency = _loadUserLockedCurrency(currency, from_) | |
607 | - | let $ | |
612 | + | let $t01943719892 = if (if (((availableBalance - userLockedCurrency) >= amount)) | |
608 | 613 | then ((_loadAssetReserves(toChainId, asset_) - lockedReserves) >= amount) | |
609 | 614 | else false) | |
610 | 615 | then $Tuple2(REQUEST_STATUS_CREATED, (_saveAssetReservesLocked(toChainId, asset_, (lockedReserves + amount)) ++ _saveUserLockedCurrency(currency, from_, (amount + userLockedCurrency)))) | |
611 | 616 | else $Tuple2(REQUEST_STATUS_REJECTED, nil) | |
612 | - | let requestStatus = $ | |
613 | - | let reservesActions = $ | |
617 | + | let requestStatus = $t01943719892._1 | |
618 | + | let reservesActions = $t01943719892._2 | |
614 | 619 | let requestWithdrawalSize = _loadRequestWithdrawalSize() | |
615 | 620 | let requestWithdrawal = $Tuple8(from_, to_, toChainId, asset_, amount, height, toBase58String(i.transactionId), requestStatus) | |
616 | 621 | $Tuple2(((_saveRequestWithdrawal(requestWithdrawalSize, requestWithdrawal) ++ _saveRequestWithdrawalSize((requestWithdrawalSize + 1))) ++ reservesActions), requestWithdrawalSize) | |
617 | 622 | } | |
618 | 623 | else throw("Strict value is not equal to itself.") | |
619 | 624 | } | |
620 | 625 | else throw("Strict value is not equal to itself.") | |
621 | 626 | } | |
622 | 627 | else throw("Strict value is not equal to itself.") | |
623 | 628 | } | |
624 | 629 | ||
625 | 630 | ||
626 | 631 | ||
627 | 632 | @Callable(i) | |
628 | 633 | func executeWithdrawal (callerContract_,chainId_,requestWithdrawalId_) = { | |
629 | 634 | let chainId = valueOrErrorMessage(parseInt(chainId_), "executeWithdrawal: chainId not int") | |
630 | 635 | let requestWithdrawalId = valueOrErrorMessage(parseInt(requestWithdrawalId_), "executeWithdrawal: requestWithdrawalId not int") | |
631 | 636 | let requestWithdrawalSize = _loadRequestWithdrawalSize() | |
632 | 637 | let err = if (if (_whenInitialized()) | |
633 | 638 | then _chainExists(chainId, "executeWithdrawal: invalid chainId") | |
634 | 639 | else false) | |
635 | 640 | then _validateInt(requestWithdrawalId, 0, (requestWithdrawalSize - 1), "executeWithdrawal: invalid requestWithdrawalId") | |
636 | 641 | else false | |
637 | 642 | if ((err == err)) | |
638 | 643 | then { | |
639 | 644 | let err1 = if ((_loadChain(chainId) == WAVES)) | |
640 | 645 | then _validateWavesVault(i.caller, "executeWithdrawal: invalid waves vault") | |
641 | 646 | else if (_validateExecutor(i.caller, "executeWithdrawal: invalid executor")) | |
642 | 647 | then _validateCallerContract(chainId, callerContract_, "executeWithdrawal: invalid caller contract") | |
643 | 648 | else false | |
644 | 649 | if ((err1 == err1)) | |
645 | 650 | then { | |
646 | 651 | let request = _loadRequestWithdrawal(requestWithdrawalId) | |
647 | 652 | let requestFrom = request._1 | |
648 | 653 | let requestTo = request._2 | |
649 | 654 | let requestToChainId = request._3 | |
650 | 655 | let requestAsset = request._4 | |
651 | 656 | let requestAmount = request._5 | |
652 | 657 | let requestHeight = request._6 | |
653 | 658 | let requestStatus = request._8 | |
654 | 659 | let newAssetReserves = (_loadAssetReserves(requestToChainId, requestAsset) - requestAmount) | |
655 | 660 | let newAssetReservesLocked = (_loadAssetReservesLocked(requestToChainId, requestAsset) - requestAmount) | |
656 | 661 | let currency = _loadAssetCurrency(requestToChainId, requestAsset) | |
657 | 662 | let newCurrencyReserves = (_loadCurrencyReserves(currency) - requestAmount) | |
658 | 663 | let newUserLockedCurrency = (_loadUserLockedCurrency(currency, requestFrom) - requestAmount) | |
659 | 664 | let err2 = if (if (if (if (if (_validateBigInt(newAssetReserves, ZERO_BIGINT, "executeWithdrawal: negative newAssetReserves")) | |
660 | 665 | then _validateBigInt(newAssetReservesLocked, ZERO_BIGINT, "executeWithdrawal: negative newAssetReservesLocked") | |
661 | 666 | else false) | |
662 | 667 | then _validateBigInt(newCurrencyReserves, ZERO_BIGINT, "executeWithdrawal: negative newCurrencyReserves") | |
663 | 668 | else false) | |
664 | 669 | then _validateBigInt(newUserLockedCurrency, ZERO_BIGINT, "executeWithdrawal: negative newUserLockedCurrency") | |
665 | 670 | else false) | |
666 | 671 | then _validateInt((height - requestHeight), _loadRequestWithdrawalBlockDelay(), MAX_INT, "executeWithdrawal: too early to execute") | |
667 | 672 | else false) | |
668 | 673 | then _requestIsCreated(requestStatus, "executeWithdrawal: request is resolved") | |
669 | 674 | else false | |
670 | 675 | if ((err2 == err2)) | |
671 | 676 | then { | |
672 | 677 | let storageInvocation = invoke(_loadAccountStorage(), FUNC_WITHDRAW, [requestFrom, currency, toString(requestAmount)], nil) | |
673 | 678 | if ((storageInvocation == storageInvocation)) | |
674 | 679 | then { | |
675 | 680 | let withdrawInvocation = if ((_loadChain(requestToChainId) == WAVES)) | |
676 | 681 | then invoke(_loadWavesVault(), FUNC_WITHDRAW, [requestTo, requestAsset, toString(requestAmount)], nil) | |
677 | 682 | else invoke(_loadVaultAdapter(), FUNC_WITHDRAW, [requestToChainId, requestAsset, toString(requestAmount), requestTo], nil) | |
678 | 683 | if ((withdrawInvocation == withdrawInvocation)) | |
679 | 684 | then { | |
680 | 685 | let requestUpdated = $Tuple8(request._1, request._2, request._3, request._4, request._5, request._6, request._7, REQUEST_STATUS_DONE) | |
681 | 686 | $Tuple2(((((_saveAssetReserves(requestToChainId, requestAsset, newAssetReserves) ++ _saveAssetReservesLocked(requestToChainId, requestAsset, newAssetReservesLocked)) ++ _saveCurrencyReserves(currency, newCurrencyReserves)) ++ _saveUserLockedCurrency(currency, requestFrom, newUserLockedCurrency)) ++ _saveRequestWithdrawal(requestWithdrawalId, requestUpdated)), unit) | |
682 | 687 | } | |
683 | 688 | else throw("Strict value is not equal to itself.") | |
684 | 689 | } | |
685 | 690 | else throw("Strict value is not equal to itself.") | |
686 | 691 | } | |
687 | 692 | else throw("Strict value is not equal to itself.") | |
688 | 693 | } | |
689 | 694 | else throw("Strict value is not equal to itself.") | |
690 | 695 | } | |
691 | 696 | else throw("Strict value is not equal to itself.") | |
692 | 697 | } | |
693 | 698 | ||
694 | 699 | ||
695 | 700 | ||
696 | 701 | @Callable(i) | |
697 | 702 | func rejectWithdrawal (requestWithdrawalId_) = { | |
698 | 703 | let requestWithdrawalId = valueOrErrorMessage(parseInt(requestWithdrawalId_), "rejectWithdrawal: requestWithdrawalId not int") | |
699 | 704 | let requestWithdrawalSize = _loadRequestWithdrawalSize() | |
700 | 705 | let err = if (if (_whenInitialized()) | |
701 | 706 | then _validateSequencer(i.caller, "rejectWithdrawal: invalid sequencer") | |
702 | 707 | else false) | |
703 | 708 | then _validateInt(requestWithdrawalId, 0, (requestWithdrawalSize - 1), "rejectWithdrawal: invalid requestWithdrawalId") | |
704 | 709 | else false | |
705 | 710 | if ((err == err)) | |
706 | 711 | then { | |
707 | 712 | let request = _loadRequestWithdrawal(requestWithdrawalId) | |
708 | 713 | let requestFrom = request._1 | |
709 | 714 | let requestTo = request._2 | |
710 | 715 | let requestToChainId = request._3 | |
711 | 716 | let requestAsset = request._4 | |
712 | 717 | let requestAmount = request._5 | |
713 | 718 | let requestHeight = request._6 | |
714 | 719 | let requestStatus = request._8 | |
715 | 720 | let currency = _loadAssetCurrency(requestToChainId, requestAsset) | |
716 | 721 | let newAssetReservesLocked = (_loadAssetReservesLocked(requestToChainId, requestAsset) - requestAmount) | |
717 | 722 | let newUserLockedCurrency = (_loadUserLockedCurrency(currency, requestFrom) - requestAmount) | |
718 | 723 | let err1 = if (if (_validateBigInt(newAssetReservesLocked, ZERO_BIGINT, "rejectWithdrawal: negative newAssetReservesLocked")) | |
719 | 724 | then _validateBigInt(newUserLockedCurrency, ZERO_BIGINT, "rejectWithdrawal: negative newUserLockedCurrency") | |
720 | 725 | else false) | |
721 | 726 | then _requestIsCreated(requestStatus, "rejectWithdrawal: request is resolved") | |
722 | 727 | else false | |
723 | 728 | if ((err1 == err1)) | |
724 | 729 | then { | |
725 | 730 | let availableBalance = match invoke(_loadAccountStorage(), FUNC_GET_USER_BALANCE, [requestFrom, SPOT_WALLET, currency], nil) { | |
726 | 731 | case a: String => | |
727 | 732 | parseBigIntValue(a) | |
728 | 733 | case _ => | |
729 | 734 | throw("rejectWithdrawal: can't take available balance from storage") | |
730 | 735 | } | |
731 | 736 | if ((availableBalance == availableBalance)) | |
732 | 737 | then if ((requestAmount > availableBalance)) | |
733 | 738 | then { | |
734 | 739 | let requestUpdated = $Tuple8(request._1, request._2, request._3, request._4, request._5, request._6, request._7, REQUEST_STATUS_REJECTED) | |
735 | 740 | $Tuple2(((_saveAssetReservesLocked(requestToChainId, requestAsset, newAssetReservesLocked) ++ _saveUserLockedCurrency(currency, requestFrom, newUserLockedCurrency)) ++ _saveRequestWithdrawal(requestWithdrawalId, requestUpdated)), true) | |
736 | 741 | } | |
737 | 742 | else $Tuple2(nil, false) | |
738 | 743 | else throw("Strict value is not equal to itself.") | |
739 | 744 | } | |
740 | 745 | else throw("Strict value is not equal to itself.") | |
741 | 746 | } | |
742 | 747 | else throw("Strict value is not equal to itself.") | |
743 | 748 | } | |
744 | 749 | ||
745 | 750 | ||
746 | 751 | ||
747 | 752 | @Callable(i) | |
748 | 753 | func withdraw (from_,to_,toChainId_,asset_,amount_,relayerFee_,timestamp_,web3Id_,alg_,signature_) = { | |
749 | 754 | let toChainId = valueOrErrorMessage(parseInt(toChainId_), "withdraw: toChainId not int") | |
750 | 755 | let amount = valueOrErrorMessage(parseBigInt(amount_), "withdraw: amount not int") | |
751 | 756 | let relayerFee = valueOrErrorMessage(parseBigInt(relayerFee_), "withdraw: relayerFee not int") | |
752 | 757 | let timestamp = valueOrErrorMessage(parseInt(timestamp_), "withdraw: timestamp not int") | |
753 | 758 | let alg = valueOrErrorMessage(parseInt(alg_), "withdraw: alg not int") | |
754 | 759 | let web3Id = fromBase58String(web3Id_) | |
755 | 760 | let signature = fromBase58String(signature_) | |
756 | 761 | let err = if (if (if (if (if (if (if (if (if (if (if (_whenInitialized()) | |
757 | 762 | then _validateSequencer(i.caller, "withdraw: invalid sequencer") | |
758 | 763 | else false) | |
759 | 764 | then _validateString(from_, "withdraw: invalid from") | |
760 | 765 | else false) | |
761 | 766 | then _validateString(to_, "withdraw: invalid to") | |
762 | 767 | else false) | |
763 | 768 | then _chainExists(toChainId, "withdraw: invalid toChainId") | |
764 | 769 | else false) | |
765 | 770 | then _assetCurrencyExists(toChainId, asset_, "withdraw: invalid asset") | |
766 | 771 | else false) | |
767 | 772 | then _validateBigInt(amount, ZERO_BIGINT, "withdraw: invalid amount") | |
768 | 773 | else false) | |
769 | 774 | then _validateBigInt_2(relayerFee, ZERO_BIGINT, amount, "withdraw: invalid relayerFee") | |
770 | 775 | else false) | |
771 | 776 | then _validateInt((timestamp + ONE_DAY), lastBlock.timestamp, MAX_INT, "withdraw: invalid timestamp") | |
772 | 777 | else false) | |
773 | 778 | then _validateWeb3Id(web3Id, alg, "withdraw: inv web3Id") | |
774 | 779 | else false) | |
775 | 780 | then _validateSignatureFormat(signature, alg, "withdraw: inv sig format") | |
776 | 781 | else false) | |
777 | 782 | then _validateWeb3IdMatchesAddress(web3Id, from_, alg, "withdraw: web3Id mismatch") | |
778 | 783 | else false | |
779 | 784 | if ((err == err)) | |
780 | 785 | then { | |
781 | 786 | let withdrawalBytes = (((((((((((toBytes(size(from_)) + toBytes(from_)) + toBytes(size(to_))) + toBytes(to_)) + toBytes(toChainId)) + toBytes(size(asset_))) + toBytes(asset_)) + toBytes(amount)) + toBytes(relayerFee)) + toBytes(timestamp)) + web3Id) + toBytes(alg)) | |
782 | 787 | let withdrawalHash = keccak256_16Kb(withdrawalBytes) | |
783 | 788 | let currency = _loadAssetCurrency(toChainId, asset_) | |
784 | 789 | let availableBalance = match invoke(_loadAccountStorage(), FUNC_GET_USER_BALANCE, [from_, SPOT_WALLET, currency], nil) { | |
785 | 790 | case a: String => | |
786 | 791 | parseBigIntValue(a) | |
787 | 792 | case _ => | |
788 | 793 | throw("withdraw: can't take available balance from storage") | |
789 | 794 | } | |
790 | 795 | if ((availableBalance == availableBalance)) | |
791 | 796 | then { | |
792 | 797 | let assetReserves = _loadAssetReserves(toChainId, asset_) | |
793 | 798 | let lockedReserves = _loadAssetReservesLocked(toChainId, asset_) | |
794 | 799 | let amountToSend = (amount - relayerFee) | |
795 | 800 | let amountToSendStr = toString(amountToSend) | |
796 | 801 | let err1 = if (if (if (_validateWithdrawalSignature(withdrawalHash, signature, web3Id, alg, "withdraw: invalid sig")) | |
797 | 802 | then _checkWithdrawalHashNotExist(withdrawalHash, "withdraw: already executed") | |
798 | 803 | else false) | |
799 | 804 | then _validateBigInt(availableBalance, amountToSend, "withdraw: insufficient balance") | |
800 | 805 | else false) | |
801 | 806 | then _validateBigInt((assetReserves - lockedReserves), amountToSend, "withdraw: insufficient reserves") | |
802 | 807 | else false | |
803 | 808 | if ((err1 == err1)) | |
804 | 809 | then { | |
805 | 810 | let newAssetReserves = (assetReserves - amountToSend) | |
806 | 811 | let newCurrencyReserves = (_loadCurrencyReserves(currency) - amountToSend) | |
807 | 812 | let err2 = if (_validateBigInt(newAssetReserves, ZERO_BIGINT, "withdraw: negative newAssetReserves")) | |
808 | 813 | then _validateBigInt(newCurrencyReserves, ZERO_BIGINT, "withdraw: negative newCurrencyReserves") | |
809 | 814 | else false | |
810 | 815 | if ((err2 == err2)) | |
811 | 816 | then { | |
812 | 817 | let storageInvocation1 = invoke(_loadAccountStorage(), FUNC_WITHDRAW, [from_, currency, amount_], nil) | |
813 | 818 | if ((storageInvocation1 == storageInvocation1)) | |
814 | 819 | then { | |
815 | 820 | let storageInvocation2 = invoke(_loadAccountStorage(), FUNC_DEPOSIT, [_loadRelayerFeeRecipient(), currency, relayerFee_], nil) | |
816 | 821 | if ((storageInvocation2 == storageInvocation2)) | |
817 | 822 | then { | |
818 | 823 | let withdrawInvocation = if ((_loadChain(toChainId) == WAVES)) | |
819 | 824 | then invoke(_loadWavesVault(), FUNC_WITHDRAW, [to_, asset_, amountToSendStr], nil) | |
820 | 825 | else invoke(_loadVaultAdapter(), FUNC_WITHDRAW, [toChainId, asset_, amountToSendStr, to_, relayerFee_], nil) | |
821 | 826 | if ((withdrawInvocation == withdrawInvocation)) | |
822 | 827 | then $Tuple2(((_saveAssetReserves(toChainId, asset_, newAssetReserves) ++ _saveCurrencyReserves(currency, newCurrencyReserves)) ++ _saveWithdrawalHash(withdrawalHash, toBase58String(i.transactionId))), unit) | |
823 | 828 | else throw("Strict value is not equal to itself.") | |
824 | 829 | } | |
825 | 830 | else throw("Strict value is not equal to itself.") | |
826 | 831 | } | |
827 | 832 | else throw("Strict value is not equal to itself.") | |
828 | 833 | } | |
829 | 834 | else throw("Strict value is not equal to itself.") | |
830 | 835 | } | |
831 | 836 | else throw("Strict value is not equal to itself.") | |
832 | 837 | } | |
833 | 838 | else throw("Strict value is not equal to itself.") | |
834 | 839 | } | |
835 | 840 | else throw("Strict value is not equal to itself.") | |
836 | 841 | } | |
837 | 842 | ||
838 | 843 | ||
839 | 844 | ||
840 | 845 | @Callable(i) | |
841 | 846 | func depositStakingReward (callerContract_,chainId_,asset_,amount_) = { | |
842 | 847 | let chainId = valueOrErrorMessage(parseInt(chainId_), "depositStakingReward: chainId not int") | |
843 | 848 | let amount = valueOrErrorMessage(parseBigInt(amount_), "depositStakingReward: amount not int") | |
844 | 849 | let err = if (if (if (if (_whenInitialized()) | |
845 | 850 | then _whenNotPaused() | |
846 | 851 | else false) | |
847 | 852 | then _chainExists(chainId, "depositStakingReward: invalid chainId") | |
848 | 853 | else false) | |
849 | 854 | then _assetCurrencyExists(chainId, asset_, "depositStakingReward: invalid asset") | |
850 | 855 | else false) | |
851 | 856 | then _validateBigInt(amount, ZERO_BIGINT, "depositStakingReward: invalid amount") | |
852 | 857 | else false | |
853 | 858 | if ((err == err)) | |
854 | 859 | then { | |
855 | 860 | let err1 = if ((_loadChain(chainId) == WAVES)) | |
856 | 861 | then _validateWavesVault(i.caller, "depositStakingReward: invalid waves vault") | |
857 | 862 | else if (_validateExecutor(i.caller, "depositStakingReward: invalid executor")) | |
858 | 863 | then _validateCallerContract(chainId, callerContract_, "depositStakingReward: invalid caller contract") | |
859 | 864 | else false | |
860 | 865 | if ((err1 == err1)) | |
861 | 866 | then { | |
862 | 867 | let newAssetReserves = (_loadAssetReserves(chainId, asset_) + amount) | |
863 | 868 | let currency = _loadAssetCurrency(chainId, asset_) | |
864 | 869 | let newCurrencyReserves = (_loadCurrencyReserves(currency) + amount) | |
865 | 870 | let invocation = invoke(_loadAccountStorage(), FUNC_DEPOSIT_STAKING_REWARD, [_loadRewardDistributor(), currency, amount_], nil) | |
866 | 871 | if ((invocation == invocation)) | |
867 | 872 | then $Tuple2((_saveAssetReserves(chainId, asset_, newAssetReserves) ++ _saveCurrencyReserves(currency, newCurrencyReserves)), unit) | |
868 | 873 | else throw("Strict value is not equal to itself.") | |
869 | 874 | } | |
870 | 875 | else throw("Strict value is not equal to itself.") | |
871 | 876 | } | |
872 | 877 | else throw("Strict value is not equal to itself.") | |
873 | 878 | } | |
874 | 879 | ||
875 | 880 | ||
876 | 881 | ||
877 | 882 | @Callable(i) | |
878 | 883 | func addChain (chainId_,name_,callerContract_) = { | |
879 | 884 | let err = if (if (if (if (if (_onlyThisContract(i.caller)) | |
880 | 885 | then _whenInitialized() | |
881 | 886 | else false) | |
882 | 887 | then _validateInt(chainId_, 0, MAX_INT, "addChain: invalid chainId") | |
883 | 888 | else false) | |
884 | 889 | then _validateString(name_, "addChain: invalid name") | |
885 | 890 | else false) | |
886 | 891 | then _validateString(callerContract_, "addChain: invalid callerContract") | |
887 | 892 | else false) | |
888 | 893 | then _chainNotExist(chainId_, "addChain: already exists") | |
889 | 894 | else false | |
890 | 895 | if ((err == err)) | |
891 | 896 | then $Tuple2((_saveChain(chainId_, name_) ++ _saveCallerContract(chainId_, callerContract_)), unit) | |
892 | 897 | else throw("Strict value is not equal to itself.") | |
893 | 898 | } | |
894 | 899 | ||
895 | 900 | ||
896 | 901 | ||
897 | 902 | @Callable(i) | |
898 | 903 | func addAsset (chainId_,asset_,currency_) = { | |
899 | 904 | let err = if (if (if (if (if (_onlyThisContract(i.caller)) | |
900 | 905 | then _whenInitialized() | |
901 | 906 | else false) | |
902 | 907 | then _chainExists(chainId_, "addAsset: invalid chainId") | |
903 | 908 | else false) | |
904 | 909 | then _validateString(asset_, "addAsset: invalid asset") | |
905 | 910 | else false) | |
906 | 911 | then _validateString(currency_, "addAsset: invalid currency") | |
907 | 912 | else false) | |
908 | 913 | then _assetCurrencyNotExist(chainId_, asset_, "addAsset: already exists") | |
909 | 914 | else false | |
910 | 915 | if ((err == err)) | |
911 | 916 | then $Tuple2(_saveAssetCurrency(chainId_, asset_, currency_), unit) | |
912 | 917 | else throw("Strict value is not equal to itself.") | |
913 | 918 | } | |
914 | 919 | ||
915 | 920 | ||
916 | 921 | ||
917 | 922 | @Callable(i) | |
918 | 923 | func setRequestWithdrawalBlockDelay (delay_) = { | |
919 | 924 | let err = if (if (_onlyThisContract(i.caller)) | |
920 | 925 | then _whenInitialized() | |
921 | 926 | else false) | |
922 | 927 | then _validateInt(delay_, 0, MAX_INT, "setRequestWithdrawalBlockDelay: invalid delay") | |
923 | 928 | else false | |
924 | 929 | if ((err == err)) | |
925 | 930 | then $Tuple2(_saveRequestWithdrawalBlockDelay(delay_), unit) | |
926 | 931 | else throw("Strict value is not equal to itself.") | |
927 | 932 | } | |
928 | 933 | ||
929 | 934 | ||
930 | 935 | ||
931 | 936 | @Callable(i) | |
932 | 937 | func updateRewardDistributor (rewardDistributor_) = { | |
933 | 938 | let err = if (if (_onlyThisContract(i.caller)) | |
934 | 939 | then _whenInitialized() | |
935 | 940 | else false) | |
936 | 941 | then _validateString(rewardDistributor_, "updateRewardDistributor: invalid rewardDistributor") | |
937 | 942 | else false | |
938 | 943 | if ((err == err)) | |
939 | 944 | then $Tuple2(_saveRewardDistributor(rewardDistributor_), unit) | |
940 | 945 | else throw("Strict value is not equal to itself.") | |
941 | 946 | } | |
942 | 947 | ||
943 | 948 | ||
944 | 949 | ||
945 | 950 | @Callable(i) | |
946 | 951 | func updateRelayerFeeRecipient (relayerFeeRecipient_) = { | |
947 | 952 | let err = if (if (_onlyThisContract(i.caller)) | |
948 | 953 | then _whenInitialized() | |
949 | 954 | else false) | |
950 | 955 | then _validateString(relayerFeeRecipient_, "updateRelayerFeeRecipient: invalid relayerFeeRecipient") | |
951 | 956 | else false | |
952 | 957 | if ((err == err)) | |
953 | 958 | then $Tuple2(_saveRelayerFeeRecipient(relayerFeeRecipient_), unit) | |
954 | 959 | else throw("Strict value is not equal to itself.") | |
955 | 960 | } | |
956 | 961 | ||
957 | 962 | ||
958 | 963 | ||
959 | 964 | @Callable(i) | |
960 | 965 | func pause () = { | |
961 | 966 | let err = if (if (_onlyPauser(i.caller)) | |
962 | 967 | then _whenInitialized() | |
963 | 968 | else false) | |
964 | 969 | then _whenNotPaused() | |
965 | 970 | else false | |
966 | 971 | if ((err == err)) | |
967 | 972 | then $Tuple2(_savePause(true), unit) | |
968 | 973 | else throw("Strict value is not equal to itself.") | |
969 | 974 | } | |
970 | 975 | ||
971 | 976 | ||
972 | 977 | ||
973 | 978 | @Callable(i) | |
974 | 979 | func unpause () = { | |
975 | 980 | let err = if (if (_onlyPauser(i.caller)) | |
976 | 981 | then _whenInitialized() | |
977 | 982 | else false) | |
978 | 983 | then _whenPaused() | |
979 | 984 | else false | |
980 | 985 | if ((err == err)) | |
981 | 986 | then $Tuple2(_savePause(false), unit) | |
982 | 987 | else throw("Strict value is not equal to itself.") | |
983 | 988 | } | |
984 | 989 | ||
985 | 990 | ||
986 | 991 | ||
987 | 992 | @Callable(i) | |
988 | 993 | func updatePauser (pauser_) = { | |
989 | 994 | let err = if (if (_onlyThisContract(i.caller)) | |
990 | 995 | then _whenInitialized() | |
991 | 996 | else false) | |
992 | 997 | then _validateAddress(pauser_, "updatePauser: invalid pauser") | |
993 | 998 | else false | |
994 | 999 | if ((err == err)) | |
995 | 1000 | then $Tuple2(_savePauser(addressFromStringValue(pauser_)), unit) | |
996 | 1001 | else throw("Strict value is not equal to itself.") | |
997 | 1002 | } | |
998 | 1003 | ||
999 | 1004 | ||
1000 | 1005 | ||
1001 | 1006 | @Callable(i) | |
1002 | 1007 | func setMultisig (multisig_) = { | |
1003 | 1008 | let err = if (_onlyThisContract(i.caller)) | |
1004 | 1009 | then _validateAddress(multisig_, "setMultisig: invalid multisig") | |
1005 | 1010 | else false | |
1006 | 1011 | if ((err == err)) | |
1007 | 1012 | then $Tuple2(_saveMultisig(addressFromStringValue(multisig_)), unit) | |
1008 | 1013 | else throw("Strict value is not equal to itself.") | |
1009 | 1014 | } | |
1010 | 1015 | ||
1011 | 1016 | ||
1012 | 1017 | @Verifier(tx) | |
1013 | 1018 | func verify () = match getString(KEY_MULTISIG) { | |
1014 | 1019 | case multisig: String => | |
1015 | 1020 | valueOrElse(getBoolean(addressFromStringValue(multisig), makeString([KEY_STATUS, toString(this), toBase58String(tx.id)], SEPARATOR)), false) | |
1016 | 1021 | case _ => | |
1017 | 1022 | sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
1018 | 1023 | } | |
1019 | 1024 |
github/deemru/w8io/026f985 132.01 ms ◑