tx · HDNkG4cHNhtZCSHrBN6iafpqYoM4FsiUiVE9ihfAh1f9

3N1ZmWkbiKsr7L7W7eYERDJE75QaC2YgXyL:  -0.04300000 Waves

2024.10.02 15:13 [3309212] smart account 3N1ZmWkbiKsr7L7W7eYERDJE75QaC2YgXyL > SELF 0.00000000 Waves

{ "type": 13, "id": "HDNkG4cHNhtZCSHrBN6iafpqYoM4FsiUiVE9ihfAh1f9", "fee": 4300000, "feeAssetId": null, "timestamp": 1727873868000, "version": 2, "chainId": 84, "sender": "3N1ZmWkbiKsr7L7W7eYERDJE75QaC2YgXyL", "senderPublicKey": "GzhAL6mZ2js6XUWcA2nT5dQ1kDDdcECWukWbSguqz6fy", "proofs": [ "4o4aoibrohw1JDrcBJyDGx1ckA8uA5rjeVgNs38UBMoty1TU9sk8MCMiiFi1wT2ZYJfh2PSv1mfnijDezkAWqXAP" ], "script": "base64:CAJCCAISBwoFCAgCCAESBwoFCAgCCAESCAoGCAgCAQgBEgYKBAgICAESAwoBCBIAEgMKAQgSBgoECBIBARIECgIIARIATQAHSU5UX01BWAD//////////38ABVdBVkVTAIDC1y8AC01JTl9CQUxBTkNFCQBoAgCgnAEFBVdBVkVTAANTRVACASwAD0JMT0NLX0hBU0hfU0laRQAgABRQVUJMSUNfS0VZX0hBU0hfU0laRQAUAA5ST09UX0hBU0hfU0laRQAgABRXSVRIRFJBV19QUk9PRlNfU0laRQAKABRFVEhfQUREUkVTU19TVFJfU0laRQAoABZNQVhfQ0xfVE9fRUxfVFJBTlNGRVJTABAACXplcm9lc1N0cgKACDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAADGFsbE1pbmVyc0tleQIJYWxsTWluZXJzAA5tYWluQ2hhaW5JZEtleQILbWFpbkNoYWluSWQADmxhc3RDaGFpbklkS2V5AgtsYXN0Q2hhaW5JZAAXZmlyc3RWYWxpZEFsdENoYWluSWRLZXkCFGZpcnN0VmFsaWRBbHRDaGFpbklkAA5taW5lclJld2FyZEtleQILbWluZXJSZXdhcmQACmJsb2NrTWV0YUsCCGJsb2NrXzB4ABFmaW5hbGl6ZWRCbG9ja0tleQIOZmluYWxpemVkQmxvY2sACnRva2VuSWRLZXkCB3Rva2VuSWQAEmVsQnJpZGdlQWRkcmVzc0tleQIPZWxCcmlkZ2VBZGRyZXNzABduYXRpdmVUcmFuc2ZlcnNDb3VudEtleQIUbmF0aXZlVHJhbnNmZXJzQ291bnQBA3BhZAEBaQQBcwkApAMBBQFpBAckbWF0Y2gwCQCxAgEFAXMDCQAAAgABBQckbWF0Y2gwCQCsAgICBzAwMDAwMDAFAXMDCQAAAgACBQckbWF0Y2gwCQCsAgICBjAwMDAwMAUBcwMJAAACAAMFByRtYXRjaDAJAKwCAgIFMDAwMDAFAXMDCQAAAgAEBQckbWF0Y2gwCQCsAgICBDAwMDAFAXMDCQAAAgAFBQckbWF0Y2gwCQCsAgICAzAwMAUBcwMJAAACAAYFByRtYXRjaDAJAKwCAgICMDAFAXMDCQAAAgAHBQckbWF0Y2gwCQCsAgICATAFAXMFAXMAEGRhb0NvbmZpZ0FkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNONWM3RENDR21pY05pSFJHb3VVcDNCYVY2ZThlRFVEbkh3ABdjaXJjdWl0QnJlYWtlckNsb3NlZEtleQIUY2lyY3VpdEJyZWFrZXJDbG9zZWQBFGNpcmN1aXRCcmVha2VyQ2xvc2VkAAMJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUXY2lyY3VpdEJyZWFrZXJDbG9zZWRLZXkGBgkAAgECGWNpcmN1aXQgYnJlYWtlciBpcyBvcGVuZWQBFGJsb2NrRTJDVHJhbnNmZXJzS2V5AQxibG9ja0hhc2hIZXgJAKwCAgISZWxUb0NsVHJhbnNmZXJzXzB4BQxibG9ja0hhc2hIZXgBDGVwb2NoTWV0YUtleQEFZXBvY2gJAKwCAgIGZXBvY2hfCQEDcGFkAQUFZXBvY2gBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQdjaGFpbklkCQCsAgIJAKwCAgIFY2hhaW4JAKQDAQUHY2hhaW5JZAIKRmlyc3RCbG9jawEMY2hhaW5NZXRhS2V5AQdjaGFpbklkCQCsAgICBmNoYWluXwkBA3BhZAEFB2NoYWluSWQBEmNoYWluTGFzdEhlaWdodEtleQIHY2hhaW5JZAVtaW5lcgkArAICCQCsAgIJAKwCAgIGY2hhaW5fCQEDcGFkAQUHY2hhaW5JZAIBXwkApQgBBQVtaW5lcgEUY2hhaW5Gb3JrZWRIZWlnaHRLZXkBB2NoYWluSWQJAKwCAgkArAICAgZjaGFpbl8JAQNwYWQBBQdjaGFpbklkAgxGb3JrZWRIZWlnaHQBDXN1cHBvcnRlcnNLZXkBB2NoYWluSWQJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgpTdXBwb3J0ZXJzARVtaW5lclJld2FyZEFkZHJlc3NLZXkBCW1pbmVyQWRkcgkArAICCQCsAgICBm1pbmVyXwUJbWluZXJBZGRyAg5fUmV3YXJkQWRkcmVzcwEKbWluZXJQa0tleQENcmV3YXJkQWRkcmVzcwkArAICCQCsAgICCG1pbmVyXzB4BQ1yZXdhcmRBZGRyZXNzAgNfUEsBD21pbmVyQ2hhaW5JZEtleQEFbWluZXIJAKwCAgkArAICAgZtaW5lcl8JAKUIAQUFbWluZXICCF9DaGFpbklkABRuYXRpdmVUcmFuc2ZlcnNDb3VudAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBRduYXRpdmVUcmFuc2ZlcnNDb3VudEtleQAAARFuYXRpdmVUcmFuc2ZlcktleQEFaW5kZXgJAKwCAgIPbmF0aXZlVHJhbnNmZXJfCQCkAwEFBWluZGV4ARVta05hdGl2ZVRyYW5zZmVyRW50cnkDBWluZGV4EGRlc3RFbEFkZHJlc3NIZXgGYW1vdW50CQELU3RyaW5nRW50cnkCCQERbmF0aXZlVHJhbnNmZXJLZXkBBQVpbmRleAkArAICCQCsAgIJAKwCAgICMHgFEGRlc3RFbEFkZHJlc3NIZXgFA1NFUAkApAMBBQZhbW91bnQBFmVuc3VyZUNvcnJlY3RUcmFuc2ZlcnMDEHJlZlRyYW5zZmVySW5kZXgNdHJhbnNmZXJJbmRleAxleHBlY3RSZXdhcmQEDG1heFRyYW5zZmVycwMFDGV4cGVjdFJld2FyZAkAZQIFFk1BWF9DTF9UT19FTF9UUkFOU0ZFUlMAAQUWTUFYX0NMX1RPX0VMX1RSQU5TRkVSUwQPYWN0dWFsVHJhbnNmZXJzCQBlAgUNdHJhbnNmZXJJbmRleAUQcmVmVHJhbnNmZXJJbmRleAQLY2hlY2tOdW1iZXIDCQBmAgUPYWN0dWFsVHJhbnNmZXJzBQxtYXhUcmFuc2ZlcnMJAAIBCQCsAgIJAKwCAgkArAICAg1BbGxvd2VkIG9ubHkgCQCkAwEFDG1heFRyYW5zZmVycwIQIHRyYW5zZmVycywgZ290IAkApAMBBQ9hY3R1YWxUcmFuc2ZlcnMGAwkAAAIFC2NoZWNrTnVtYmVyBQtjaGVja051bWJlcgMJAGcCBQ10cmFuc2ZlckluZGV4BRRuYXRpdmVUcmFuc2ZlcnNDb3VudAkAAgEJAKwCAgkArAICCQCsAgICFUF0dGVtcHQgdG8gdHJhbnNmZXIgIwkApAMBBQ10cmFuc2ZlckluZGV4AhcuIEF2YWlsYWJsZSB0cmFuc2ZlcnM6IAkApAMBBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAYJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BCmFtb3VudEd0RXEDAXQEZ3RFcQlxdWV1ZVNpemUDCQBnAggFAXQGYW1vdW50BQRndEVxBgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFFRyYW5zZmVycmluZyBhbW91bnQgCQCkAwEIBQF0BmFtb3VudAIOIHNob3VsZCBiZSA+PSAJAKQDAQUEZ3RFcQITIGZvciBxdWV1ZSBzaXplIG9mIAkApAMBBQlxdWV1ZVNpemUCFy4gVHJhbnNmZXIgbW9yZSBvciB3YWl0ARFnZW5lcmF0aW5nQmFsYW5jZQEHYWRkcmVzcwgJAO8HAQUHYWRkcmVzcwpnZW5lcmF0aW5nAQljaGFpbk1ldGEBB2NoYWluSWQEAXMJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkBAVpdGVtcwkAtQkCBQFzBQNTRVAJAJQKAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWl0ZW1zAAAJAJEDAgUFaXRlbXMAAQEQbWtDaGFpbk1ldGFFbnRyeQMHY2hhaW5JZA5uZXdDaGFpbkhlaWdodAxibG9ja0hhc2hIZXgJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgAC21haW5DaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDm1haW5DaGFpbklkS2V5AAAACyR0MDUyOTg1MzY0CQEJY2hhaW5NZXRhAQULbWFpbkNoYWluSWQAD21haW5DaGFpbkhlaWdodAgFCyR0MDUyOTg1MzY0Al8xABJtYWluQ2hhaW5MYXN0QmxvY2sIBQskdDA1Mjk4NTM2NAJfMgEJZXBvY2hNZXRhAQVlcG9jaAQHJG1hdGNoMAkAoggBCQEMZXBvY2hNZXRhS2V5AQUFZXBvY2gDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBAlmcmFnbWVudHMJALUJAgUBcwUDU0VQCQCVCgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUJZnJhZ21lbnRzAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmcmFnbWVudHMAAQkAkQMCBQlmcmFnbWVudHMAAgUEdW5pdAALJHQwNTU5NTU3MTkEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIWKEFkZHJlc3MsIEludCwgU3RyaW5nKQQBbQUHJG1hdGNoMAUBbQkAlAoCBQR1bml0AAAADnRoaXNFcG9jaE1pbmVyCAULJHQwNTU5NTU3MTkCXzEADHRoaXNFcG9jaFJlZggFCyR0MDU1OTU1NzE5Al8yAAxhbGxNaW5lcnNTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUMYWxsTWluZXJzS2V5AgAACWFsbE1pbmVycwQHJG1hdGNoMAUMYWxsTWluZXJzU3RyAwkAAAICAAUHJG1hdGNoMAUDbmlsAwkAAQIFByRtYXRjaDACBlN0cmluZwQDcmF3BQckbWF0Y2gwCQC8CQIFA3JhdwUDU0VQCQACAQILTWF0Y2ggZXJyb3IBCWJsb2NrTWV0YQEHYmxvY2tJZAQEbWV0YQkBEUBleHRyTmF0aXZlKDEwNTcpAQkArAICBQpibG9ja01ldGFLBQdibG9ja0lkBAhtZXRhU2l6ZQkAyAEBBQRtZXRhBAtibG9ja0hlaWdodAkAsQkBBQRtZXRhBApibG9ja0Vwb2NoCQCyCQIFBG1ldGEACAQLYmxvY2tQYXJlbnQJAMkBAgkAygECBQRtZXRhABAFD0JMT0NLX0hBU0hfU0laRQQHY2hhaW5JZAkAsgkCBQRtZXRhCQBkAgAQBQ9CTE9DS19IQVNIX1NJWkUECmJhc2VPZmZzZXQJAGQCABgFD0JMT0NLX0hBU0hfU0laRQQOcmVtYWluaW5nQnl0ZXMJAGUCBQhtZXRhU2l6ZQUKYmFzZU9mZnNldAQUZTJjVHJhbnNmZXJzUm9vdEhhc2gDCQBnAgUOcmVtYWluaW5nQnl0ZXMFDlJPT1RfSEFTSF9TSVpFCQDJAQIJAMoBAgUEbWV0YQUKYmFzZU9mZnNldAUOUk9PVF9IQVNIX1NJWkUBAAQUbGFzdEMyRVRyYW5zZmVySW5kZXgDAwkAAAIFDnJlbWFpbmluZ0J5dGVzAAgGCQBmAgUOcmVtYWluaW5nQnl0ZXMFDlJPT1RfSEFTSF9TSVpFCQCyCQIFBG1ldGEJAGQCBQpiYXNlT2Zmc2V0CQDIAQEFFGUyY1RyYW5zZmVyc1Jvb3RIYXNoAP///////////wEJAJgKBgULYmxvY2tIZWlnaHQFCmJsb2NrRXBvY2gFC2Jsb2NrUGFyZW50BQdjaGFpbklkBRRlMmNUcmFuc2ZlcnNSb290SGFzaAUUbGFzdEMyRVRyYW5zZmVySW5kZXgBEG1rQmxvY2tNZXRhRW50cnkGDGJsb2NrSGFzaEhleAtibG9ja0hlaWdodA5ibG9ja1BhcmVudEhleAdjaGFpbklkF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4FGxhc3RDMkVUcmFuc2ZlckluZGV4BBllMmNUcmFuc2ZlcnNSb290SGFzaEJ5dGVzCQDdBAEFF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4BBFyb290SGFzaEJ5dGVzU2l6ZQkAyAEBBRllMmNUcmFuc2ZlcnNSb290SGFzaEJ5dGVzBA1jaGVja1Jvb3RIYXNoAwMJAAACBRFyb290SGFzaEJ5dGVzU2l6ZQAABgkAAAIFEXJvb3RIYXNoQnl0ZXNTaXplBQ5ST09UX0hBU0hfU0laRQYJAAIBCQCsAgIJAKwCAgkArAICAiVUcmFuc2ZlcnMgcm9vdCBoYXNoIHNob3VsZCBoYXZlIDAgb3IgCQCkAwEFDlJPT1RfSEFTSF9TSVpFAgwgYnl0ZXMsIGdvdCAJAKQDAQURcm9vdEhhc2hCeXRlc1NpemUDCQAAAgUNY2hlY2tSb290SGFzaAUNY2hlY2tSb290SGFzaAQOYmxvY2tNZXRhQnl0ZXMJAMsBAgkAywECCQDLAQIJAMsBAgkAywECCQCaAwEFC2Jsb2NrSGVpZ2h0CQCaAwEFBmhlaWdodAkA3QQBBQ5ibG9ja1BhcmVudEhleAkAmgMBBQdjaGFpbklkBRllMmNUcmFuc2ZlcnNSb290SGFzaEJ5dGVzCQCaAwEFFGxhc3RDMkVUcmFuc2ZlckluZGV4CQELQmluYXJ5RW50cnkCCQCsAgIFCmJsb2NrTWV0YUsFDGJsb2NrSGFzaEhleAUOYmxvY2tNZXRhQnl0ZXMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BDGxhc3RIZWlnaHRCeQIFbWluZXIHY2hhaW5JZAQHJG1hdGNoMAkAnwgBCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAUFbWluZXIDCQABAgUHJG1hdGNoMAIDSW50BAFoBQckbWF0Y2gwBQFoBAlibG9ja0hhc2gJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAKwCAgkArAICCQCsAgICBWNoYWluCQCkAwEFB2NoYWluSWQCC0xhc3RNaW5lZEJ5CQClCAEFBW1pbmVyCAkBCWJsb2NrTWV0YQEFCWJsb2NrSGFzaAJfMQALJHQwNzc1OTg2OTQECWhpdFNvdXJjZQQHJG1hdGNoMAgFCWxhc3RCbG9jawN2cmYDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQDdnJmBQckbWF0Y2gwBQN2cmYIBQlsYXN0QmxvY2sTZ2VuZXJhdGlvblNpZ25hdHVyZQoBDHByb2Nlc3NNaW5lcgIEcHJldgVtaW5lcgQLJHQwODAyNjgwODkFBHByZXYECXByZXZNaW5lcggFCyR0MDgwMjY4MDg5Al8xBBBwcmV2VG90YWxCYWxhbmNlCAULJHQwODAyNjgwODkCXzIECXByZXZEZWxheQgFCyR0MDgwMjY4MDg5Al8zBApwcmV2TWluZXJzCAULJHQwODAyNjgwODkCXzQEDG1pbmVyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUFbWluZXIED3dhdmVzR2VuQmFsYW5jZQgJAO8HAQUMbWluZXJBZGRyZXNzCmdlbmVyYXRpbmcEDG1pbmVyQmFsYW5jZQkBEWdlbmVyYXRpbmdCYWxhbmNlAQUMbWluZXJBZGRyZXNzAwMJAGYCBQtNSU5fQkFMQU5DRQUPd2F2ZXNHZW5CYWxhbmNlBgkAZwIAAAUMbWluZXJCYWxhbmNlBQRwcmV2BAluZXh0RGVsYXkJAIUHAgUMbWluZXJBZGRyZXNzBQxtaW5lckJhbGFuY2UDCQBmAgUJcHJldkRlbGF5BQluZXh0RGVsYXkJAJYKBAUFbWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UFCW5leHREZWxheQkAzQgCBQpwcmV2TWluZXJzBQVtaW5lcgkAlgoEBQlwcmV2TWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UFCXByZXZEZWxheQkAzQgCBQpwcmV2TWluZXJzBQVtaW5lcgoAAiRsBQlhbGxNaW5lcnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCWCgQCAAAABQdJTlRfTUFYBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDHByb2Nlc3NNaW5lcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgNTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyABFjb21wdXRlZEdlbmVyYXRvcggFCyR0MDc3NTk4Njk0Al8xABRjb21wdXRlZFRvdGFsQmFsYW5jZQgFCyR0MDc3NTk4Njk0Al8yAAskdDA4Njk2ODc2MgkBCWJsb2NrTWV0YQEFEm1haW5DaGFpbkxhc3RCbG9jawAMbWNsYklnbm9yZWQxCAULJHQwODY5Njg3NjICXzEADm1haW5DaGFpbkVwb2NoCAULJHQwODY5Njg3NjICXzIBG2NhbGN1bGF0ZUZpbmFsaXplZEJsb2NrSGFzaAMIY3VyTWluZXIMY3VyUHJldkVwb2NoEGN1ckxhc3RCbG9ja0hhc2gEC29mZnNldHNfMTAwCQC8CQICZDo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjoCAAQLaGFsZkJhbGFuY2UJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACCgEEc3RlcAIEcHJldgRuZXh0BAskdDA5MTI4OTE5MgUEcHJldgQJdGhpc0Vwb2NoCAULJHQwOTEyODkxOTICXzEEDm1heWJlU2FmZUVwb2NoCAULJHQwOTEyODkxOTICXzIEDHRvdGFsQmFsYW5jZQgFCyR0MDkxMjg5MTkyAl8zBApwcmV2TWluZXJzCAULJHQwOTEyODkxOTICXzQEByRtYXRjaDAFDm1heWJlU2FmZUVwb2NoAwkAAQIFByRtYXRjaDACBFVuaXQECyR0MDkyNTA5NDE2AwkAAAIFCXRoaXNFcG9jaAUGaGVpZ2h0CQCVCgMFCGN1ck1pbmVyBQxjdXJQcmV2RXBvY2gFEGN1ckxhc3RCbG9ja0hhc2gJAQV2YWx1ZQEJAQllcG9jaE1ldGEBBQl0aGlzRXBvY2gEBW1pbmVyCAULJHQwOTI1MDk0MTYCXzEECXByZXZFcG9jaAgFCyR0MDkyNTA5NDE2Al8yBA1sYXN0QmxvY2tIYXNoCAULJHQwOTI1MDk0MTYCXzMDAwkAAAIFCXByZXZFcG9jaAAABgkAZwIJAGUCBQZoZWlnaHQFCXRoaXNFcG9jaABkCQCWCgQFCXRoaXNFcG9jaAUNbGFzdEJsb2NrSGFzaAUMdG90YWxCYWxhbmNlBQlhbGxNaW5lcnMECyR0MDk1NzA5NzcyAwkBD2NvbnRhaW5zRWxlbWVudAIFCnByZXZNaW5lcnMFBW1pbmVyCQCUCgIFDHRvdGFsQmFsYW5jZQUKcHJldk1pbmVycwkAlAoCCQBkAgUMdG90YWxCYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQVtaW5lcgkAzAgCBQVtaW5lcgUKcHJldk1pbmVycwQPbmV3VG90YWxCYWxhbmNlCAULJHQwOTU3MDk3NzICXzEECW5ld01pbmVycwgFCyR0MDk1NzA5NzcyAl8yAwkAZgIFD25ld1RvdGFsQmFsYW5jZQULaGFsZkJhbGFuY2UJAJYKBAUJdGhpc0Vwb2NoBQ1sYXN0QmxvY2tIYXNoBQ9uZXdUb3RhbEJhbGFuY2UFCWFsbE1pbmVycwkAlgoEBQlwcmV2RXBvY2gFBHVuaXQFD25ld1RvdGFsQmFsYW5jZQUJbmV3TWluZXJzBQRwcmV2BA0kdDAxMDAwNTEwMTAxCgACJGwFC29mZnNldHNfMTAwCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlgoEBQZoZWlnaHQFBHVuaXQAAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQRzdGVwAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhVMaXN0IHNpemUgZXhjZWVkcyAxMDAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZAQNZmFsbGJhY2tFcG9jaAgFDSR0MDEwMDA1MTAxMDECXzEEFWZpbmFsaXplZEJsb2NrSGFzaE9wdAgFDSR0MDEwMDA1MTAxMDECXzIEByRtYXRjaDAFFWZpbmFsaXplZEJsb2NrSGFzaE9wdAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEEmZpbmFsaXplZEJsb2NrSGFzaAUHJG1hdGNoMAUSZmluYWxpemVkQmxvY2tIYXNoCAkBBXZhbHVlAQkBCWVwb2NoTWV0YQEFDWZhbGxiYWNrRXBvY2gCXzMBEXN1cHBvcnRpbmdCYWxhbmNlAQdjaGFpbklkCgEKYWRkQmFsYW5jZQIDYWNjDGdlbmVyYXRvclN0cgQNJHQwMTAzNzExMDQwNwUDYWNjBAx0b3RhbEJhbGFuY2UIBQ0kdDAxMDM3MTEwNDA3Al8xBApnZW5lcmF0b3JzCAUNJHQwMTAzNzExMDQwNwJfMgQJZ2VuZXJhdG9yCQERQGV4dHJOYXRpdmUoMTA2MikBBQxnZW5lcmF0b3JTdHIDCQEPY29udGFpbnNFbGVtZW50AgUKZ2VuZXJhdG9ycwUJZ2VuZXJhdG9yBQNhY2MEB2JhbGFuY2UJARFnZW5lcmF0aW5nQmFsYW5jZQEFCWdlbmVyYXRvcgkAlAoCCQBkAgUMdG90YWxCYWxhbmNlBQdiYWxhbmNlCQDNCAIFCmdlbmVyYXRvcnMFCWdlbmVyYXRvcgQNYWxsR2VuZXJhdG9ycwkAvAkCCQERQGV4dHJOYXRpdmUoMTA1OCkBCQENc3VwcG9ydGVyc0tleQEFB2NoYWluSWQFA1NFUAQNJHQwMTA3MjkxMDc5NAoAAiRsBQ1hbGxHZW5lcmF0b3JzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCAAAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKYWRkQmFsYW5jZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIVTGlzdCBzaXplIGV4Y2VlZHMgMTAwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAYgBjAGQEB2JhbGFuY2UIBQ0kdDAxMDcyOTEwNzk0Al8xBAJfZwgFDSR0MDEwNzI5MTA3OTQCXzIFB2JhbGFuY2UBD2lzQ29udHJhY3RTZXR1cAAJAQlpc0RlZmluZWQBCQCfCAEFDm1pbmVyUmV3YXJkS2V5ARFlbnN1cmVNaW5pbmdFcG9jaAEJZ2VuZXJhdG9yAwkBAiE9AgkApQgBBQlnZW5lcmF0b3IFEWNvbXB1dGVkR2VuZXJhdG9yCQACAQkArAICCQCsAgIJAKwCAgkArAICCQDYBAEIBQlnZW5lcmF0b3IFYnl0ZXMCGyBpcyBub3QgYWxsb3dlZCB0byBtaW5lIGluIAkApAMBBQZoZWlnaHQCESBlcG9jaC4gRXhwZWN0ZWQgBRFjb21wdXRlZEdlbmVyYXRvcgUEdW5pdAESaXNSZWZlcmVuY2VDb3JyZWN0AglyZWZlcmVuY2UJbGFzdEJsb2NrAwkAAAIFCXJlZmVyZW5jZQUJbGFzdEJsb2NrBQR1bml0CQACAQkArAICCQCsAgIJAKwCAgIwRXhwZWN0ZWQgYSByZWZlcmVuY2UgdG8gdGhlIGNoYWluIGxhc3QgYmxvY2s6IDB4BQlsYXN0QmxvY2sCCS4gR290OiAweAUJcmVmZXJlbmNlAQ9jaGFpbklzSW5hY3RpdmUBB2NoYWluSWQEDGZpcnN0QmxvY2tJZAkBEUBleHRyTmF0aXZlKDEwNTgpAQkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUHY2hhaW5JZAQUZmlyc3RWYWxpZEFsdENoYWluSWQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUXZmlyc3RWYWxpZEFsdENoYWluSWRLZXkAAAMJAGYCBRRmaXJzdFZhbGlkQWx0Q2hhaW5JZAUHY2hhaW5JZAYJAGYCCAkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFEWZpbmFsaXplZEJsb2NrS2V5Al8xCAkBCWJsb2NrTWV0YQEFDGZpcnN0QmxvY2tJZAJfMQEMbWluZXJDaGFpbklkAQVtaW5lcgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEPbWluZXJDaGFpbklkS2V5AQUFbWluZXIJAJ8IAQkArAICAgljaGFpbklkT2YJAKUIAQUFbWluZXIBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwlnZW5lcmF0b3IPZXhwZWN0ZWRDaGFpbklkEGNoZWNrSGVpZ2h0QmxvY2sED2hlaWdodElzQ29ycmVjdAQHJG1hdGNoMAUQY2hlY2tIZWlnaHRCbG9jawMJAAECBQckbWF0Y2gwAgZTdHJpbmcECWJsb2NrSGFzaAUHJG1hdGNoMAQUbGFzdE1pbmVkQmxvY2tIZWlnaHQJAQxsYXN0SGVpZ2h0QnkCBQlnZW5lcmF0b3IFC21haW5DaGFpbklkCQBmAgkAZAIICQEJYmxvY2tNZXRhAQUJYmxvY2tIYXNoAl8xAAEFFGxhc3RNaW5lZEJsb2NrSGVpZ2h0BgQHJG1hdGNoMAkBDG1pbmVyQ2hhaW5JZAEFCWdlbmVyYXRvcgMJAAECBQckbWF0Y2gwAgNJbnQECWN1cnJlbnRJZAUHJG1hdGNoMAMDCQAAAgUJY3VycmVudElkBQ9leHBlY3RlZENoYWluSWQGAwkBD2NoYWluSXNJbmFjdGl2ZQEFCWN1cnJlbnRJZAUPaGVpZ2h0SXNDb3JyZWN0BwUEdW5pdAkAAgEJAKwCAgIcbWluZXIgaXMgbWluaW5nIG90aGVyIGNoYWluIAkApAMBBQljdXJyZW50SWQFBHVuaXQADGhlaWdodFN0cmluZwkArAICAgsgYXQgaGVpZ2h0IAkApAMBBQZoZWlnaHQBBXZyZkF0AQZoZWlnaHQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7QcBBQZoZWlnaHQJAKwCAgIbbGFzdCBibG9jayBpcyBub3QgYXZhaWxhYmxlBQxoZWlnaHRTdHJpbmcDdnJmCQCsAgICFFZSRiBpcyBub3QgYXZhaWxhYmxlBQxoZWlnaHRTdHJpbmcBEmVuc3VyZUNvcnJlY3RFcG9jaAELZXhwZWN0ZWRWUkYECWFjdHVhbFZSRgkBBXZyZkF0AQUGaGVpZ2h0AwkAAAIFC2V4cGVjdGVkVlJGBQlhY3R1YWxWUkYFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICDUV4cGVjdGVkIFZSRiAJANgEAQULZXhwZWN0ZWRWUkYCFyBkb2VzIG5vdCBtYXRjaCBhY3R1YWwgCQDYBAEFCWFjdHVhbFZSRgUMaGVpZ2h0U3RyaW5nAQxhZGRTdXBwb3J0ZXICB2NoYWluSWQJZ2VuZXJhdG9yBA1zdXBwb3J0ZXJzU3RyCQERQGV4dHJOYXRpdmUoMTA1OCkBCQENc3VwcG9ydGVyc0tleQEFB2NoYWluSWQECnN1cHBvcnRlcnMJALwJAgUNc3VwcG9ydGVyc1N0cgUDU0VQAwkBD2NvbnRhaW5zRWxlbWVudAIFCnN1cHBvcnRlcnMJAKUIAQUJZ2VuZXJhdG9yBQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDXN1cHBvcnRlcnNLZXkBBQdjaGFpbklkCQCsAgIJAKwCAgUNc3VwcG9ydGVyc1N0cgUDU0VQCQClCAEFCWdlbmVyYXRvcgUDbmlsAQlzZXRPckZhaWwCBWZsYWdzBWluZGV4AwkAZgIAAAUFaW5kZXgJAAIBCQCsAgICIkNhbid0IHdpdGhkcmF3IGF0IG5lZ2F0aXZlIGluZGV4OiAJAKQDAQUFaW5kZXgECWZsYWdzU2l6ZQkAsQIBBQVmbGFncwMJAGcCBQVpbmRleAUJZmxhZ3NTaXplBAlhZGRaZXJvZXMJAGUCBQVpbmRleAUJZmxhZ3NTaXplAwkAZgIFCWFkZFplcm9lcwkAsQIBBQl6ZXJvZXNTdHIJAAIBCQCsAgIJAKwCAgIKQ2FuJ3QgYWRkIAkApAMBBQlhZGRaZXJvZXMCJSBlbXB0eSBmbGFncy4gQ29udGFjdCB3aXRoIGRldmVsb3BlcnMJAKwCAgkArAICBQVmbGFncwkArwICBQl6ZXJvZXNTdHIFCWFkZFplcm9lcwIBMQQEdGFpbAkAsAICBQVmbGFncwUFaW5kZXgEB2F0SW5kZXgJAK8CAgUEdGFpbAABAwkAAAIFB2F0SW5kZXgCATAJAKwCAgkArAICCQCvAgIFBWZsYWdzBQVpbmRleAIBMQkAsAICBQR0YWlsAAEJAAIBCQCsAgIJAKwCAgIKVHJhbnNmZXIgIwkApAMBBQVpbmRleAIXIGhhcyBiZWVuIGFscmVhZHkgdGFrZW4BEXZhbGlkYXRlQmxvY2tIYXNoAQZoZXhTdHIEDGRlY29kZWRCeXRlcwkA3QQBBQZoZXhTdHIDCQECIT0CCQDIAQEFDGRlY29kZWRCeXRlcwUPQkxPQ0tfSEFTSF9TSVpFCQACAQIXaW52YWxpZCBibG9jayBpZCBsZW5ndGgFBmhleFN0cgEdZ2V0VXBkYXRlRmluYWxpemVkQmxvY2tBY3Rpb24DBmNhbGxlcg9uZXdCbG9ja0hhc2hIZXgJcHJldkVwb2NoBBdjdXJGaW5hbGl6ZWRCbG9ja0hlaWdodAgJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMQQVbmV3RmluYWxpemVkQmxvY2tIYXNoCQEbY2FsY3VsYXRlRmluYWxpemVkQmxvY2tIYXNoAwUGY2FsbGVyBQlwcmV2RXBvY2gFD25ld0Jsb2NrSGFzaEhleAMDCQAAAgUVbmV3RmluYWxpemVkQmxvY2tIYXNoBQ9uZXdCbG9ja0hhc2hIZXgGCQBmAggJAQlibG9ja01ldGEBBRVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gCXzEFF2N1ckZpbmFsaXplZEJsb2NrSGVpZ2h0CQDMCAIJAQtTdHJpbmdFbnRyeQIFEWZpbmFsaXplZEJsb2NrS2V5BRVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gFA25pbAUDbmlsCgFpAQ9leHRlbmRNYWluQ2hhaW4FDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgDdnJmF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4FGxhc3RDMkVUcmFuc2ZlckluZGV4BAtjYW5Db250aW51ZQkBFGNpcmN1aXRCcmVha2VyQ2xvc2VkAAMJAAACBQtjYW5Db250aW51ZQULY2FuQ29udGludWUEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUDdnJmAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gECmNoZWNrQ2hhaW4JAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQFBHVuaXQDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQOY2hlY2tSZWZlcmVuY2UJARJpc1JlZmVyZW5jZUNvcnJlY3QCBQxyZWZlcmVuY2VIZXgFEm1haW5DaGFpbkxhc3RCbG9jawMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al82BRRsYXN0QzJFVHJhbnNmZXJJbmRleAYDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQ5tYWluQ2hhaW5FcG9jaAUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkAwkAAAIFDXRoaXNFcG9jaE1ldGEFDXRoaXNFcG9jaE1ldGEEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFDm1haW5DaGFpbkVwb2NoBA5uZXdDaGFpbkhlaWdodAkAZAIFD21haW5DaGFpbkhlaWdodAABCQDOCAIJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkGBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BRJtYWluQ2hhaW5MYXN0QmxvY2sFC21haW5DaGFpbklkBRdlMmNUcmFuc2ZlcnNSb290SGFzaEhleAUUbGFzdEMyRVRyYW5zZmVySW5kZXgJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQttYWluQ2hhaW5JZAUObmV3Q2hhaW5IZWlnaHQFDGJsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD21pbmVyQ2hhaW5JZEtleQEIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCBQ10aGlzRXBvY2hNZXRhBQNuaWwFFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDXN0YXJ0QWx0Q2hhaW4FDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgDdnJmF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4FGxhc3RDMkVUcmFuc2ZlckluZGV4BAtjYW5Db250aW51ZQkBFGNpcmN1aXRCcmVha2VyQ2xvc2VkAAMJAAACBQtjYW5Db250aW51ZQULY2FuQ29udGludWUEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUDdnJmAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDSR0MDE2NDk5MTY2MTIJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgEDnJlZkNoYWluSGVpZ2h0CAUNJHQwMTY0OTkxNjYxMgJfMQQIcmVmRXBvY2gIBQ0kdDAxNjQ5OTE2NjEyAl8yBAtyZWZJZ25vcmVkMQgFDSR0MDE2NDk5MTY2MTICXzMEC3JlZklnbm9yZWQyCAUNJHQwMTY0OTkxNjYxMgJfNAQLcmVmSWdub3JlZDMIBQ0kdDAxNjQ5OTE2NjEyAl81BBByZWZUcmFuc2ZlckluZGV4CAUNJHQwMTY0OTkxNjYxMgJfNgQOZmluYWxpemVkRXBvY2gICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkCXzIECGVwb2NoUmVmAwkAZwIFCHJlZkVwb2NoBQ5maW5hbGl6ZWRFcG9jaAUIcmVmRXBvY2gJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICI0NhbiBub3Qgc3RhcnQgYWx0IGNoYWluIGZyb20gZXBvY2ggCQCkAwEFCHJlZkVwb2NoAggsIGVwb2NoIAkApAMBBQ5maW5hbGl6ZWRFcG9jaAINIGlzIGZpbmFsaXplZAQKY2hlY2tDaGFpbgkBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUMcmVmZXJlbmNlSGV4AwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4EDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMFEHJlZlRyYW5zZmVySW5kZXgFFGxhc3RDMkVUcmFuc2ZlckluZGV4BgMJAAACBQ5jaGVja1RyYW5zZmVycwUOY2hlY2tUcmFuc2ZlcnMECm5ld0NoYWluSWQJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAAAQQObmV3Q2hhaW5IZWlnaHQJAGQCBQ5yZWZDaGFpbkhlaWdodAABBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQhlcG9jaFJlZgUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkBA5jaGVja0dlbmVyYXRvcgkBEWVuc3VyZU1pbmluZ0Vwb2NoAQgFAWkMb3JpZ2luQ2FsbGVyAwkAAAIFDmNoZWNrR2VuZXJhdG9yBQ5jaGVja0dlbmVyYXRvcgkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJARBta0Jsb2NrTWV0YUVudHJ5BgUMYmxvY2tIYXNoSGV4BQ5uZXdDaGFpbkhlaWdodAUMcmVmZXJlbmNlSGV4BQpuZXdDaGFpbklkBRdlMmNUcmFuc2ZlcnNSb290SGFzaEhleAUUbGFzdEMyRVRyYW5zZmVySW5kZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUKbmV3Q2hhaW5JZAUMYmxvY2tIYXNoSGV4CQDMCAIJARBta0NoYWluTWV0YUVudHJ5AwUKbmV3Q2hhaW5JZAUObmV3Q2hhaW5IZWlnaHQFDGJsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD21pbmVyQ2hhaW5JZEtleQEIBQFpDG9yaWdpbkNhbGxlcgUKbmV3Q2hhaW5JZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFCm5ld0NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCCQENc3VwcG9ydGVyc0tleQEFCm5ld0NoYWluSWQJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5sYXN0Q2hhaW5JZEtleQUKbmV3Q2hhaW5JZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmV4dGVuZEFsdENoYWluBgxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4A3ZyZgdjaGFpbklkF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4FGxhc3RDMkVUcmFuc2ZlckluZGV4BAtjYW5Db250aW51ZQkBFGNpcmN1aXRCcmVha2VyQ2xvc2VkAAMJAAACBQtjYW5Db250aW51ZQULY2FuQ29udGludWUEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUDdnJmAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEE2NoYWluRmlyc3RCbG9ja01ldGEJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQdjaGFpbklkBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJANwEAQgFE2NoYWluRmlyc3RCbG9ja01ldGECXzMDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQNJHQwMTg5NzExOTAyNQkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMTg5NzExOTAyNQJfMQQOY2hhaW5MYXN0QmxvY2sIBQ0kdDAxODk3MTE5MDI1Al8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAUOY2hhaW5MYXN0QmxvY2sDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5jaGVja1RyYW5zZmVycwkBFmVuc3VyZUNvcnJlY3RUcmFuc2ZlcnMDCAkBCWJsb2NrTWV0YQEFDHJlZmVyZW5jZUhleAJfNgUUbGFzdEMyRVRyYW5zZmVySW5kZXgGAwkAAAIFDmNoZWNrVHJhbnNmZXJzBQ5jaGVja1RyYW5zZmVycwQObmV3Q2hhaW5IZWlnaHQJAGQCBQtjaGFpbkhlaWdodAABBAlwcmV2RXBvY2gICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al8yBBN1cGRhdGVNYWluQ2hhaW5EYXRhAwkAZgIJARFzdXBwb3J0aW5nQmFsYW5jZQEFB2NoYWluSWQJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACBAtsYXN0Q2hhaW5JZAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQ5sYXN0Q2hhaW5JZEtleQAABBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFCXByZXZFcG9jaAkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUY2hhaW5Gb3JrZWRIZWlnaHRLZXkBBQttYWluQ2hhaW5JZAgFE2NoYWluRmlyc3RCbG9ja01ldGECXzEJAMwIAgkBDEludGVnZXJFbnRyeQIFDm1haW5DaGFpbklkS2V5BQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdmaXJzdFZhbGlkQWx0Q2hhaW5JZEtleQkAZAIFC2xhc3RDaGFpbklkAAEFA25pbAUUdXBkYXRlRmluYWxpemVkQmxvY2sFA25pbAQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUJcHJldkVwb2NoBQNTRVAFDGJsb2NrSGFzaEhleAQFb3RoZXIFByRtYXRjaDAJAAIBAhVFcG9jaCBhbHJlYWR5IHN0YXJ0ZWQDCQAAAgUNdGhpc0Vwb2NoTWV0YQUNdGhpc0Vwb2NoTWV0YQQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEHXVwZGF0ZU1haW5DaGFpbkxhc3RNaW5lZEJsb2NrAwMJAAACBRN1cGRhdGVNYWluQ2hhaW5EYXRhBQNuaWwJAQIhPQIJAQt2YWx1ZU9yRWxzZQIJAQxtaW5lckNoYWluSWQBCAUBaQxvcmlnaW5DYWxsZXIAAAUHY2hhaW5JZAcJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyCAUTY2hhaW5GaXJzdEJsb2NrTWV0YQJfMQUDbmlsBQNuaWwJAM4IAgkAzggCCQDOCAIJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkGBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BQxyZWZlcmVuY2VIZXgFB2NoYWluSWQFF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4BRRsYXN0QzJFVHJhbnNmZXJJbmRleAkAzAgCCQEQbWtDaGFpbk1ldGFFbnRyeQMFB2NoYWluSWQFDm5ld0NoYWluSGVpZ2h0BQxibG9ja0hhc2hIZXgJAMwIAgUNdGhpc0Vwb2NoTWV0YQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD21pbmVyQ2hhaW5JZEtleQEIBQFpDG9yaWdpbkNhbGxlcgUHY2hhaW5JZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQFA25pbAUTdXBkYXRlTWFpbkNoYWluRGF0YQkBDGFkZFN1cHBvcnRlcgIFB2NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUddXBkYXRlTWFpbkNoYWluTGFzdE1pbmVkQmxvY2sJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELYXBwZW5kQmxvY2sEDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgXZTJjVHJhbnNmZXJzUm9vdEhhc2hIZXgUbGFzdEMyRVRyYW5zZmVySW5kZXgEC2NhbkNvbnRpbnVlCQEUY2lyY3VpdEJyZWFrZXJDbG9zZWQAAwkAAAIFC2NhbkNvbnRpbnVlBQtjYW5Db250aW51ZQQLY2hlY2tDYWxsZXIDCQAAAgUOdGhpc0Vwb2NoTWluZXIIBQFpDG9yaWdpbkNhbGxlcgYEByRtYXRjaDAFDnRoaXNFcG9jaE1pbmVyAwkAAQIFByRtYXRjaDACB0FkZHJlc3MECmVwb2NoTWluZXIFByRtYXRjaDAJAAIBCQCsAgICOW5vdCBhbGxvd2VkIHRvIGZvcmdlIGJsb2NrcyBpbiB0aGlzIGVwb2NoLCBleHBlY3RlZCBmcm9tIAkApQgBBQplcG9jaE1pbmVyCQACAQJAbm90IGFsbG93ZWQgdG8gZm9yZ2UgYmxvY2tzIGluIHRoaXMgZXBvY2gsIGVwb2NoIG1pbmVyIGlzIGFic2VudAMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIEB2NoYWluSWQJAQt2YWx1ZU9yRWxzZQIJAQxtaW5lckNoYWluSWQBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBA0kdDAyMTQyMDIxNDcxCQEJY2hhaW5NZXRhAQUHY2hhaW5JZAQLY2hhaW5IZWlnaHQIBQ0kdDAyMTQyMDIxNDcxAl8xBAtsYXN0QmxvY2tJZAgFDSR0MDIxNDIwMjE0NzECXzIEDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BQtsYXN0QmxvY2tJZAMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al82BRRsYXN0QzJFVHJhbnNmZXJJbmRleAcDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoCQDMCAIJARBta0Jsb2NrTWV0YUVudHJ5BgUMYmxvY2tIYXNoSGV4BQ5uZXdDaGFpbkhlaWdodAULbGFzdEJsb2NrSWQFB2NoYWluSWQFF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4BRRsYXN0QzJFVHJhbnNmZXJJbmRleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQdjaGFpbklkBQ5uZXdDaGFpbkhlaWdodAUMYmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCQEFdmFsdWUBBQ50aGlzRXBvY2hNaW5lcgUDU0VQCQCkAwEFDHRoaXNFcG9jaFJlZgUDU0VQBQxibG9ja0hhc2hIZXgFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQRqb2luARByZXdhcmRBZGRyZXNzSGV4BAtjYW5Db250aW51ZQkBFGNpcmN1aXRCcmVha2VyQ2xvc2VkAAMJAAACBQtjYW5Db250aW51ZQULY2FuQ29udGludWUKAR1lbnN1cmVOb3RPdmVycmlkZU90aGVyTWluZXJQawEMZWxBZGRyZXNzSGV4BAckbWF0Y2gwCQChCAEJAQptaW5lclBrS2V5AQUMZWxBZGRyZXNzSGV4AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwAwkAAAIFAnBrCAUBaRVvcmlnaW5DYWxsZXJQdWJsaWNLZXkFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAhFFTCBtaW5lciBhZGRyZXNzIAUMZWxBZGRyZXNzSGV4AhggaXMgYWxyZWFkeSBsaW5rZWQgd2l0aCAJANgEAQUCcGsFBHVuaXQEBXBhcnRzCQC1CQIFEHJld2FyZEFkZHJlc3NIZXgCAjB4BA1yZXdhcmRBZGRyZXNzCQDdBAEJAJEDAgUFcGFydHMJAGUCCQCQAwEFBXBhcnRzAAEDCQEBIQEJAQ9pc0NvbnRyYWN0U2V0dXAACQACAQIfVGhlIGNvbnRyYWN0IGhhcyBub3QgeWV0IHNldCB1cAMJAGYCBQtNSU5fQkFMQU5DRQgJAO8HAQgFAWkMb3JpZ2luQ2FsbGVyCmdlbmVyYXRpbmcJAAIBCQCsAgIJAKwCAgkArAICAiFJbnN1ZmZpY2llbnQgZ2VuZXJhdGluZyBiYWxhbmNlOiAJAKQDAQgJAO8HAQgFAWkMb3JpZ2luQ2FsbGVyCmdlbmVyYXRpbmcCDC4gUmVxdWlyZWQ6IAkApAMBBQtNSU5fQkFMQU5DRQMJAQIhPQIJAMgBAQUNcmV3YXJkQWRkcmVzcwAUCQACAQIlcmV3YXJkQWRkcmVzcyBzaG91bGQgYmUgYW4gTDIgYWRkcmVzcwMJAGcCCQCQAwEFCWFsbE1pbmVycwAyCQACAQIPdG9vIG1hbnkgbWluZXJzCgEOY2hlY2tFeGlzdGVuY2UCBmV4aXN0cwVtaW5lcgMFBmV4aXN0cwYJAAACBQVtaW5lcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEDWFscmVhZHlFeGlzdHMKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAcKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDmNoZWNrRXhpc3RlbmNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIDBQ1hbHJlYWR5RXhpc3RzBQNuaWwECG5ld01pbmVyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQWbG93ZXJjYXNlUmV3YXJkQWRkcmVzcwkA3AQBBQ1yZXdhcmRBZGRyZXNzBAVjaGVjawkBHWVuc3VyZU5vdE92ZXJyaWRlT3RoZXJNaW5lclBrAQUWbG93ZXJjYXNlUmV3YXJkQWRkcmVzcwMJAAACBQVjaGVjawUFY2hlY2sECW5ld01pbmVycwMJAAACCQCQAwEFCWFsbE1pbmVycwAABQhuZXdNaW5lcgkArAICCQCsAgIFDGFsbE1pbmVyc1N0cgUDU0VQBQhuZXdNaW5lcgQZZGVsZXRlUHJldlJld2FyZEFkZHJlc3NQawQHJG1hdGNoMAkAoggBCQEVbWluZXJSZXdhcmRBZGRyZXNzS2V5AQUIbmV3TWluZXIDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAtwcmV2QWRkcmVzcwUHJG1hdGNoMAMJAAACBQtwcmV2QWRkcmVzcwkA3AQBBQ1yZXdhcmRBZGRyZXNzBQNuaWwJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBCm1pbmVyUGtLZXkBBQtwcmV2QWRkcmVzcwUDbmlsBQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQxhbGxNaW5lcnNLZXkFCW5ld01pbmVycwkAzAgCCQELU3RyaW5nRW50cnkCCQEVbWluZXJSZXdhcmRBZGRyZXNzS2V5AQUIbmV3TWluZXIJAKwCAgICMHgFFmxvd2VyY2FzZVJld2FyZEFkZHJlc3MJAMwIAgkBC0JpbmFyeUVudHJ5AgkBCm1pbmVyUGtLZXkBBRZsb3dlcmNhc2VSZXdhcmRBZGRyZXNzCAUBaRVvcmlnaW5DYWxsZXJQdWJsaWNLZXkFA25pbAUZZGVsZXRlUHJldlJld2FyZEFkZHJlc3NQawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQVsZWF2ZQAEC2NhbkNvbnRpbnVlCQEUY2lyY3VpdEJyZWFrZXJDbG9zZWQAAwkAAAIFC2NhbkNvbnRpbnVlBQtjYW5Db250aW51ZQQMbGVhdmluZ01pbmVyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgoBEHNraXBMZWF2aW5nTWluZXICA2FjYwVtaW5lcgMJAAACBQVtaW5lcgUMbGVhdmluZ01pbmVyBQNhY2MJAM0IAgUDYWNjBQVtaW5lcgQPcmVtYWluaW5nTWluZXJzCgACJGwFCWFsbE1pbmVycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQc2tpcExlYXZpbmdNaW5lcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgNTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyBA1yZXdhcmRBZGRyS2V5CQEVbWluZXJSZXdhcmRBZGRyZXNzS2V5AQUMbGVhdmluZ01pbmVyBBFwcmV2UmV3YXJkQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFBHRoaXMFDXJld2FyZEFkZHJLZXkCFm1pbmVyIGhhcyBuZXZlciBqb2luZWQDCQAAAgURcHJldlJld2FyZEFkZHJlc3MFEXByZXZSZXdhcmRBZGRyZXNzAwkAAAIFDnRoaXNFcG9jaE1pbmVyCAUBaQxvcmlnaW5DYWxsZXIJAAIBAhxkZXNpZ25hdGVkIG1pbmVyIGNhbid0IGxlYXZlCQDMCAIJAQtTdHJpbmdFbnRyeQIFDGFsbE1pbmVyc0tleQkAugkCBQ9yZW1haW5pbmdNaW5lcnMFA1NFUAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCHRyYW5zZmVyARBkZXN0RWxBZGRyZXNzSGV4BAxjaGVja0FkZHJlc3MDCQAAAgkAsQIBBRBkZXN0RWxBZGRyZXNzSGV4BRRFVEhfQUREUkVTU19TVFJfU0laRQkA3QQBBRBkZXN0RWxBZGRyZXNzSGV4CQACAQkArAICCQCsAgIJAKwCAgIUQWRkcmVzcyBzaG91bGQgaGF2ZSAJAKQDAQUURVRIX0FERFJFU1NfU1RSX1NJWkUCESBjaGFyYWN0ZXJzLCBnb3QgCQCkAwEJALECAQUQZGVzdEVsQWRkcmVzc0hleAMJAAACBQxjaGVja0FkZHJlc3MFDGNoZWNrQWRkcmVzcwQMY2hlY2tQYXltZW50AwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAQYJAAIBCQCsAgICL0V4cGVjdGVkIG9uZSBwYXltZW50IGFzIGEgdHJhbnNmZXIgYW1vdW50LCBnb3QgCQCkAwEJAJADAQgFAWkIcGF5bWVudHMDCQAAAgUMY2hlY2tQYXltZW50BQxjaGVja1BheW1lbnQECnRva2VuSWRTdHIJARFAZXh0ck5hdGl2ZSgxMDU4KQEFCnRva2VuSWRLZXkEB3Rva2VuSWQJANkEAQUKdG9rZW5JZFN0cgQBdAkAkQMCCAUBaQhwYXltZW50cwAABAxjaGVja0Fzc2V0SWQEByRtYXRjaDAIBQF0B2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQHYXNzZXRJZAUHJG1hdGNoMAMJAAACBQdhc3NldElkBQd0b2tlbklkBgkAAgEJAKwCAgkArAICCQCsAgICCUV4cGVjdGVkIAUKdG9rZW5JZFN0cgIVIGluIHRoZSBwYXltZW50LCBnb3QgCQDYBAEFB2Fzc2V0SWQJAAIBCQCsAgIJAKwCAgIJRXhwZWN0ZWQgBQp0b2tlbklkU3RyAhogaW4gdGhlIHBheW1lbnQsIGdvdCBXYXZlcwMJAAACBQxjaGVja0Fzc2V0SWQFDGNoZWNrQXNzZXRJZAQJbGFzdEluZGV4CAkBCWJsb2NrTWV0YQEFEm1haW5DaGFpbkxhc3RCbG9jawJfNgQJcXVldWVTaXplCQBlAgUUbmF0aXZlVHJhbnNmZXJzQ291bnQFCWxhc3RJbmRleAQPY2hlY2tRdWV1ZUxpbWl0AwkAZgIAoAEFCXF1ZXVlU2l6ZQkBCmFtb3VudEd0RXEDBQF0AMCEPQUJcXVldWVTaXplAwkAZgIAwAwFCXF1ZXVlU2l6ZQkBCmFtb3VudEd0RXEDBQF0AICt4gQFCXF1ZXVlU2l6ZQMJAGYCAIAZBQlxdWV1ZVNpemUJAQphbW91bnRHdEVxAwUBdACAwtcvBQlxdWV1ZVNpemUDCQBmAgCAMgUJcXVldWVTaXplCQEKYW1vdW50R3RFcQMFAXQAgJTr3AMFCXF1ZXVlU2l6ZQkAAgEJAKwCAgkArAICAiNUcmFuc2ZlcnMgZGVuaWVkIGZvciBxdWV1ZSBzaXplIG9mIAkApAMBBQlxdWV1ZVNpemUCKC4gV2FpdCB1bnRpbCBjdXJyZW50IHRyYW5zZmVycyBwcm9jZXNzZWQDCQAAAgUPY2hlY2tRdWV1ZUxpbWl0BQ9jaGVja1F1ZXVlTGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFF25hdGl2ZVRyYW5zZmVyc0NvdW50S2V5CQBkAgUUbmF0aXZlVHJhbnNmZXJzQ291bnQAAQkAzAgCCQEVbWtOYXRpdmVUcmFuc2ZlckVudHJ5AwUUbmF0aXZlVHJhbnNmZXJzQ291bnQFEGRlc3RFbEFkZHJlc3NIZXgIBQF0BmFtb3VudAkAzAgCCQEEQnVybgIFB3Rva2VuSWQIBQF0BmFtb3VudAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCHdpdGhkcmF3BAxibG9ja0hhc2hIZXgLbWVya2xlUHJvb2YUdHJhbnNmZXJJbmRleEluQmxvY2sGYW1vdW50BBF3aXRoZHJhd0Jsb2NrTWV0YQkBCWJsb2NrTWV0YQEFDGJsb2NrSGFzaEhleAQTd2l0aGRyYXdCbG9ja0hlaWdodAgFEXdpdGhkcmF3QmxvY2tNZXRhAl8xBBRmaW5hbGl6ZWRCbG9ja0hlaWdodAgJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMQQYbWFpbkNoYWluTGFzdEJsb2NrSGVpZ2h0CAkBCWJsb2NrTWV0YQEFEm1haW5DaGFpbkxhc3RCbG9jawJfMQMJAGYCBRN3aXRoZHJhd0Jsb2NrSGVpZ2h0BRRmaW5hbGl6ZWRCbG9ja0hlaWdodAkAAgEJAKwCAgkArAICCQCsAgICCkVMIGJsb2NrICMJAKQDAQUTd2l0aGRyYXdCbG9ja0hlaWdodAItIGlzIG5vdCBmaW5hbGl6ZWQuIFRoZSBjdXJyZW50IGZpbmFsaXplZCBpcyAjCQCkAwEFFGZpbmFsaXplZEJsb2NrSGVpZ2h0AwkBAiE9AgkAkAMBBQttZXJrbGVQcm9vZgUUV0lUSERSQVdfUFJPT0ZTX1NJWkUJAAIBCQCsAgIJAKwCAgkArAICAglFeHBlY3RlZCAJAKQDAQUUV0lUSERSQVdfUFJPT0ZTX1NJWkUCDSBwcm9vZnMsIGdvdCAJAKQDAQkAkAMBBQttZXJrbGVQcm9vZgMJAGYCAAAFFHRyYW5zZmVySW5kZXhJbkJsb2NrCQACAQkArAICAjNUcmFuc2ZlciBpbmRleCBpbiBibG9jayBzaG91bGQgYmUgbm9ubmVnYXRpdmUsIGdvdCAJAKQDAQUUdHJhbnNmZXJJbmRleEluQmxvY2sDCQBnAgAABQZhbW91bnQJAAIBCQCsAgICH0Ftb3VudCBzaG91bGQgYmUgcG9zaXRpdmUsIGdvdCAJAKQDAQUGYW1vdW50BBR3aXRoZHJhd0Jsb2NrQ2hhaW5JZAgFEXdpdGhkcmF3QmxvY2tNZXRhAl80BAtpc01haW5DaGFpbgkAAAIFFHdpdGhkcmF3QmxvY2tDaGFpbklkBQttYWluQ2hhaW5JZAQScmVsYXRlc1RvTWFpbkNoYWluBAckbWF0Y2gwCQCfCAEJARRjaGFpbkZvcmtlZEhlaWdodEtleQEFFHdpdGhkcmF3QmxvY2tDaGFpbklkAwkAAQIFByRtYXRjaDACA0ludAQMZm9ya2VkSGVpZ2h0BQckbWF0Y2gwCQBmAgUMZm9ya2VkSGVpZ2h0BRN3aXRoZHJhd0Jsb2NrSGVpZ2h0CQACAQkArAICCQCsAgIJAKwCAgUMYmxvY2tIYXNoSGV4Ah0gaXMgb24gYW4gYWx0ZXJuYXRpdmUgY2hhaW4gIwkApAMBBRR3aXRoZHJhd0Jsb2NrQ2hhaW5JZAI4IHRoYXQgd2FzIG5vdCBhcHByb3ZlZCBieSBtYWpvcml0eS4gV2FpdCBmb3Igc29tZSBibG9ja3MDAwULaXNNYWluQ2hhaW4GBRJyZWxhdGVzVG9NYWluQ2hhaW4ECXJlY2lwaWVudAgFAWkMb3JpZ2luQ2FsbGVyBA9yZWNpcGllbnRQa0hhc2gJAMkBAgkAygECCAUJcmVjaXBpZW50BWJ5dGVzAAIFFFBVQkxJQ19LRVlfSEFTSF9TSVpFBA96ZXJvQW1vdW50Qnl0ZXMBLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAthbW91bnRCeXRlcwkAmgMBBQZhbW91bnQEC2VsRXZlbnREYXRhCQDLAQIJAMsBAgUPcmVjaXBpZW50UGtIYXNoCQDJAQIFD3plcm9BbW91bnRCeXRlcwkAZQIJAMgBAQUPemVyb0Ftb3VudEJ5dGVzCQDIAQEFC2Ftb3VudEJ5dGVzBQthbW91bnRCeXRlcwQRZWxFdmVudERhdGFEaWdlc3QJAPAVAQULZWxFdmVudERhdGEEEmNhbGN1bGF0ZWRSb290SGFzaAkAvQUDBQttZXJrbGVQcm9vZgURZWxFdmVudERhdGFEaWdlc3QFFHRyYW5zZmVySW5kZXhJbkJsb2NrBBBleHBlY3RlZFJvb3RIYXNoCAURd2l0aGRyYXdCbG9ja01ldGECXzUDCQAAAgUSY2FsY3VsYXRlZFJvb3RIYXNoBRBleHBlY3RlZFJvb3RIYXNoBAd0b2tlbklkCQDZBAEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFCnRva2VuSWRLZXkEDHRyYW5zZmVyc0tleQkBFGJsb2NrRTJDVHJhbnNmZXJzS2V5AQUMYmxvY2tIYXNoSGV4CQDMCAIJAQdSZWlzc3VlAwUHdG9rZW5JZAUGYW1vdW50BgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQlyZWNpcGllbnQFBmFtb3VudAUHdG9rZW5JZAkAzAgCCQELU3RyaW5nRW50cnkCBQx0cmFuc2ZlcnNLZXkJAQlzZXRPckZhaWwCCQELdmFsdWVPckVsc2UCCQCiCAEFDHRyYW5zZmVyc0tleQIABRR0cmFuc2ZlckluZGV4SW5CbG9jawUDbmlsCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIURXhwZWN0ZWQgcm9vdCBoYXNoOiAJANwEAQUQZXhwZWN0ZWRSb290SGFzaAIHLCBnb3Q6IAkA3AQBBRJjYWxjdWxhdGVkUm9vdEhhc2gCFS4gRXZlbnQgZGF0YSBkaWdlc3Q6IAkA2gQBBRFlbEV2ZW50RGF0YURpZ2VzdAIfLiBDaGVjayB5b3VyIHdpdGhkcmF3IGFyZ3VtZW50cwkAAgEJAKwCAgkArAICAglFeHBlY3RlZCAFDGJsb2NrSGFzaEhleAIvIHRvIGJlIGVpdGhlciBvbiB0aGUgbWFpbiBjaGFpbiBvciByZWxhdGUgdG8gaXQBaQEFc2V0dXACE2dlbmVzaXNCbG9ja0hhc2hIZXgRbWluZXJSZXdhcmRJbkd3ZWkDCQEPaXNDb250cmFjdFNldHVwAAkAAgECJFRoZSBjb250cmFjdCBoYXMgYmVlbiBhbHJlYWR5IHNldCB1cAMJAQIhPQIIBQFpDG9yaWdpbkNhbGxlcgUEdGhpcwkAAgEJAKwCAgIbc2V0dXAoKSBtdXN0IGJlIGludm9rZWQgYnkgCQClCAEFBHRoaXMDCQBmAgAABRFtaW5lclJld2FyZEluR3dlaQkAAgECJVRoZSBtaW5lciByZXdhcmQgbXVzdCBiZSBub24tbmVnYXRpdmUEEGdlbmVzaXNCbG9ja0hhc2gJAN0EAQUTZ2VuZXNpc0Jsb2NrSGFzaEhleAQZY2hlY2tHZW5lc2lzQmxvY2tIYXNoU2l6ZQMJAAACCQDIAQEFEGdlbmVzaXNCbG9ja0hhc2gFD0JMT0NLX0hBU0hfU0laRQYJAAIBAhhXcm9uZyBnZW5lc2lzIGJsb2NrIGhhc2gDCQAAAgUZY2hlY2tHZW5lc2lzQmxvY2tIYXNoU2l6ZQUZY2hlY2tHZW5lc2lzQmxvY2tIYXNoU2l6ZQQHZW1wdHlQawEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE2dlbmVzaXNNaW5lckFkZHJlc3MJAKcIAQUHZW1wdHlQawQXZ2VuZXNpc0V0aFJld2FyZEFkZHJlc3MBFAAAAAAAAAAAAAAAAAAAAAAAAAAABBlnZW5lc2lzQmxvY2tSZWZlcmVuY2VIYXNoAkAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBAVpc3N1ZQkAwggFAgVVTklUMQIMTmF0aXZlIHRva2VuAAAACAYEB3Rva2VuSWQJALgIAQUFaXNzdWUEEGdlbmVzaXNCbG9ja01ldGEJARBta0Jsb2NrTWV0YUVudHJ5BgUTZ2VuZXNpc0Jsb2NrSGFzaEhleAAABRlnZW5lc2lzQmxvY2tSZWZlcmVuY2VIYXNoAAAJANwEAQEAAP///////////wEJAMwIAgUQZ2VuZXNpc0Jsb2NrTWV0YQkAzAgCCQELU3RyaW5nRW50cnkCCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBAAAFE2dlbmVzaXNCbG9ja0hhc2hIZXgJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDAAAAAAUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgUObWluZXJSZXdhcmRLZXkFEW1pbmVyUmV3YXJkSW5Hd2VpCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQClCAEFE2dlbmVzaXNNaW5lckFkZHJlc3MCAywwLAUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCCQELU3RyaW5nRW50cnkCBRFmaW5hbGl6ZWRCbG9ja0tleQUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCBQVpc3N1ZQkAzAgCCQELU3RyaW5nRW50cnkCBQp0b2tlbklkS2V5CQDYBAEFB3Rva2VuSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUSZWxCcmlkZ2VBZGRyZXNzS2V5AioweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDZhN2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQRoYWx0AAQJc2VudGluZWxzCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBEUBleHRyTmF0aXZlKDEwNTMpAgUQZGFvQ29uZmlnQWRkcmVzcwIJc2VudGluZWxzAhZzZW50aW5lbCBsaXN0IGlzIGVtcHR5BQNTRVADCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCBQlzZW50aW5lbHMJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQACAQkArAICCQClCAEIBQFpDG9yaWdpbkNhbGxlcgISIGlzIG5vdCBhIHNlbnRpbmVsCQDMCAIJAQxCb29sZWFuRW50cnkCBRdjaXJjdWl0QnJlYWtlckNsb3NlZEtleQcFA25pbAECdHgBBnZlcmlmeQAEGGFsbG93QnJvYWRjYXN0RnJvbUhlaWdodAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUQZGFvQ29uZmlnQWRkcmVzcwIWY29udHJhY3Rfdm90aW5nX3Jlc3VsdAIZbm8gY29udHJhY3Rfdm90aW5nX3Jlc3VsdAImaW52YWxpZCBjb250cmFjdF92b3RpbmdfcmVzdWx0IGFkZHJlc3MJAKwCAgkArAICCQCsAgICGXByb3Bvc2FsX2FsbG93X2Jyb2FkY2FzdF8JAKUIAQUEdGhpcwIBXwkA2AQBCAUCdHgCaWQJAKwCAgIfbm8gdm90ZSByZXN1bHQgZm9yIHRyYW5zYWN0aW9uIAkA2AQBCAUCdHgCaWQDAwkBC3ZhbHVlT3JFbHNlAgkAmwgCBRBkYW9Db25maWdBZGRyZXNzAh5vcF9nb3Zlcm5hbmNlX2FwcGx5X3R4X2FsbG93ZWQGBgkAAgECGWNpcmN1aXQgYnJlYWtlciBpcyBvcGVuZWQJAGcCBQZoZWlnaHQFGGFsbG93QnJvYWRjYXN0RnJvbUhlaWdodAeGvGce", "height": 3309212, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 8 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let INT_MAX = 9223372036854775807
5+
6+let WAVES = 100000000
7+
8+let MIN_BALANCE = (20000 * WAVES)
9+
10+let SEP = ","
11+
12+let BLOCK_HASH_SIZE = 32
13+
14+let PUBLIC_KEY_HASH_SIZE = 20
15+
16+let ROOT_HASH_SIZE = 32
17+
18+let WITHDRAW_PROOFS_SIZE = 10
19+
20+let ETH_ADDRESS_STR_SIZE = 40
21+
22+let MAX_CL_TO_EL_TRANSFERS = 16
23+
24+let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
25+
26+let allMinersKey = "allMiners"
27+
28+let mainChainIdKey = "mainChainId"
29+
30+let lastChainIdKey = "lastChainId"
31+
32+let firstValidAltChainIdKey = "firstValidAltChainId"
33+
34+let minerRewardKey = "minerReward"
35+
36+let blockMetaK = "block_0x"
37+
38+let finalizedBlockKey = "finalizedBlock"
39+
40+let tokenIdKey = "tokenId"
41+
42+let elBridgeAddressKey = "elBridgeAddress"
43+
44+let nativeTransfersCountKey = "nativeTransfersCount"
45+
46+func pad (i) = {
47+ let s = toString(i)
48+ match size(s) {
49+ case _ =>
50+ if ((1 == $match0))
51+ then ("0000000" + s)
52+ else if ((2 == $match0))
53+ then ("000000" + s)
54+ else if ((3 == $match0))
55+ then ("00000" + s)
56+ else if ((4 == $match0))
57+ then ("0000" + s)
58+ else if ((5 == $match0))
59+ then ("000" + s)
60+ else if ((6 == $match0))
61+ then ("00" + s)
62+ else if ((7 == $match0))
63+ then ("0" + s)
64+ else s
65+ }
66+ }
67+
68+
69+let daoConfigAddress = addressFromStringValue("3N5c7DCCGmicNiHRGouUp3BaV6e8eDUDnHw")
70+
71+let circuitBreakerClosedKey = "circuitBreakerClosed"
72+
73+func circuitBreakerClosed () = if (valueOrElse(getBoolean(this, circuitBreakerClosedKey), true))
74+ then true
75+ else throw("circuit breaker is opened")
76+
77+
78+func blockE2CTransfersKey (blockHashHex) = ("elToClTransfers_0x" + blockHashHex)
79+
80+
81+func epochMetaKey (epoch) = ("epoch_" + pad(epoch))
82+
83+
84+func chainFirstBlockIdKey (chainId) = (("chain" + toString(chainId)) + "FirstBlock")
85+
86+
87+func chainMetaKey (chainId) = ("chain_" + pad(chainId))
88+
89+
90+func chainLastHeightKey (chainId,miner) = ((("chain_" + pad(chainId)) + "_") + toString(miner))
91+
92+
93+func chainForkedHeightKey (chainId) = (("chain_" + pad(chainId)) + "ForkedHeight")
94+
95+
96+func supportersKey (chainId) = (("chain" + toString(chainId)) + "Supporters")
97+
98+
99+func minerRewardAddressKey (minerAddr) = (("miner_" + minerAddr) + "_RewardAddress")
100+
101+
102+func minerPkKey (rewardAddress) = (("miner_0x" + rewardAddress) + "_PK")
103+
104+
105+func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId")
106+
107+
108+let nativeTransfersCount = valueOrElse(getInteger(this, nativeTransfersCountKey), 0)
109+
110+func nativeTransferKey (index) = ("nativeTransfer_" + toString(index))
111+
112+
113+func mkNativeTransferEntry (index,destElAddressHex,amount) = StringEntry(nativeTransferKey(index), ((("0x" + destElAddressHex) + SEP) + toString(amount)))
114+
115+
116+func ensureCorrectTransfers (refTransferIndex,transferIndex,expectReward) = {
117+ let maxTransfers = if (expectReward)
118+ then (MAX_CL_TO_EL_TRANSFERS - 1)
119+ else MAX_CL_TO_EL_TRANSFERS
120+ let actualTransfers = (transferIndex - refTransferIndex)
121+ let checkNumber = if ((actualTransfers > maxTransfers))
122+ then throw(((("Allowed only " + toString(maxTransfers)) + " transfers, got ") + toString(actualTransfers)))
123+ else true
124+ if ((checkNumber == checkNumber))
125+ then if ((transferIndex >= nativeTransfersCount))
126+ then throw(((("Attempt to transfer #" + toString(transferIndex)) + ". Available transfers: ") + toString(nativeTransfersCount)))
127+ else true
128+ else throw("Strict value is not equal to itself.")
129+ }
130+
131+
132+func amountGtEq (t,gtEq,queueSize) = if ((t.amount >= gtEq))
133+ then true
134+ else throw((((((("Transferring amount " + toString(t.amount)) + " should be >= ") + toString(gtEq)) + " for queue size of ") + toString(queueSize)) + ". Transfer more or wait"))
135+
136+
137+func generatingBalance (address) = wavesBalance(address).generating
138+
139+
140+func chainMeta (chainId) = {
141+ let s = getStringValue(chainMetaKey(chainId))
142+ let items = split(s, SEP)
143+ $Tuple2(parseIntValue(items[0]), items[1])
144+ }
145+
146+
147+func mkChainMetaEntry (chainId,newChainHeight,blockHashHex) = StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex))
148+
149+
150+let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0)
151+
152+let $t052985364 = chainMeta(mainChainId)
153+
154+let mainChainHeight = $t052985364._1
155+
156+let mainChainLastBlock = $t052985364._2
157+
158+func epochMeta (epoch) = match getString(epochMetaKey(epoch)) {
159+ case s: String =>
160+ let fragments = split(s, SEP)
161+ $Tuple3(addressFromStringValue(fragments[0]), parseIntValue(fragments[1]), fragments[2])
162+ case _ =>
163+ unit
164+}
165+
166+
167+let $t055955719 = match epochMeta(height) {
168+ case m: (Address, Int, String) =>
169+ m
170+ case _ =>
171+ $Tuple2(unit, 0)
172+}
173+
174+let thisEpochMiner = $t055955719._1
175+
176+let thisEpochRef = $t055955719._2
177+
178+let allMinersStr = valueOrElse(getString(allMinersKey), "")
179+
180+let allMiners = match allMinersStr {
181+ case _ =>
182+ if (("" == $match0))
183+ then nil
184+ else if ($isInstanceOf($match0, "String"))
185+ then {
186+ let raw = $match0
187+ split_4C(raw, SEP)
188+ }
189+ else throw("Match error")
190+}
191+
192+func blockMeta (blockId) = {
193+ let meta = getBinaryValue((blockMetaK + blockId))
194+ let metaSize = size(meta)
195+ let blockHeight = toInt(meta)
196+ let blockEpoch = toInt(meta, 8)
197+ let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE)
198+ let chainId = toInt(meta, (16 + BLOCK_HASH_SIZE))
199+ let baseOffset = (24 + BLOCK_HASH_SIZE)
200+ let remainingBytes = (metaSize - baseOffset)
201+ let e2cTransfersRootHash = if ((remainingBytes >= ROOT_HASH_SIZE))
202+ then take(drop(meta, baseOffset), ROOT_HASH_SIZE)
203+ else base58''
204+ let lastC2ETransferIndex = if (if ((remainingBytes == 8))
205+ then true
206+ else (remainingBytes > ROOT_HASH_SIZE))
207+ then toInt(meta, (baseOffset + size(e2cTransfersRootHash)))
208+ else -1
209+ $Tuple6(blockHeight, blockEpoch, blockParent, chainId, e2cTransfersRootHash, lastC2ETransferIndex)
210+ }
211+
212+
213+func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,chainId,e2cTransfersRootHashHex,lastC2ETransferIndex) = {
214+ let e2cTransfersRootHashBytes = fromBase16String(e2cTransfersRootHashHex)
215+ let rootHashBytesSize = size(e2cTransfersRootHashBytes)
216+ let checkRootHash = if (if ((rootHashBytesSize == 0))
217+ then true
218+ else (rootHashBytesSize == ROOT_HASH_SIZE))
219+ then true
220+ else throw(((("Transfers root hash should have 0 or " + toString(ROOT_HASH_SIZE)) + " bytes, got ") + toString(rootHashBytesSize)))
221+ if ((checkRootHash == checkRootHash))
222+ then {
223+ let blockMetaBytes = (((((toBytes(blockHeight) + toBytes(height)) + fromBase16String(blockParentHex)) + toBytes(chainId)) + e2cTransfersRootHashBytes) + toBytes(lastC2ETransferIndex))
224+ BinaryEntry((blockMetaK + blockHashHex), blockMetaBytes)
225+ }
226+ else throw("Strict value is not equal to itself.")
227+ }
228+
229+
230+func lastHeightBy (miner,chainId) = match getInteger(chainLastHeightKey(chainId, miner)) {
231+ case h: Int =>
232+ h
233+ case _ =>
234+ let blockHash = getStringValue(((("chain" + toString(chainId)) + "LastMinedBy") + toString(miner)))
235+ blockMeta(blockHash)._1
236+}
237+
238+
239+let $t077598694 = {
240+ let hitSource = match lastBlock.vrf {
241+ case vrf: ByteVector =>
242+ vrf
243+ case _ =>
244+ lastBlock.generationSignature
245+ }
246+ func processMiner (prev,miner) = {
247+ let $t080268089 = prev
248+ let prevMiner = $t080268089._1
249+ let prevTotalBalance = $t080268089._2
250+ let prevDelay = $t080268089._3
251+ let prevMiners = $t080268089._4
252+ let minerAddress = addressFromStringValue(miner)
253+ let wavesGenBalance = wavesBalance(minerAddress).generating
254+ let minerBalance = generatingBalance(minerAddress)
255+ if (if ((MIN_BALANCE > wavesGenBalance))
256+ then true
257+ else (0 >= minerBalance))
258+ then prev
259+ else {
260+ let nextDelay = calculateDelay(minerAddress, minerBalance)
261+ if ((prevDelay > nextDelay))
262+ then $Tuple4(miner, (prevTotalBalance + minerBalance), nextDelay, (prevMiners :+ miner))
263+ else $Tuple4(prevMiner, (prevTotalBalance + minerBalance), prevDelay, (prevMiners :+ miner))
264+ }
265+ }
266+
267+ let $l = allMiners
268+ let $s = size($l)
269+ let $acc0 = $Tuple4("", 0, INT_MAX, nil)
270+ func $f0_1 ($a,$i) = if (($i >= $s))
271+ then $a
272+ else processMiner($a, $l[$i])
273+
274+ func $f0_2 ($a,$i) = if (($i >= $s))
275+ then $a
276+ else throw("List size exceeds 50")
277+
278+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50)
279+ }
280+
281+let computedGenerator = $t077598694._1
282+
283+let computedTotalBalance = $t077598694._2
284+
285+let $t086968762 = blockMeta(mainChainLastBlock)
286+
287+let mclbIgnored1 = $t086968762._1
288+
289+let mainChainEpoch = $t086968762._2
290+
291+func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = {
292+ let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "")
293+ let halfBalance = (computedTotalBalance / 2)
294+ func step (prev,next) = {
295+ let $t091289192 = prev
296+ let thisEpoch = $t091289192._1
297+ let maybeSafeEpoch = $t091289192._2
298+ let totalBalance = $t091289192._3
299+ let prevMiners = $t091289192._4
300+ match maybeSafeEpoch {
301+ case _: Unit =>
302+ let $t092509416 = if ((thisEpoch == height))
303+ then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash)
304+ else value(epochMeta(thisEpoch))
305+ let miner = $t092509416._1
306+ let prevEpoch = $t092509416._2
307+ let lastBlockHash = $t092509416._3
308+ if (if ((prevEpoch == 0))
309+ then true
310+ else ((height - thisEpoch) >= 100))
311+ then $Tuple4(thisEpoch, lastBlockHash, totalBalance, allMiners)
312+ else {
313+ let $t095709772 = if (containsElement(prevMiners, miner))
314+ then $Tuple2(totalBalance, prevMiners)
315+ else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners)
316+ let newTotalBalance = $t095709772._1
317+ let newMiners = $t095709772._2
318+ if ((newTotalBalance > halfBalance))
319+ then $Tuple4(thisEpoch, lastBlockHash, newTotalBalance, allMiners)
320+ else $Tuple4(prevEpoch, unit, newTotalBalance, newMiners)
321+ }
322+ case _ =>
323+ prev
324+ }
325+ }
326+
327+ let $t01000510101 = {
328+ let $l = offsets_100
329+ let $s = size($l)
330+ let $acc0 = $Tuple4(height, unit, 0, nil)
331+ func $f0_1 ($a,$i) = if (($i >= $s))
332+ then $a
333+ else step($a, $l[$i])
334+
335+ func $f0_2 ($a,$i) = if (($i >= $s))
336+ then $a
337+ else throw("List size exceeds 100")
338+
339+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100)
340+ }
341+ let fallbackEpoch = $t01000510101._1
342+ let finalizedBlockHashOpt = $t01000510101._2
343+ match finalizedBlockHashOpt {
344+ case finalizedBlockHash: String =>
345+ finalizedBlockHash
346+ case _ =>
347+ value(epochMeta(fallbackEpoch))._3
348+ }
349+ }
350+
351+
352+func supportingBalance (chainId) = {
353+ func addBalance (acc,generatorStr) = {
354+ let $t01037110407 = acc
355+ let totalBalance = $t01037110407._1
356+ let generators = $t01037110407._2
357+ let generator = addressFromStringValue(generatorStr)
358+ if (containsElement(generators, generator))
359+ then acc
360+ else {
361+ let balance = generatingBalance(generator)
362+ $Tuple2((totalBalance + balance), (generators :+ generator))
363+ }
364+ }
365+
366+ let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP)
367+ let $t01072910794 = {
368+ let $l = allGenerators
369+ let $s = size($l)
370+ let $acc0 = $Tuple2(0, nil)
371+ func $f0_1 ($a,$i) = if (($i >= $s))
372+ then $a
373+ else addBalance($a, $l[$i])
374+
375+ func $f0_2 ($a,$i) = if (($i >= $s))
376+ then $a
377+ else throw("List size exceeds 100")
378+
379+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100)
380+ }
381+ let balance = $t01072910794._1
382+ let _g = $t01072910794._2
383+ balance
384+ }
385+
386+
387+func isContractSetup () = isDefined(getInteger(minerRewardKey))
388+
389+
390+func ensureMiningEpoch (generator) = if ((toString(generator) != computedGenerator))
391+ then throw(((((toBase58String(generator.bytes) + " is not allowed to mine in ") + toString(height)) + " epoch. Expected ") + computedGenerator))
392+ else unit
393+
394+
395+func isReferenceCorrect (reference,lastBlock) = if ((reference == lastBlock))
396+ then unit
397+ else throw(((("Expected a reference to the chain last block: 0x" + lastBlock) + ". Got: 0x") + reference))
398+
399+
400+func chainIsInactive (chainId) = {
401+ let firstBlockId = getStringValue(chainFirstBlockIdKey(chainId))
402+ let firstValidAltChainId = valueOrElse(getInteger(firstValidAltChainIdKey), 0)
403+ if ((firstValidAltChainId > chainId))
404+ then true
405+ else (blockMeta(getStringValue(finalizedBlockKey))._1 > blockMeta(firstBlockId)._1)
406+ }
407+
408+
409+func minerChainId (miner) = valueOrElse(getInteger(minerChainIdKey(miner)), getInteger(("chainIdOf" + toString(miner))))
410+
411+
412+func ensureExpectedOrInactiveChain (generator,expectedChainId,checkHeightBlock) = {
413+ let heightIsCorrect = match checkHeightBlock {
414+ case blockHash: String =>
415+ let lastMinedBlockHeight = lastHeightBy(generator, mainChainId)
416+ ((blockMeta(blockHash)._1 + 1) > lastMinedBlockHeight)
417+ case _ =>
418+ true
419+ }
420+ match minerChainId(generator) {
421+ case currentId: Int =>
422+ if (if ((currentId == expectedChainId))
423+ then true
424+ else if (chainIsInactive(currentId))
425+ then heightIsCorrect
426+ else false)
427+ then unit
428+ else throw(("miner is mining other chain " + toString(currentId)))
429+ case _ =>
430+ unit
431+ }
432+ }
433+
434+
435+let heightString = (" at height " + toString(height))
436+
437+func vrfAt (height) = valueOrErrorMessage(valueOrErrorMessage(blockInfoByHeight(height), ("last block is not available" + heightString)).vrf, ("VRF is not available" + heightString))
438+
439+
440+func ensureCorrectEpoch (expectedVRF) = {
441+ let actualVRF = vrfAt(height)
442+ if ((expectedVRF == actualVRF))
443+ then unit
444+ else throw((((("Expected VRF " + toBase58String(expectedVRF)) + " does not match actual ") + toBase58String(actualVRF)) + heightString))
445+ }
446+
447+
448+func addSupporter (chainId,generator) = {
449+ let supportersStr = getStringValue(supportersKey(chainId))
450+ let supporters = split_4C(supportersStr, SEP)
451+ if (containsElement(supporters, toString(generator)))
452+ then nil
453+ else [StringEntry(supportersKey(chainId), ((supportersStr + SEP) + toString(generator)))]
454+ }
455+
456+
457+func setOrFail (flags,index) = if ((0 > index))
458+ then throw(("Can't withdraw at negative index: " + toString(index)))
459+ else {
460+ let flagsSize = size(flags)
461+ if ((index >= flagsSize))
462+ then {
463+ let addZeroes = (index - flagsSize)
464+ if ((addZeroes > size(zeroesStr)))
465+ then throw((("Can't add " + toString(addZeroes)) + " empty flags. Contact with developers"))
466+ else ((flags + take(zeroesStr, addZeroes)) + "1")
467+ }
468+ else {
469+ let tail = drop(flags, index)
470+ let atIndex = take(tail, 1)
471+ if ((atIndex == "0"))
472+ then ((take(flags, index) + "1") + drop(tail, 1))
473+ else throw((("Transfer #" + toString(index)) + " has been already taken"))
474+ }
475+ }
476+
477+
478+func validateBlockHash (hexStr) = {
479+ let decodedBytes = fromBase16String(hexStr)
480+ if ((size(decodedBytes) != BLOCK_HASH_SIZE))
481+ then throw("invalid block id length")
482+ else hexStr
483+ }
484+
485+
486+func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = {
487+ let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
488+ let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex)
489+ if (if ((newFinalizedBlockHash == newBlockHashHex))
490+ then true
491+ else (blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight))
492+ then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)]
493+ else nil
494+ }
495+
496+
497+@Callable(i)
498+func extendMainChain (blockHashHex,referenceHex,vrf,e2cTransfersRootHashHex,lastC2ETransferIndex) = {
499+ let canContinue = circuitBreakerClosed()
500+ if ((canContinue == canContinue))
501+ then {
502+ let checkBlockHash = validateBlockHash(blockHashHex)
503+ if ((checkBlockHash == checkBlockHash))
504+ then {
505+ let checkEpoch = ensureCorrectEpoch(vrf)
506+ if ((checkEpoch == checkEpoch))
507+ then {
508+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
509+ if ((checkChain == checkChain))
510+ then {
511+ let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
512+ if ((checkReference == checkReference))
513+ then {
514+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastC2ETransferIndex, true)
515+ if ((checkTransfers == checkTransfers))
516+ then {
517+ let thisEpochMeta = match epochMeta(height) {
518+ case _: Unit =>
519+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
520+ case other =>
521+ throw("Epoch already started")
522+ }
523+ if ((thisEpochMeta == thisEpochMeta))
524+ then {
525+ let checkGenerator = ensureMiningEpoch(i.originCaller)
526+ if ((checkGenerator == checkGenerator))
527+ then {
528+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
529+ let newChainHeight = (mainChainHeight + 1)
530+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, mainChainId, e2cTransfersRootHashHex, lastC2ETransferIndex), mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
531+ }
532+ else throw("Strict value is not equal to itself.")
533+ }
534+ else throw("Strict value is not equal to itself.")
535+ }
536+ else throw("Strict value is not equal to itself.")
537+ }
538+ else throw("Strict value is not equal to itself.")
539+ }
540+ else throw("Strict value is not equal to itself.")
541+ }
542+ else throw("Strict value is not equal to itself.")
543+ }
544+ else throw("Strict value is not equal to itself.")
545+ }
546+ else throw("Strict value is not equal to itself.")
547+ }
548+
549+
550+
551+@Callable(i)
552+func startAltChain (blockHashHex,referenceHex,vrf,e2cTransfersRootHashHex,lastC2ETransferIndex) = {
553+ let canContinue = circuitBreakerClosed()
554+ if ((canContinue == canContinue))
555+ then {
556+ let checkBlockHash = validateBlockHash(blockHashHex)
557+ if ((checkBlockHash == checkBlockHash))
558+ then {
559+ let checkEpoch = ensureCorrectEpoch(vrf)
560+ if ((checkEpoch == checkEpoch))
561+ then {
562+ let $t01649916612 = blockMeta(referenceHex)
563+ let refChainHeight = $t01649916612._1
564+ let refEpoch = $t01649916612._2
565+ let refIgnored1 = $t01649916612._3
566+ let refIgnored2 = $t01649916612._4
567+ let refIgnored3 = $t01649916612._5
568+ let refTransferIndex = $t01649916612._6
569+ let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
570+ let epochRef = if ((refEpoch >= finalizedEpoch))
571+ then refEpoch
572+ else throw((((("Can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
573+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
574+ if ((checkChain == checkChain))
575+ then {
576+ let checkTransfers = ensureCorrectTransfers(refTransferIndex, lastC2ETransferIndex, true)
577+ if ((checkTransfers == checkTransfers))
578+ then {
579+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
580+ let newChainHeight = (refChainHeight + 1)
581+ let thisEpochMeta = match epochMeta(height) {
582+ case _: Unit =>
583+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
584+ case other =>
585+ throw("Epoch already started")
586+ }
587+ let checkGenerator = ensureMiningEpoch(i.originCaller)
588+ if ((checkGenerator == checkGenerator))
589+ then [thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, newChainId, e2cTransfersRootHashHex, lastC2ETransferIndex), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), mkChainMetaEntry(newChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
590+ else throw("Strict value is not equal to itself.")
591+ }
592+ else throw("Strict value is not equal to itself.")
593+ }
594+ else throw("Strict value is not equal to itself.")
595+ }
596+ else throw("Strict value is not equal to itself.")
597+ }
598+ else throw("Strict value is not equal to itself.")
599+ }
600+ else throw("Strict value is not equal to itself.")
601+ }
602+
603+
604+
605+@Callable(i)
606+func extendAltChain (blockHashHex,referenceHex,vrf,chainId,e2cTransfersRootHashHex,lastC2ETransferIndex) = {
607+ let canContinue = circuitBreakerClosed()
608+ if ((canContinue == canContinue))
609+ then {
610+ let checkBlockHash = validateBlockHash(blockHashHex)
611+ if ((checkBlockHash == checkBlockHash))
612+ then {
613+ let checkEpoch = ensureCorrectEpoch(vrf)
614+ if ((checkEpoch == checkEpoch))
615+ then {
616+ let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
617+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
618+ if ((checkChain == checkChain))
619+ then {
620+ let $t01897119025 = chainMeta(chainId)
621+ let chainHeight = $t01897119025._1
622+ let chainLastBlock = $t01897119025._2
623+ let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
624+ if ((checkReference == checkReference))
625+ then {
626+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastC2ETransferIndex, true)
627+ if ((checkTransfers == checkTransfers))
628+ then {
629+ let newChainHeight = (chainHeight + 1)
630+ let prevEpoch = blockMeta(referenceHex)._2
631+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
632+ then {
633+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
634+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
635+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
636+ }
637+ else nil
638+ let thisEpochMeta = match epochMeta(height) {
639+ case _: Unit =>
640+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
641+ case other =>
642+ throw("Epoch already started")
643+ }
644+ if ((thisEpochMeta == thisEpochMeta))
645+ then {
646+ let checkGenerator = ensureMiningEpoch(i.originCaller)
647+ if ((checkGenerator == checkGenerator))
648+ then {
649+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
650+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
651+ else false)
652+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
653+ else nil
654+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, chainId, e2cTransfersRootHashHex, lastC2ETransferIndex), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
655+ }
656+ else throw("Strict value is not equal to itself.")
657+ }
658+ else throw("Strict value is not equal to itself.")
659+ }
660+ else throw("Strict value is not equal to itself.")
661+ }
662+ else throw("Strict value is not equal to itself.")
663+ }
664+ else throw("Strict value is not equal to itself.")
665+ }
666+ else throw("Strict value is not equal to itself.")
667+ }
668+ else throw("Strict value is not equal to itself.")
669+ }
670+ else throw("Strict value is not equal to itself.")
671+ }
672+
673+
674+
675+@Callable(i)
676+func appendBlock (blockHashHex,referenceHex,e2cTransfersRootHashHex,lastC2ETransferIndex) = {
677+ let canContinue = circuitBreakerClosed()
678+ if ((canContinue == canContinue))
679+ then {
680+ let checkCaller = if ((thisEpochMiner == i.originCaller))
681+ then true
682+ else match thisEpochMiner {
683+ case epochMiner: Address =>
684+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
685+ case _ =>
686+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
687+ }
688+ if ((checkCaller == checkCaller))
689+ then {
690+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
691+ let $t02142021471 = chainMeta(chainId)
692+ let chainHeight = $t02142021471._1
693+ let lastBlockId = $t02142021471._2
694+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
695+ if ((checkReference == checkReference))
696+ then {
697+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastC2ETransferIndex, false)
698+ if ((checkTransfers == checkTransfers))
699+ then {
700+ let newChainHeight = (chainHeight + 1)
701+ let checkBlockHash = validateBlockHash(blockHashHex)
702+ if ((checkBlockHash == checkBlockHash))
703+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, chainId, e2cTransfersRootHashHex, lastC2ETransferIndex), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
704+ else throw("Strict value is not equal to itself.")
705+ }
706+ else throw("Strict value is not equal to itself.")
707+ }
708+ else throw("Strict value is not equal to itself.")
709+ }
710+ else throw("Strict value is not equal to itself.")
711+ }
712+ else throw("Strict value is not equal to itself.")
713+ }
714+
715+
716+
717+@Callable(i)
718+func join (rewardAddressHex) = {
719+ let canContinue = circuitBreakerClosed()
720+ if ((canContinue == canContinue))
721+ then {
722+ func ensureNotOverrideOtherMinerPk (elAddressHex) = match getBinary(minerPkKey(elAddressHex)) {
723+ case pk: ByteVector =>
724+ if ((pk == i.originCallerPublicKey))
725+ then unit
726+ else throw(((("EL miner address " + elAddressHex) + " is already linked with ") + toBase58String(pk)))
727+ case _ =>
728+ unit
729+ }
730+
731+ let parts = split(rewardAddressHex, "0x")
732+ let rewardAddress = fromBase16String(parts[(size(parts) - 1)])
733+ if (!(isContractSetup()))
734+ then throw("The contract has not yet set up")
735+ else if ((MIN_BALANCE > wavesBalance(i.originCaller).generating))
736+ then throw(((("Insufficient generating balance: " + toString(wavesBalance(i.originCaller).generating)) + ". Required: ") + toString(MIN_BALANCE)))
737+ else if ((size(rewardAddress) != 20))
738+ then throw("rewardAddress should be an L2 address")
739+ else if ((size(allMiners) >= 50))
740+ then throw("too many miners")
741+ else {
742+ func checkExistence (exists,miner) = if (exists)
743+ then true
744+ else (miner == toString(i.originCaller))
745+
746+ let alreadyExists = {
747+ let $l = allMiners
748+ let $s = size($l)
749+ let $acc0 = false
750+ func $f0_1 ($a,$i) = if (($i >= $s))
751+ then $a
752+ else checkExistence($a, $l[$i])
753+
754+ func $f0_2 ($a,$i) = if (($i >= $s))
755+ then $a
756+ else throw("List size exceeds 50")
757+
758+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50)
759+ }
760+ if (alreadyExists)
761+ then nil
762+ else {
763+ let newMiner = toString(i.originCaller)
764+ let lowercaseRewardAddress = toBase16String(rewardAddress)
765+ let check = ensureNotOverrideOtherMinerPk(lowercaseRewardAddress)
766+ if ((check == check))
767+ then {
768+ let newMiners = if ((size(allMiners) == 0))
769+ then newMiner
770+ else ((allMinersStr + SEP) + newMiner)
771+ let deletePrevRewardAddressPk = match getString(minerRewardAddressKey(newMiner)) {
772+ case prevAddress: String =>
773+ if ((prevAddress == toBase16String(rewardAddress)))
774+ then nil
775+ else [DeleteEntry(minerPkKey(prevAddress))]
776+ case _ =>
777+ nil
778+ }
779+ ([StringEntry(allMinersKey, newMiners), StringEntry(minerRewardAddressKey(newMiner), ("0x" + lowercaseRewardAddress)), BinaryEntry(minerPkKey(lowercaseRewardAddress), i.originCallerPublicKey)] ++ deletePrevRewardAddressPk)
780+ }
781+ else throw("Strict value is not equal to itself.")
782+ }
783+ }
784+ }
785+ else throw("Strict value is not equal to itself.")
786+ }
787+
788+
789+
790+@Callable(i)
791+func leave () = {
792+ let canContinue = circuitBreakerClosed()
793+ if ((canContinue == canContinue))
794+ then {
795+ let leavingMiner = toString(i.originCaller)
796+ func skipLeavingMiner (acc,miner) = if ((miner == leavingMiner))
797+ then acc
798+ else (acc :+ miner)
799+
800+ let remainingMiners = {
801+ let $l = allMiners
802+ let $s = size($l)
803+ let $acc0 = nil
804+ func $f0_1 ($a,$i) = if (($i >= $s))
805+ then $a
806+ else skipLeavingMiner($a, $l[$i])
807+
808+ func $f0_2 ($a,$i) = if (($i >= $s))
809+ then $a
810+ else throw("List size exceeds 50")
811+
812+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50)
813+ }
814+ let rewardAddrKey = minerRewardAddressKey(leavingMiner)
815+ let prevRewardAddress = valueOrErrorMessage(getString(this, rewardAddrKey), "miner has never joined")
816+ if ((prevRewardAddress == prevRewardAddress))
817+ then if ((thisEpochMiner == i.originCaller))
818+ then throw("designated miner can't leave")
819+ else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP))]
820+ else throw("Strict value is not equal to itself.")
821+ }
822+ else throw("Strict value is not equal to itself.")
823+ }
824+
825+
826+
827+@Callable(i)
828+func transfer (destElAddressHex) = {
829+ let checkAddress = if ((size(destElAddressHex) == ETH_ADDRESS_STR_SIZE))
830+ then fromBase16String(destElAddressHex)
831+ else throw(((("Address should have " + toString(ETH_ADDRESS_STR_SIZE)) + " characters, got ") + toString(size(destElAddressHex))))
832+ if ((checkAddress == checkAddress))
833+ then {
834+ let checkPayment = if ((size(i.payments) == 1))
835+ then true
836+ else throw(("Expected one payment as a transfer amount, got " + toString(size(i.payments))))
837+ if ((checkPayment == checkPayment))
838+ then {
839+ let tokenIdStr = getStringValue(tokenIdKey)
840+ let tokenId = fromBase58String(tokenIdStr)
841+ let t = i.payments[0]
842+ let checkAssetId = match t.assetId {
843+ case assetId: ByteVector =>
844+ if ((assetId == tokenId))
845+ then true
846+ else throw(((("Expected " + tokenIdStr) + " in the payment, got ") + toBase58String(assetId)))
847+ case _ =>
848+ throw((("Expected " + tokenIdStr) + " in the payment, got Waves"))
849+ }
850+ if ((checkAssetId == checkAssetId))
851+ then {
852+ let lastIndex = blockMeta(mainChainLastBlock)._6
853+ let queueSize = (nativeTransfersCount - lastIndex)
854+ let checkQueueLimit = if ((160 > queueSize))
855+ then amountGtEq(t, 1000000, queueSize)
856+ else if ((1600 > queueSize))
857+ then amountGtEq(t, 10000000, queueSize)
858+ else if ((3200 > queueSize))
859+ then amountGtEq(t, 100000000, queueSize)
860+ else if ((6400 > queueSize))
861+ then amountGtEq(t, 1000000000, queueSize)
862+ else throw((("Transfers denied for queue size of " + toString(queueSize)) + ". Wait until current transfers processed"))
863+ if ((checkQueueLimit == checkQueueLimit))
864+ then [IntegerEntry(nativeTransfersCountKey, (nativeTransfersCount + 1)), mkNativeTransferEntry(nativeTransfersCount, destElAddressHex, t.amount), Burn(tokenId, t.amount)]
865+ else throw("Strict value is not equal to itself.")
866+ }
867+ else throw("Strict value is not equal to itself.")
868+ }
869+ else throw("Strict value is not equal to itself.")
870+ }
871+ else throw("Strict value is not equal to itself.")
872+ }
873+
874+
875+
876+@Callable(i)
877+func withdraw (blockHashHex,merkleProof,transferIndexInBlock,amount) = {
878+ let withdrawBlockMeta = blockMeta(blockHashHex)
879+ let withdrawBlockHeight = withdrawBlockMeta._1
880+ let finalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
881+ let mainChainLastBlockHeight = blockMeta(mainChainLastBlock)._1
882+ if ((withdrawBlockHeight > finalizedBlockHeight))
883+ then throw(((("EL block #" + toString(withdrawBlockHeight)) + " is not finalized. The current finalized is #") + toString(finalizedBlockHeight)))
884+ else if ((size(merkleProof) != WITHDRAW_PROOFS_SIZE))
885+ then throw(((("Expected " + toString(WITHDRAW_PROOFS_SIZE)) + " proofs, got ") + toString(size(merkleProof))))
886+ else if ((0 > transferIndexInBlock))
887+ then throw(("Transfer index in block should be nonnegative, got " + toString(transferIndexInBlock)))
888+ else if ((0 >= amount))
889+ then throw(("Amount should be positive, got " + toString(amount)))
890+ else {
891+ let withdrawBlockChainId = withdrawBlockMeta._4
892+ let isMainChain = (withdrawBlockChainId == mainChainId)
893+ let relatesToMainChain = match getInteger(chainForkedHeightKey(withdrawBlockChainId)) {
894+ case forkedHeight: Int =>
895+ (forkedHeight > withdrawBlockHeight)
896+ case _ =>
897+ throw((((blockHashHex + " is on an alternative chain #") + toString(withdrawBlockChainId)) + " that was not approved by majority. Wait for some blocks"))
898+ }
899+ if (if (isMainChain)
900+ then true
901+ else relatesToMainChain)
902+ then {
903+ let recipient = i.originCaller
904+ let recipientPkHash = take(drop(recipient.bytes, 2), PUBLIC_KEY_HASH_SIZE)
905+ let zeroAmountBytes = base58'11111111111111111111111111111111111111111111'
906+ let amountBytes = toBytes(amount)
907+ let elEventData = ((recipientPkHash + take(zeroAmountBytes, (size(zeroAmountBytes) - size(amountBytes)))) + amountBytes)
908+ let elEventDataDigest = blake2b256_16Kb(elEventData)
909+ let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock)
910+ let expectedRootHash = withdrawBlockMeta._5
911+ if ((calculatedRootHash == expectedRootHash))
912+ then {
913+ let tokenId = fromBase58String(getStringValue(tokenIdKey))
914+ let transfersKey = blockE2CTransfersKey(blockHashHex)
915+[Reissue(tokenId, amount, true), ScriptTransfer(recipient, amount, tokenId), StringEntry(transfersKey, setOrFail(valueOrElse(getString(transfersKey), ""), transferIndexInBlock))]
916+ }
917+ else throw((((((("Expected root hash: " + toBase16String(expectedRootHash)) + ", got: ") + toBase16String(calculatedRootHash)) + ". Event data digest: ") + toBase64String(elEventDataDigest)) + ". Check your withdraw arguments"))
918+ }
919+ else throw((("Expected " + blockHashHex) + " to be either on the main chain or relate to it"))
920+ }
921+ }
922+
923+
924+
925+@Callable(i)
926+func setup (genesisBlockHashHex,minerRewardInGwei) = if (isContractSetup())
927+ then throw("The contract has been already set up")
928+ else if ((i.originCaller != this))
929+ then throw(("setup() must be invoked by " + toString(this)))
930+ else if ((0 > minerRewardInGwei))
931+ then throw("The miner reward must be non-negative")
932+ else {
933+ let genesisBlockHash = fromBase16String(genesisBlockHashHex)
934+ let checkGenesisBlockHashSize = if ((size(genesisBlockHash) == BLOCK_HASH_SIZE))
935+ then true
936+ else throw("Wrong genesis block hash")
937+ if ((checkGenesisBlockHashSize == checkGenesisBlockHashSize))
938+ then {
939+ let emptyPk = base58'11111111111111111111111111111111'
940+ let genesisMinerAddress = addressFromPublicKey(emptyPk)
941+ let genesisEthRewardAddress = base58'11111111111111111111'
942+ let genesisBlockReferenceHash = "0000000000000000000000000000000000000000000000000000000000000000"
943+ let issue = Issue("UNIT1", "Native token", 0, 8, true)
944+ let tokenId = calculateAssetId(issue)
945+ let genesisBlockMeta = mkBlockMetaEntry(genesisBlockHashHex, 0, genesisBlockReferenceHash, 0, toBase16String(base58''), -1)
946+[genesisBlockMeta, StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, "0x0000000000000000000000000000000000006a7e")]
947+ }
948+ else throw("Strict value is not equal to itself.")
949+ }
950+
951+
952+
953+@Callable(i)
954+func halt () = {
955+ let sentinels = split(valueOrErrorMessage(getStringValue(daoConfigAddress, "sentinels"), "sentinel list is empty"), SEP)
956+ if (!(containsElement(sentinels, toString(i.originCaller))))
957+ then throw((toString(i.originCaller) + " is not a sentinel"))
958+ else [BooleanEntry(circuitBreakerClosedKey, false)]
959+ }
960+
961+
962+@Verifier(tx)
963+func verify () = {
964+ let allowBroadcastFromHeight = valueOrErrorMessage(getInteger(valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(daoConfigAddress, "contract_voting_result"), "no contract_voting_result")), "invalid contract_voting_result address"), ((("proposal_allow_broadcast_" + toString(this)) + "_") + toBase58String(tx.id))), ("no vote result for transaction " + toBase58String(tx.id)))
965+ if (if (valueOrElse(getBoolean(daoConfigAddress, "op_governance_apply_tx_allowed"), true))
966+ then true
967+ else throw("circuit breaker is opened"))
968+ then (height >= allowBroadcastFromHeight)
969+ else false
970+ }
971+

github/deemru/w8io/169f3d6 
46.56 ms