tx · CoBrjfNs95XfyUDq5Y7tZvkNagsgkxdCcYKPrCHjZz5a

3N9be2mwrA52WJho6DiesZkk4351GvpnWuj:  -0.04300000 Waves

2023.02.13 19:05 [2448062] smart account 3N9be2mwrA52WJho6DiesZkk4351GvpnWuj > SELF 0.00000000 Waves

{ "type": 13, "id": "CoBrjfNs95XfyUDq5Y7tZvkNagsgkxdCcYKPrCHjZz5a", "fee": 4300000, "feeAssetId": null, "timestamp": 1676304352551, "version": 2, "chainId": 84, "sender": "3N9be2mwrA52WJho6DiesZkk4351GvpnWuj", "senderPublicKey": "6mzmbCza9iqbzxMEELcEA4Xc9NeF4CYpbTtz1zMK3C7x", "proofs": [ "3mHZJZwKpyRpgxCtyNvBzt7jQHYzsmSgrJ8roXVoj3WPQNnFZVDgaqhZhyrh9y2pC5hKLLf8uMANpNohUM3BMZ5g", "3i8LdSeoNrzb6GbvzoiNH5RkNN7ym2g6JnV77Ntye1rZq8Kz2F7d6fZUe4ANSVWMJe4u5tFS4kGPPRxeuT4kcQFJ", "ahHayP6yrrE1j7iqDAJJJ1ruCe8TmdRGwfHfVoR12DfazZ2xSZNkMSWZChjfY65VRvKbSM9g5qNALYnTGqdx1c8" ], "script": "base64:BgJhCAISDgoMCAgICAgIAQEBAQEBEgUKAwgIARIHCgUYAQEBARIAEgASBQoDCAEIEgMKAQESBAoCAQgSABIFCgMIAQESBAoCAQESBAoCCAESBgoECAEBCBIGCgQICAEBEgASALABAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgIBLgkAzAgCBQNrZXkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAEFbGNhbGMBAWwJALkIAQUBbAEOZ2V0TnVtYmVyQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkAAAEOZ2V0U3RyaW5nQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQNrZXkCAAEMZ2V0Qm9vbEJ5S2V5AQNrZXkJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUDa2V5BwEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQdhZGRyZXNzBQNrZXkAAAEYZ2V0U3RyaW5nQnlBZGRyZXNzQW5kS2V5AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAnQgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQdhZGRyZXNzBQNrZXkCAAEWZ2V0Qm9vbEJ5QWRkcmVzc0FuZEtleQIHYWRkcmVzcwNrZXkJAQt2YWx1ZU9yRWxzZQIJAJsIAgUHYWRkcmVzcwUDa2V5BwEJYXNBbnlMaXN0AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACCUxpc3RbQW55XQQBbAUHJG1hdGNoMAUBbAkAAgECG2ZhaWwgdG8gY2FzdCBpbnRvIExpc3RbQW55XQEIYXNTdHJpbmcBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBQFzCQACAQIYZmFpbCB0byBjYXN0IGludG8gU3RyaW5nAQVhc0ludAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgNJbnQEAWkFByRtYXRjaDAFAWkJAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBB2FzQnl0ZXMBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEB3ZhbEJ5dGUFByRtYXRjaDAFB3ZhbEJ5dGUJAAIBAhxmYWlsIHRvIGNhc3QgaW50byBCeXRlVmVjdG9yAQlhc1BheW1lbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIPQXR0YWNoZWRQYXltZW50BAFwBQckbWF0Y2gwBQFwCQACAQIhZmFpbCB0byBjYXN0IGludG8gQXR0YWNoZWRQYXltZW50ARJhc1N3YXBQYXJhbXNTVFJVQ1QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIjKEludCwgSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCkEBnN0cnVjdAUHJG1hdGNoMAUGc3RydWN0CQACAQIdZmFpbCB0byBjYXN0IGludG8gVHVwbGU1IGludHMAA1NFUAICX18AB0xJU1RTRVACAToABU1VTFQ4AIDC1y8ABU1VTFQ2AMCEPQAOREVGQVVMVFNXQVBGRUUAoJwBAAtCUlBST1RFQ1RFRACgjQYAB1dBVkVTSUQBBBOr2TMAD25NZXRyaWNJZHhQcmljZQAAABtuTWV0cmljSWR4VXNkbkxvY2tlZEJhbGFuY2UAAQAcbk1ldHJpY0lkeFdhdmVzTG9ja2VkQmFsYW5jZQACABFuTWV0cmljSWR4UmVzZXJ2ZQADABduTWV0cmljSWR4UmVzZXJ2ZUluVXNkbgAEABRuTWV0cmljSWR4VXNkblN1cHBseQAFABFuTWV0cmljSWR4U3VycGx1cwAGABhuTWV0cmljSWR4U3VycGx1c1BlcmNlbnQABwAMbk1ldHJpY0lkeEJSAAgAFG5NZXRyaWNJZHhOc2J0U3VwcGx5AAkAF25NZXRyaWNJZHhNYXhOc2J0U3VwcGx5AAoAFG5NZXRyaWNJZHhTdXJmU3VwcGx5AAsAEm5NZXRyaWNVc2RuVXNkdFBlZwAMABZuTWV0cmljQ3VycmVudFByaWNlQWRqAA0AEW5NZXRyaWNCYXNrZXRJbmZvAA4AFG5NZXRyaWNXZWlnaHRlZFByaWNlAA8AF25NZXRyaWNUb3RhbFJlc2VydmVzVXNkABAAGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAAQAYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwAAIAFElkeENvbnRyb2xDZmdScGREYXBwAAMAFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAEABxJZHhDb250cm9sQ2ZnTGlxdWlkYXRpb25EYXBwAAUAFUlkeENvbnRyb2xDZmdSZXN0RGFwcAAGAB1JZHhDb250cm9sQ2ZnTm9kZVJlZ2lzdHJ5RGFwcAAHABxJZHhDb250cm9sQ2ZnTnNidFN0YWtpbmdEYXBwAAgAGUlkeENvbnRyb2xDZmdNZWRpYXRvckRhcHAACQAcSWR4Q29udHJvbENmZ1N1cmZTdGFraW5nRGFwcAAKACBJZHhDb250cm9sQ2ZnR25zYnRDb250cm9sbGVyRGFwcAALABdJZHhDb250cm9sQ2ZnUmVzdFYyRGFwcAAMABtJZHhDb250cm9sQ2ZnR292ZXJuYW5jZURhcHAADQERa2V5Q29udHJvbEFkZHJlc3MAAhwlcyVzX19jb25maWdfX2NvbnRyb2xBZGRyZXNzAQ1rZXlDb250cm9sQ2ZnAAIRJXNfX2NvbnRyb2xDb25maWcBFHJlYWRDb250cm9sQ2ZnT3JGYWlsAQdjb250cm9sCQC8CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQdjb250cm9sCQENa2V5Q29udHJvbENmZwAFA1NFUAEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgpjb250cm9sQ2ZnA2lkeAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUKY29udHJvbENmZwUDaWR4CQCsAgICLUNvbnRyb2wgY2ZnIGRvZXNuJ3QgY29udGFpbiBhZGRyZXNzIGF0IGluZGV4IAkApAMBBQNpZHgAD2NvbnRyb2xDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQERa2V5Q29udHJvbEFkZHJlc3MAAiMzTjROUzdkNEpvOWE2RjE0TGlGVUtLWVZkVWtrZjJlUDRaeAAKY29udHJvbENmZwkBFHJlYWRDb250cm9sQ2ZnT3JGYWlsAQUPY29udHJvbENvbnRyYWN0AAxtYXRoQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRVJZHhDb250cm9sQ2ZnTWF0aERhcHAAE25zYnRTdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRxJZHhDb250cm9sQ2ZnTnNidFN0YWtpbmdEYXBwABNzdXJmU3Rha2luZ0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUcSWR4Q29udHJvbENmZ1N1cmZTdGFraW5nRGFwcAAXZ25zYnRDb250cm9sbGVyQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBSBJZHhDb250cm9sQ2ZnR25zYnRDb250cm9sbGVyRGFwcAAPYXVjdGlvbkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwABRub2RlUmVnaXN0cnlDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAtnb3ZDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAASTmV1dHJpbm9Bc3NldElkS2V5AhFuZXV0cmlub19hc3NldF9pZAAOQm9uZEFzc2V0SWRLZXkCDWJvbmRfYXNzZXRfaWQAEkF1Y3Rpb25Db250cmFjdEtleQIQYXVjdGlvbl9jb250cmFjdAAWTnNidFN0YWtpbmdDb250cmFjdEtleQITbnNidFN0YWtpbmdDb250cmFjdAAWTGlxdWlkYXRpb25Db250cmFjdEtleQIUbGlxdWlkYXRpb25fY29udHJhY3QADlJQRENvbnRyYWN0S2V5AgxycGRfY29udHJhY3QAEUNvbnRvbENvbnRyYWN0S2V5AhBjb250cm9sX2NvbnRyYWN0AA9NYXRoQ29udHJhY3RLZXkCDW1hdGhfY29udHJhY3QAG0JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbEtleQIbYmFsYW5jZV93YXZlc19sb2NrX2ludGVydmFsAB5CYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxLZXkCHmJhbGFuY2VfbmV1dHJpbm9fbG9ja19pbnRlcnZhbAEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQdhc3NldElkCQCsAgICHG1pbl9vdXROZXV0cmlub19zd2FwX2Ftb3VudF8FB2Fzc2V0SWQAGE1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQIYbWluX291dE11bHRpX3N3YXBfYW1vdW50ABtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkCFG5vZGVfb3JhY2xlX3Byb3ZpZGVyABVOZXV0cmlub091dEZlZVBhcnRLZXkCGG5ldXRyaW5vT3V0X3N3YXBfZmVlUGFydAASV2F2ZXNPdXRGZWVQYXJ0S2V5AhV3YXZlc091dF9zd2FwX2ZlZVBhcnQBD2tleU5vZGVSZWdpc3RyeQEHYWRkcmVzcwkArAICAgQlc19fBQdhZGRyZXNzAAhQcmljZUtleQIFcHJpY2UADVByaWNlSW5kZXhLZXkCC3ByaWNlX2luZGV4AAxJc0Jsb2NrZWRLZXkCCmlzX2Jsb2NrZWQBEmdldFByaWNlSGlzdG9yeUtleQEFYmxvY2sJAKwCAgkArAICBQhQcmljZUtleQIBXwkApAMBBQVibG9jawEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQVpbmRleAkArAICCQCsAgIFDVByaWNlSW5kZXhLZXkCAV8JAKQDAQUFaW5kZXgBFWdldFN0YWtpbmdOb2RlQnlJbmRleAEDaWR4CQEOZ2V0U3RyaW5nQnlLZXkBCQC5CQIJAMwIAgIGJXMlZCVzCQDMCAICBWxlYXNlCQDMCAIJAKQDAQUDaWR4CQDMCAICC25vZGVBZGRyZXNzBQNuaWwFA1NFUAEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEDaWR4CQERQGV4dHJOYXRpdmUoMTA2MikBCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQUDaWR4AR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVsZWFzZQkAzAgCAhdzcG9uc29yc2hpcFdhdmVzUmVzZXJ2ZQUDbmlsBQNTRVAJAGgCAOgHBQVNVUxUOAEYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AQVvd25lcgkArAICAhViYWxhbmNlX3VubG9ja19ibG9ja18FBW93bmVyAQ1nZXRMZWFzZUlkS2V5AQlub2RlSW5kZXgJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIFbGVhc2UJAMwIAgkApAMBBQlub2RlSW5kZXgJAMwIAgICaWQFA25pbAUDU0VQARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQtub2RlQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAg5sZWFzZUJ5QWRkcmVzcwkAzAgCBQtub2RlQWRkcmVzcwkAzAgCAgJpZAUDbmlsBQNTRVABEWdldExlYXNlQW1vdW50S2V5AQlub2RlSW5kZXgJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIFbGVhc2UJAMwIAgkApAMBBQlub2RlSW5kZXgJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBC25vZGVBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICDmxlYXNlQnlBZGRyZXNzCQDMCAIFC25vZGVBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQNTRVABGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEIZ3JvdXBOdW0JALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIKbGVhc2VHcm91cAkAzAgCCQCkAwEFCGdyb3VwTnVtCQDMCAICCG5vZGVMaXN0BQNuaWwFA1NFUAEQbWluU3dhcEFtb3VudEtFWQEIc3dhcFR5cGUJAKwCAgkArAICAgRtaW5fBQhzd2FwVHlwZQIMX3N3YXBfYW1vdW50AQ50b3RhbExvY2tlZEtFWQIIc3dhcFR5cGUHYXNzZXRJZAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtiYWxhbmNlTG9jawkAzAgCBQhzd2FwVHlwZQkAzAgCBQdhc3NldElkBQNuaWwFA1NFUAEUdG90YWxMb2NrZWRCeVVzZXJLRVkDCHN3YXBUeXBlBW93bmVyB2Fzc2V0SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCAgtiYWxhbmNlTG9jawkAzAgCBQhzd2FwVHlwZQkAzAgCBQVvd25lcgkAzAgCBQdhc3NldElkBQNuaWwCAV8BFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBCHN3YXBUeXBlAwkAAAIFCHN3YXBUeXBlAghvdXRNdWx0aQUeQmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsS2V5BRtCYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxLZXkBGm5vZGVCYWxhbmNlTG9ja0ludGVydmFsS0VZAAIaYmFsYW5jZV9ub2RlX2xvY2tfaW50ZXJ2YWwBEXN3YXBzVGltZWZyYW1lS0VZAAIPc3dhcHNfdGltZWZyYW1lAQ5iclByb3RlY3RlZEtFWQACF21pbl9CUl9wcm90ZWN0aW9uX2xldmVsAQ9iYXNrZXRBc3NldHNLZXkAAholcyVzX19jb21tb25fX2Jhc2tldEFzc2V0cwEKYmFza2V0REtleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0RAEKYmFza2V0S0tleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0SwEKYmFza2V0QktleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0QgESYmFza2V0TG9nYkRlbHRhS2V5AAIdJXMlc19fY29tbW9uX19iYXNrZXRMb2diRGVsdGEBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBB2Fzc2V0SWQJAKwCAgIfJXMlcyVzX19jb21tb25fX3dlaWdodEJ5QXNzZXRfXwUHYXNzZXRJZAERbWluU3dhcEFtb3VudFJFQUQCCHN3YXBUeXBlB2Fzc2V0SWQJAQt2YWx1ZU9yRWxzZQIDCQAAAgUIc3dhcFR5cGUCCG91dE11bHRpCQCfCAEFGE1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQkAnwgBCQEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQUHYXNzZXRJZAAAARJzd2Fwc1RpbWVmcmFtZVJFQUQACQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARFzd2Fwc1RpbWVmcmFtZUtFWQAAoAsBD3RvdGFsTG9ja2VkUkVBRAIIc3dhcFR5cGUHYXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOdG90YWxMb2NrZWRLRVkCBQhzd2FwVHlwZQUHYXNzZXRJZAAAARV0b3RhbExvY2tlZEJ5VXNlclJFQUQDCHN3YXBUeXBlBW93bmVyB2Fzc2V0SWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFHRvdGFsTG9ja2VkQnlVc2VyS0VZAwUIc3dhcFR5cGUFBW93bmVyBQdhc3NldElkAAABF2JhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAQhzd2FwVHlwZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEWYmFsYW5jZUxvY2tJbnRlcnZhbEtFWQEFCHN3YXBUeXBlAKALARtub2RlQmFsYW5jZUxvY2tJbnRlcnZhbFJFQUQACQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARpub2RlQmFsYW5jZUxvY2tJbnRlcnZhbEtFWQAAAQEYa2V5U3dhcFVzZXJTcGVudEluUGVyaW9kAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBCVzJXMJAMwIAgIVc3dhcFVzZXJTcGVudEluUGVyaW9kCQDMCAIFC3VzZXJBZGRyZXNzBQNuaWwFA1NFUAEVa2V5VXNlckxhc3RTd2FwSGVpZ2h0AQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBCVzJXMJAMwIAgISdXNlckxhc3RTd2FwSGVpZ2h0CQDMCAIFC3VzZXJBZGRyZXNzBQNuaWwFA1NFUAEWY29udmVydE5ldXRyaW5vVG9XYXZlcwIGYW1vdW50BXByaWNlCQBrAwUGYW1vdW50BQVNVUxUOAUFcHJpY2UBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBmFtb3VudAVwcmljZQkAawMFBmFtb3VudAUFcHJpY2UFBU1VTFQ4ARJjb252ZXJ0V2F2ZXNUb0JvbmQCBmFtb3VudAVwcmljZQkBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBQZhbW91bnQFBXByaWNlARZjb252ZXJ0SnNvbkFycmF5VG9MaXN0AQlqc29uQXJyYXkJALUJAgUJanNvbkFycmF5AgEsARtjb252ZXJ0QmFza2V0SXRlbVRvTmV1dHJpbm8ECGluQW1vdW50B2luQXNzZXQNYmFza2V0SW5mb1N0cg1uZXV0cmlub1ByaWNlBApiYXNrZXRJbmZvCQC1CQIFDWJhc2tldEluZm9TdHICAV8KAQhmaW5kSXRlbQIDYWNjBGl0ZW0EBWJJdGVtCQC1CQIFBGl0ZW0FB0xJU1RTRVADCQAAAgkAkQMCBQViSXRlbQAABQdpbkFzc2V0BQViSXRlbQUDYWNjBAJpdAoAAiRsBQpiYXNrZXRJbmZvCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhmaW5kSXRlbQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQFZGxvZzYJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmJhc2tldExvZ2JEZWx0YUtleQAA3qOD9///////AQQCZDYJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBCmJhc2tldERLZXkAANCGAwQCYjYJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBCmJhc2tldEJLZXkAANClTAQCdzYJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBBQdpbkFzc2V0AIqWCgQCcDYJAGQCCQBlAgUFZGxvZzYFAnc2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaXQAAQQDcHA2CQBsBgUCYjYABgUCcDYABgAGBQZIQUxGVVAEDm91dEFtb3VudEdyb3NzCQBrAwUIaW5BbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJpdAACAwkAAAIFDW5ldXRyaW5vUHJpY2UAAAUFTVVMVDgJAGgCBQ1uZXV0cmlub1ByaWNlAGQECm11bHRpcGxpZXIJAGUCCQBkAgUFTVVMVDYFAmQ2BQNwcDYECW5ldEFtb3VudAkAawMFDm91dEFtb3VudEdyb3NzBQptdWx0aXBsaWVyBQVNVUxUNgQJZmVlQW1vdW50AwkAZwIFCW5ldEFtb3VudAUOb3V0QW1vdW50R3Jvc3MAAAkAZQIFDm91dEFtb3VudEdyb3NzBQluZXRBbW91bnQJAMwIAgUOb3V0QW1vdW50R3Jvc3MJAMwIAgUJbmV0QW1vdW50CQDMCAIFCWZlZUFtb3VudAUDbmlsARdjb252ZXJ0TmV1dHJpbm9Ub0Jhc2tldAMGYW1vdW50DWJhc2tldEluZm9TdHIObmV1dHJpbm9TdXBwbHkECmJhc2tldEluZm8JALUJAgUNYmFza2V0SW5mb1N0cgIBXwoBBGNvbnYCA2FjYwRpdGVtBAVwYXJ0cwkAtQkCBQRpdGVtBQdMSVNUU0VQBAdhc3NldElkCQCRAwIFBXBhcnRzAAAEBXNoYXJlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQQFcHJpY2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwYXJ0cwACBAZyZXNlcnYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwYXJ0cwADAwkAAAIFDm5ldXRyaW5vU3VwcGx5AAAJAAIBAidBdHRlbXB0IHRvIGJ1cm4gbmV1dHJpbm8gYXQgemVybyBzdXBwbHkECW91dEFtb3VudAkAawMFBmFtb3VudAUGcmVzZXJ2BQ5uZXV0cmlub1N1cHBseQQKd2F2ZXNUdXBsZQMJAAACBQdhc3NldElkAgVXQVZFUwkAlAoCBQlvdXRBbW91bnQFBXByaWNlCQCUCgIIBQNhY2MCXzIIBQNhY2MCXzMJAJUKAwkAzQgCCAUDYWNjAl8xCQCWCgQFB2Fzc2V0SWQFCW91dEFtb3VudAUFcHJpY2UFBXNoYXJlCAUKd2F2ZXNUdXBsZQJfMQgFCndhdmVzVHVwbGUCXzIKAAIkbAUKYmFza2V0SW5mbwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJUKAwUDbmlsAAAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEY29udgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgERbWluU3dhcEFtb3VudEZBSUwCCHN3YXBUeXBlDW1pblN3YXBBbW91bnQJAAIBCQCsAgIJAKwCAgkArAICAhhUaGUgc3BlY2lmaWVkIGFtb3VudCBpbiAFCHN3YXBUeXBlAisgc3dhcCBpcyBsZXNzIHRoYW4gdGhlIHJlcXVpcmVkIG1pbmltdW0gb2YgCQCkAwEFDW1pblN3YXBBbW91bnQBFWVtZXJnZW5jeVNodXRkb3duRkFJTAAJAAIBAlpjb250cmFjdCBpcyBibG9ja2VkIGJ5IEVNRVJHRU5DWSBTSFVURE9XTiBhY3Rpb25zIHVudGlsbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMBDnByaWNlSW5kZXhGQUlMBQVpbmRleApwcmljZUluZGV4C2luZGV4SGVpZ2h0DHVubG9ja0hlaWdodA9wcmV2SW5kZXhIZWlnaHQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAiNpbnZhbGlkIHByaWNlIGhpc3RvcnkgaW5kZXg6IGluZGV4PQkApAMBBQVpbmRleAIMIHByaWNlSW5kZXg9CQCkAwEFCnByaWNlSW5kZXgCDSBpbmRleEhlaWdodD0JAKQDAQULaW5kZXhIZWlnaHQCDiB1bmxvY2tIZWlnaHQ9CQCkAwEFDHVubG9ja0hlaWdodAIRIHByZXZJbmRleEhlaWdodD0JAKQDAQUPcHJldkluZGV4SGVpZ2h0AA9uZXV0cmlub0Fzc2V0SWQJANkEAQkBDmdldFN0cmluZ0J5S2V5AQUSTmV1dHJpbm9Bc3NldElkS2V5AApwcmljZUluZGV4CQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0BQ1QcmljZUluZGV4S2V5AAlpc0Jsb2NrZWQJARZnZXRCb29sQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0BQxJc0Jsb2NrZWRLZXkAGG5vZGVPcmFjbGVQcm92aWRlclB1YktleQkA2QQBCQEOZ2V0U3RyaW5nQnlLZXkBBRtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkAC2JvbmRBc3NldElkCQDZBAECLEYzaWF4enJ1RmVLdWpmVmZZU1pFa2VqcGpoNjd3bVJmUENSSGlObVdLcDNaABVkZXByZWNhdGVkQm9uZEFzc2V0SWQJANkEAQIsOTc1YWtaQmZuTWo1MTNVN01aYUhLelFybXNFeDVhRTN3ZFdLVHJIQmhiakYAEG5ldXRyaW5vQ29udHJhY3QFBHRoaXMADGN1cnJlbnRQcmljZQkBGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQIFD2NvbnRyb2xDb250cmFjdAUIUHJpY2VLZXkBG2NoZWNrSXNWYWxpZE1pblNwb25zb3JlZEZlZQECdHgEDk1JTlRSQU5TRkVSRkVFAKCNBgQWU3BvbnNvcmVkRmVlVXBwZXJCb3VuZADoBwQPcmVhbE5ldXRyaW5vRmVlCQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIFDk1JTlRSQU5TRkVSRkVFBQxjdXJyZW50UHJpY2UEDm1pbk5ldXRyaW5vRmVlCQBoAgUPcmVhbE5ldXRyaW5vRmVlAAIEDm1heE5ldXRyaW5vRmVlCQBrAwUPcmVhbE5ldXRyaW5vRmVlBRZTcG9uc29yZWRGZWVVcHBlckJvdW5kAGQECGlucHV0RmVlCQEFdmFsdWUBCAUCdHgUbWluU3BvbnNvcmVkQXNzZXRGZWUDAwkAZwIFCGlucHV0RmVlBQ5taW5OZXV0cmlub0ZlZQkAZwIFDm1heE5ldXRyaW5vRmVlBQhpbnB1dEZlZQcJAAACCAUCdHgHYXNzZXRJZAUPbmV1dHJpbm9Bc3NldElkBwEPZ2V0UHJpY2VIaXN0b3J5AQVibG9jawkBGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQIFD2NvbnRyb2xDb250cmFjdAkBEmdldFByaWNlSGlzdG9yeUtleQEFBWJsb2NrARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBBWluZGV4CQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0CQEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQUFaW5kZXgBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQNTRVAADHNJZHhTd2FwVHlwZQABAApzSWR4U3RhdHVzAAIADHNJZHhJbkFtb3VudAADAA9zSWR4U3RhcnRIZWlnaHQABwASc0lkeFN0YXJ0VGltZXN0YW1wAAgAFHNJZHhTZWxmVW5sb2NrSGVpZ2h0AAsAC3NJZHhNaW5SYW5kAA8AC3NJZHhNYXhSYW5kABAAC3NJZHhJbkFzc2V0ABQBB3N3YXBLRVkCC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFBHR4SWQFA25pbAUDU0VQAQtzdHJTd2FwREFUQRQIc3dhcFR5cGUGc3RhdHVzCGluQW1vdW50BXByaWNlDG91dE5ldEFtb3VudAxvdXRGZWVBbW91bnQLc3RhcnRIZWlnaHQOc3RhcnRUaW1lc3RhbXAJZW5kSGVpZ2h0DGVuZFRpbWVzdGFtcBBzZWxmVW5sb2NrSGVpZ2h0EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkB3JhbmRNaW4HcmFuZE1heApvdXRTdXJmQW10AmJyCmJhc2tldERhdGEHaW5Bc3NldAkAuQkCCQDMCAICKCVzJXMlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJXMlZCVkJWQlZCVzJXMJAMwIAgUIc3dhcFR5cGUJAMwIAgUGc3RhdHVzCQDMCAIFCGluQW1vdW50CQDMCAIFBXByaWNlCQDMCAIFDG91dE5ldEFtb3VudAkAzAgCBQxvdXRGZWVBbW91bnQJAMwIAgULc3RhcnRIZWlnaHQJAMwIAgUOc3RhcnRUaW1lc3RhbXAJAMwIAgUJZW5kSGVpZ2h0CQDMCAIFDGVuZFRpbWVzdGFtcAkAzAgCBRBzZWxmVW5sb2NrSGVpZ2h0CQDMCAIFEHJhbmRVbmxvY2tIZWlnaHQJAMwIAgUFaW5kZXgJAMwIAgUMd2l0aGRyYXdUeElkCQDMCAIFB3JhbmRNaW4JAMwIAgUHcmFuZE1heAkAzAgCBQpvdXRTdXJmQW10CQDMCAIFAmJyCQDMCAIFCmJhc2tldERhdGEJAMwIAgUHaW5Bc3NldAUDbmlsBQNTRVABD3BlbmRpbmdTd2FwREFUQQQIc3dhcFR5cGUNaW5Bc3NldEFtb3VudBBzZWxmVW5sb2NrSGVpZ2h0B2luQXNzZXQJAQtzdHJTd2FwREFUQRQFCHN3YXBUeXBlAgdQRU5ESU5HCQCkAwEFDWluQXNzZXRBbW91bnQCATACATACATAJAKQDAQUGaGVpZ2h0CQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgEwAgEwCQCkAwEFEHNlbGZVbmxvY2tIZWlnaHQCATACATACBE5VTEwCATACATACATACATACAAUHaW5Bc3NldAEOZmluaXNoU3dhcERBVEELCWRhdGFBcnJheQVwcmljZQxvdXROZXRBbW91bnQMb3V0RmVlQW1vdW50EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkCm91dFN1cmZBbXQCYnIKYmFza2V0RGF0YQdpbkFzc2V0CQELc3RyU3dhcERBVEEUCQCRAwIFCWRhdGFBcnJheQUMc0lkeFN3YXBUeXBlAghGSU5JU0hFRAkAkQMCBQlkYXRhQXJyYXkFDHNJZHhJbkFtb3VudAkApAMBBQVwcmljZQkApAMBBQxvdXROZXRBbW91bnQJAKQDAQUMb3V0RmVlQW1vdW50CQCRAwIFCWRhdGFBcnJheQUPc0lkeFN0YXJ0SGVpZ2h0CQCRAwIFCWRhdGFBcnJheQUSc0lkeFN0YXJ0VGltZXN0YW1wCQCkAwEFBmhlaWdodAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAkQMCBQlkYXRhQXJyYXkFFHNJZHhTZWxmVW5sb2NrSGVpZ2h0CQCkAwEFEHJhbmRVbmxvY2tIZWlnaHQJAKQDAQUFaW5kZXgFDHdpdGhkcmF3VHhJZAkAkQMCBQlkYXRhQXJyYXkFC3NJZHhNaW5SYW5kCQCRAwIFCWRhdGFBcnJheQULc0lkeE1heFJhbmQJAKQDAQUKb3V0U3VyZkFtdAkApAMBBQJicgUKYmFza2V0RGF0YQUHaW5Bc3NldAESc3dhcERhdGFGYWlsT3JSRUFEAgt1c2VyQWRkcmVzcwhzd2FwVHhJZAQHc3dhcEtleQkBB3N3YXBLRVkCBQt1c2VyQWRkcmVzcwUIc3dhcFR4SWQJALwJAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEFB3N3YXBLZXkJAKwCAgIRbm8gc3dhcCBkYXRhIGZvciAFB3N3YXBLZXkFA1NFUAEJYXBwbHlGZWVzAw5hbW91bnRPdXRHcm9zcwtpbkFtdFRvU1VSRgdmZWVQYXJ0BAlmZWVBbW91bnQJAGsDBQ5hbW91bnRPdXRHcm9zcwUHZmVlUGFydAUFTVVMVDYJAMwIAgkAZQIFDmFtb3VudE91dEdyb3NzBQlmZWVBbW91bnQJAMwIAgUJZmVlQW1vdW50BQNuaWwBD2FwcGx5RmVlc0Jhc2tldAEJYmFza2V0T3V0BAJrNgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEKYmFza2V0S0tleQAFBU1VTFQ2BAJkNgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEKYmFza2V0REtleQAA0IYDBAdmZWVQYXJ0CQBrAwUCazYFAmQ2BQVNVUxUNgoBCmZlZUFwcGxpZXICA2FjYwRpdGVtBAlmZWVBbW91bnQJAGsDCAUEaXRlbQJfMgUHZmVlUGFydAUFTVVMVDYJAM0IAgUDYWNjCQC5CQIJAMwIAggFBGl0ZW0CXzEJAMwIAgkApAMBCAUEaXRlbQJfMwkAzAgCCQCkAwEJAGUCCAUEaXRlbQJfMgUJZmVlQW1vdW50CQDMCAIJAKQDAQUJZmVlQW1vdW50CQDMCAIJAKQDAQgFBGl0ZW0CXzQFA25pbAUHTElTVFNFUAQBYQoAAiRsBQliYXNrZXRPdXQKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCmZlZUFwcGxpZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJALkJAgUBYQUDU0VQAQNhYnMBAXgDCQBmAgAABQF4CQEBLQEFAXgFAXgBCnNlbGVjdE5vZGUBDXVubGVhc2VBbW91bnQEDWFtb3VudFRvTGVhc2UJAGUCCQBlAggJAO8HAQUQbmV1dHJpbm9Db250cmFjdAlhdmFpbGFibGUFDXVubGVhc2VBbW91bnQJAR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAQKb2xkTGVhc2VkMAkBDmdldE51bWJlckJ5S2V5AQkBEWdldExlYXNlQW1vdW50S2V5AQAABApvbGRMZWFzZWQxCQEOZ2V0TnVtYmVyQnlLZXkBCQERZ2V0TGVhc2VBbW91bnRLZXkBAAEECm5ld0xlYXNlZDAJAGQCBQ1hbW91bnRUb0xlYXNlBQpvbGRMZWFzZWQwBApuZXdMZWFzZWQxCQBkAgUNYW1vdW50VG9MZWFzZQUKb2xkTGVhc2VkMQMDCQBmAgUKbmV3TGVhc2VkMAAABgkAZgIFCm5ld0xlYXNlZDEAAAQGZGVsdGEwCQEDYWJzAQkAZQIFCm5ld0xlYXNlZDAFCm9sZExlYXNlZDEEBmRlbHRhMQkBA2FicwEJAGUCBQpuZXdMZWFzZWQxBQpvbGRMZWFzZWQwAwkAZwIFBmRlbHRhMQUGZGVsdGEwCQCUCgIAAAUKbmV3TGVhc2VkMAkAlAoCAAEFCm5ld0xlYXNlZDEJAJQKAgD///////////8BAAABCHRoaXNPbmx5AQFpAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQItUGVybWlzc2lvbiBkZW5pZWQ6IHRoaXMgY29udHJhY3Qgb25seSBhbGxvd2VkBgEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQENdW5sZWFzZUFtb3VudAQJbm9kZVR1cGxlCQEKc2VsZWN0Tm9kZQEFDXVubGVhc2VBbW91bnQECW5vZGVJbmRleAgFCW5vZGVUdXBsZQJfMQQObmV3TGVhc2VBbW91bnQIBQlub2RlVHVwbGUCXzIDCQBmAgUObmV3TGVhc2VBbW91bnQAAAQKbGVhc2VJZEtleQkBDWdldExlYXNlSWRLZXkBBQlub2RlSW5kZXgECG9sZExlYXNlCQCcCAIFBHRoaXMFCmxlYXNlSWRLZXkEDnVubGVhc2VPckVtcHR5AwkBCWlzRGVmaW5lZAEFCG9sZExlYXNlCQDMCAIJAQtMZWFzZUNhbmNlbAEJAQV2YWx1ZQEFCG9sZExlYXNlBQNuaWwFA25pbAQObGVhc2VBbW91bnRLZXkJARFnZXRMZWFzZUFtb3VudEtleQEFCW5vZGVJbmRleAQFbGVhc2UJAMQIAgkBHGdldFN0YWtpbmdOb2RlQWRkcmVzc0J5SW5kZXgBBQlub2RlSW5kZXgFDm5ld0xlYXNlQW1vdW50CQDOCAIFDnVubGVhc2VPckVtcHR5CQDMCAIFBWxlYXNlCQDMCAIJAQtCaW5hcnlFbnRyeQIFCmxlYXNlSWRLZXkJAQVsY2FsYwEFBWxlYXNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQERZ2V0TGVhc2VBbW91bnRLZXkBBQlub2RlSW5kZXgFDm5ld0xlYXNlQW1vdW50BQNuaWwFA25pbAEMcmVhZE5vZGVJbmZvAQdub2RlSWR4BAtub2RlQWRkcmVzcwkBHGdldFN0YWtpbmdOb2RlQWRkcmVzc0J5SW5kZXgBBQdub2RlSWR4BAxsZWFzZWRBbXRLRVkJARFnZXRMZWFzZUFtb3VudEtleQEFB25vZGVJZHgECWxlYXNlZEFtdAkBDmdldE51bWJlckJ5S2V5AQUMbGVhc2VkQW10S0VZBApsZWFzZUlkS0VZCQENZ2V0TGVhc2VJZEtleQEFB25vZGVJZHgEB2xlYXNlSWQJAQV2YWx1ZQEJAJwIAgUEdGhpcwUKbGVhc2VJZEtFWQkAlwoFBQtub2RlQWRkcmVzcwUMbGVhc2VkQW10S0VZBQlsZWFzZWRBbXQFCmxlYXNlSWRLRVkFB2xlYXNlSWQBCmNvbW1vblN3YXAFCHN3YXBUeXBlCXBtdEFtb3VudAdpbkFzc2V0DnVzZXJBZGRyZXNzU3RyBnR4SWQ1OAQQc3dhcFBhcmFtc1NUUlVDVAkBEmFzU3dhcFBhcmFtc1NUUlVDVAEJAPwHBAUEdGhpcwIbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZCQDMCAIFDnVzZXJBZGRyZXNzU3RyCQDMCAIAAAUDbmlsBQNuaWwEDnN3YXBMaW1pdFNwZW50CAUQc3dhcFBhcmFtc1NUUlVDVAJfMgQOYmxja3MyTG10UmVzZXQIBRBzd2FwUGFyYW1zU1RSVUNUAl8zBBF3YXZlc1N3YXBMaW1pdE1heAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzYEEHVzZG5Td2FwTGltaXRNYXgIBRBzd2FwUGFyYW1zU1RSVUNUAl83BA1taW5Td2FwQW1vdW50CQERbWluU3dhcEFtb3VudFJFQUQCBQhzd2FwVHlwZQUHaW5Bc3NldAQLdG90YWxMb2NrZWQJAQ90b3RhbExvY2tlZFJFQUQCBQhzd2FwVHlwZQUHaW5Bc3NldAQRdG90YWxMb2NrZWRCeVVzZXIJARV0b3RhbExvY2tlZEJ5VXNlclJFQUQDBQhzd2FwVHlwZQUOdXNlckFkZHJlc3NTdHIFB2luQXNzZXQEC25vZGVBZGRyZXNzCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQAABAxwcmljZUJ5SW5kZXgJAQ9nZXRQcmljZUhpc3RvcnkBCQEVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AQUKcHJpY2VJbmRleAQMaXNTd2FwQnlOb2RlCQAAAgULbm9kZUFkZHJlc3MFDnVzZXJBZGRyZXNzU3RyBBZiYWxhbmNlTG9ja01heEludGVydmFsAwUMaXNTd2FwQnlOb2RlCQEbbm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAkBF2JhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAQUIc3dhcFR5cGUEEHNlbGZVbmxvY2tIZWlnaHQJAGQCBQZoZWlnaHQFFmJhbGFuY2VMb2NrTWF4SW50ZXJ2YWwEDnN3YXBVc2RuVm9sdW1lAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBQlwbXRBbW91bnQFDHByaWNlQnlJbmRleAUJcG10QW1vdW50BAxzd2FwTGltaXRNYXgDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIFEXdhdmVzU3dhcExpbWl0TWF4BQxwcmljZUJ5SW5kZXgFEHVzZG5Td2FwTGltaXRNYXgDCQBmAgUNbWluU3dhcEFtb3VudAUJcG10QW1vdW50CQERbWluU3dhcEFtb3VudEZBSUwCBQhzd2FwVHlwZQUNbWluU3dhcEFtb3VudAMDCQEBIQEFDGlzU3dhcEJ5Tm9kZQkAZgIFDnN3YXBMaW1pdFNwZW50AAAHCQACAQkArAICAjpZb3UgaGF2ZSBleGNlZWRlZCBzd2FwIGxpbWl0ISBOZXh0IGFsbG93ZWQgc3dhcCBoZWlnaHQgaXMgCQCkAwEJAGQCBQZoZWlnaHQFDmJsY2tzMkxtdFJlc2V0AwMJAQEhAQUMaXNTd2FwQnlOb2RlCQBmAgUOc3dhcFVzZG5Wb2x1bWUFDHN3YXBMaW1pdE1heAcJAAIBCQCsAgIJAKwCAgkArAICAi5Zb3UgaGF2ZSBleGNlZWRlZCB5b3VyIHN3YXAgbGltaXQhIFJlcXVlc3RlZDogCQCkAwEFDnN3YXBVc2RuVm9sdW1lAg0sIGF2YWlsYWJsZTogCQCkAwEFDHN3YXBMaW1pdE1heAMFCWlzQmxvY2tlZAkBFWVtZXJnZW5jeVNodXRkb3duRkFJTAAED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwECmJhc2tldEluZm8JAQhhc1N0cmluZwEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBRFuTWV0cmljQmFza2V0SW5mbwQNd2VpZ2h0ZWRQcmljZQkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFFG5NZXRyaWNXZWlnaHRlZFByaWNlBANvdXQJARtjb252ZXJ0QmFza2V0SXRlbVRvTmV1dHJpbm8EBQlwbXRBbW91bnQFB2luQXNzZXQFCmJhc2tldEluZm8FDXdlaWdodGVkUHJpY2UDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAZwIAAAkAkQMCBQNvdXQAAQcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAj5OZXQgYW1vdW50IGlzIG5vbi1wb3NpdGl2ZSwgY2Fubm90IHN3YXAuIChncm9zcywgbmV0LCBmZWUpID0gKAkApAMBCQCRAwIFA291dAAAAgIsIAkApAMBCQCRAwIFA291dAABAgIsIAkApAMBCQCRAwIFA291dAACAgEpBAlsZWFzZVBhcnQDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAAAIFB2luQXNzZXQCBVdBVkVTBwkBFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UBAAAFA25pbAkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARhrZXlTd2FwVXNlclNwZW50SW5QZXJpb2QBBQ51c2VyQWRkcmVzc1N0cgUOc3dhcFVzZG5Wb2x1bWUJAMwIAgkBDEludGVnZXJFbnRyeQIJARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBBQ51c2VyQWRkcmVzc1N0cgUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUdG90YWxMb2NrZWRCeVVzZXJLRVkDBQhzd2FwVHlwZQUOdXNlckFkZHJlc3NTdHIFB2luQXNzZXQJAGQCBRF0b3RhbExvY2tlZEJ5VXNlcgUJcG10QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AQUOdXNlckFkZHJlc3NTdHIFEHNlbGZVbmxvY2tIZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b3RhbExvY2tlZEtFWQIFCHN3YXBUeXBlBQdpbkFzc2V0CQBkAgULdG90YWxMb2NrZWQFCXBtdEFtb3VudAkAzAgCCQELU3RyaW5nRW50cnkCCQEHc3dhcEtFWQIFDnVzZXJBZGRyZXNzU3RyBQZ0eElkNTgJAQ9wZW5kaW5nU3dhcERBVEEEBQhzd2FwVHlwZQUJcG10QW1vdW50BRBzZWxmVW5sb2NrSGVpZ2h0BQdpbkFzc2V0BQNuaWwFCWxlYXNlUGFydAUEdW5pdAAMYkZ1bmNJZHhTdXJmAAAADWJGdW5jSWR4V2F2ZXMAAQAMYkZ1bmNJZHhVc2RuAAIAFGJGdW5jSWR4UmVzZXJ2ZVN0YXJ0AAMAE2JGdW5jSWR4U3VwcGx5U3RhcnQABAAPYkZ1bmNJZHhCUlN0YXJ0AAUAEmJGdW5jSWR4UmVzZXJ2ZUVuZAAGABFiRnVuY0lkeFN1cHBseUVuZAAHAA1iRnVuY0lkeEJSRW5kAAgADGJGdW5jSWR4UmVzdAAJABJiRnVuY0lkeFdhdmVzUHJpY2UACgEPY2FsY1dpdGhkcmF3VDJVBAhpbkFtb3VudAdpbkFzc2V0CmJhc2tldEluZm8Nd2VpZ2h0ZWRQcmljZQQGb3V0QW10CQEbY29udmVydEJhc2tldEl0ZW1Ub05ldXRyaW5vBAUIaW5BbW91bnQFB2luQXNzZXQFCmJhc2tldEluZm8FDXdlaWdodGVkUHJpY2UJAJ4KDAkAkQMCBQZvdXRBbXQAAAUPbmV1dHJpbm9Bc3NldElkAAAFB2luQXNzZXQAAAUNd2VpZ2h0ZWRQcmljZQUIaW5BbW91bnQAAAAAAAAFA25pbAkAzAgCCQCRAwIFBm91dEFtdAABCQDMCAIJAJEDAgUGb3V0QW10AAIFA25pbAEUY2FsY1dpdGhkcmF3VTJCYXNrZXQFBnVzZG5JbgpiYXNrZXRJbmZvAmJyDnJlc2VydmVzSW5Vc2RuDm5ldXRyaW5vU3VwcGx5BAticlByb3RlY3RlZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOYnJQcm90ZWN0ZWRLRVkABQtCUlBST1RFQ1RFRAQZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgMJAGcCBQticlByb3RlY3RlZAUCYnIAAAkAawMJAGUCBQ5yZXNlcnZlc0luVXNkbgkAawMFC2JyUHJvdGVjdGVkBQ5uZXV0cmlub1N1cHBseQUFTVVMVDYFBU1VTFQ2CQBlAgUFTVVMVDYFC2JyUHJvdGVjdGVkBBZhbGxvd2VkVXNkbkJlZm9yZU1pbkJyAwkAZgIFBnVzZG5JbgUZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUGdXNkbkluBBVhbGxvd2VkVXNkbkFmdGVyTWluQnIDCQBmAgUGdXNkbkluBRltYXhBbGxvd2VkVXNkbkJlZm9yZU1pbkJyCQBrAwkAZQIFBnVzZG5JbgUZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUCYnIFBU1VTFQ2AAAEC2FsbG93ZWRVc2RuCQBkAgUWYWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUVYWxsb3dlZFVzZG5BZnRlck1pbkJyBAl1c2RuMlNVUkYJAGUCBQZ1c2RuSW4FC2FsbG93ZWRVc2RuAwkAAAIAAQABCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIHdXNkbkluPQkApAMBBQZ1c2RuSW4CAm1BCQCkAwEFGW1heEFsbG93ZWRVc2RuQmVmb3JlTWluQnICBiBhQmVmPQkApAMBBRZhbGxvd2VkVXNkbkJlZm9yZU1pbkJyAgYgYUFmdD0JAKQDAQUVYWxsb3dlZFVzZG5BZnRlck1pbkJyAg0gYWxsb3dlZFVzZG49CQCkAwEFC2FsbG93ZWRVc2RuBAtvdXRBbXRHcm9zcwkBF2NvbnZlcnROZXV0cmlub1RvQmFza2V0AwULYWxsb3dlZFVzZG4FCmJhc2tldEluZm8FDm5ldXRyaW5vU3VwcGx5CQCeCgwIBQtvdXRBbXRHcm9zcwJfMgUEdW5pdAUJdXNkbjJTVVJGBQ9uZXV0cmlub0Fzc2V0SWQIBQtvdXRBbXRHcm9zcwJfMggFC291dEFtdEdyb3NzAl8zBQthbGxvd2VkVXNkbgUZbWF4QWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUWYWxsb3dlZFVzZG5CZWZvcmVNaW5CcgUVYWxsb3dlZFVzZG5BZnRlck1pbkJyCAULb3V0QW10R3Jvc3MCXzEFA25pbAEMY2FsY1dpdGhkcmF3BQhzd2FwVHlwZQhpbkFtb3VudAVwcmljZQ9uZXV0cmlub01ldHJpY3MHaW5Bc3NldAQLYnJQcm90ZWN0ZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDmJyUHJvdGVjdGVkS0VZAAULQlJQUk9URUNURUQEAkJSCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUMbk1ldHJpY0lkeEJSBA1yZXNlcnZlc0luVXNkCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUXbk1ldHJpY1RvdGFsUmVzZXJ2ZXNVc2QEDm5ldXRyaW5vU3VwcGx5CQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUUbk1ldHJpY0lkeFVzZG5TdXBwbHkECmJhc2tldEluZm8JAQhhc1N0cmluZwEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBRFuTWV0cmljQmFza2V0SW5mbwQNd2VpZ2h0ZWRQcmljZQkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFFG5NZXRyaWNXZWlnaHRlZFByaWNlBAxvdXREYXRhVHVwbGUDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQEPY2FsY1dpdGhkcmF3VDJVBAUIaW5BbW91bnQFB2luQXNzZXQFCmJhc2tldEluZm8FDXdlaWdodGVkUHJpY2UDCQAAAgUIc3dhcFR5cGUCCG91dE11bHRpCQEUY2FsY1dpdGhkcmF3VTJCYXNrZXQFBQhpbkFtb3VudAUKYmFza2V0SW5mbwUCQlIFDXJlc2VydmVzSW5Vc2QFDm5ldXRyaW5vU3VwcGx5CQACAQkArAICAhZVbnN1cHBvcnRlZCBzd2FwIHR5cGUgBQhzd2FwVHlwZQQLb3V0QW10R3Jvc3MIBQxvdXREYXRhVHVwbGUCXzEECm91dEFzc2V0SWQIBQxvdXREYXRhVHVwbGUCXzIED2luQW10VG9TdXJmUGFydAgFDG91dERhdGFUdXBsZQJfMwQJaW5Bc3NldElkCAUMb3V0RGF0YVR1cGxlAl80BAp1bmxlYXNlQW10CAUMb3V0RGF0YVR1cGxlAl81BA13aXRoZHJhd1ByaWNlCAUMb3V0RGF0YVR1cGxlAl82BApiYXNrZXREYXRhCAUMb3V0RGF0YVR1cGxlA18xMQQKbmV0RmVlRGF0YQgFDG91dERhdGFUdXBsZQNfMTIECW91dE5ldEFtdAMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8JAJEDAgUKbmV0RmVlRGF0YQAAAAAECW91dEZlZUFtdAMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8JAJEDAgUKbmV0RmVlRGF0YQABAAAECm91dFN1cmZBbXQDCQBnAgAABQ9pbkFtdFRvU3VyZlBhcnQAAAkBBWFzSW50AQkAkQMCCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCFHN1cmZGdW5jdGlvblJFQURPTkxZCQDMCAIFD2luQW10VG9TdXJmUGFydAkAzAgCBQlpbkFzc2V0SWQFA25pbAUDbmlsBQxiRnVuY0lkeFN1cmYEDndpdGhkcmF3QmFza2V0AwkAAAIFCHN3YXBUeXBlAghvdXRNdWx0aQkBD2FwcGx5RmVlc0Jhc2tldAEFCmJhc2tldERhdGECAAkAmwoJBQlvdXROZXRBbXQFCm91dEFzc2V0SWQFCm91dFN1cmZBbXQFD2luQW10VG9TdXJmUGFydAUKdW5sZWFzZUFtdAUJb3V0RmVlQW10BQtvdXRBbXRHcm9zcwUNd2l0aGRyYXdQcmljZQUOd2l0aGRyYXdCYXNrZXQBEmtleUFwcGx5SW5Qcm9ncmVzcwACEyVzX19hcHBseUluUHJvZ3Jlc3MBE2tleVByb3Bvc2FsRGF0YUJ5SWQBCnByb3Bvc2FsSWQJAKwCAgIUJXMlZF9fcHJvcG9zYWxEYXRhX18JAKQDAQUKcHJvcG9zYWxJZAALZ292SWR4VHhJZHMACQEOdmFsaWRhdGVVcGRhdGUBAnR4BAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAgVPcmRlcgQBbwUHJG1hdGNoMAkAAgECFU9yZGVycyBhcmVuJ3QgYWxsb3dlZAMDCQABAgUHJG1hdGNoMAIPRGF0YVRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhVTcG9uc29yRmVlVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACFFNldFNjcmlwdFRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhZDcmVhdGVBbGlhc1RyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhZMZWFzZUNhbmNlbFRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhBMZWFzZVRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhBJc3N1ZVRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhtJbnZva2VFeHByZXNzaW9uVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACGlVwZGF0ZUFzc2V0SW5mb1RyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhdJbnZva2VTY3JpcHRUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIZU2V0QXNzZXRTY3JpcHRUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAITVHJhbnNmZXJUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAITRXhjaGFuZ2VUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIXTWFzc1RyYW5zZmVyVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACD0J1cm5UcmFuc2FjdGlvbgYJAAECBQckbWF0Y2gwAhJSZWlzc3VlVHJhbnNhY3Rpb24EAXQFByRtYXRjaDAEBHR4SWQJANgEAQgFAXQCaWQECnByb3Bvc2FsSWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQtnb3ZDb250cmFjdAkBEmtleUFwcGx5SW5Qcm9ncmVzcwACFkFwcGx5IGlzIG5vdCBoYXBwZW5pbmcEBnR4TGlzdAkAtQkCCQCRAwIJALUJAgkBD2dldFN0cmluZ09yRmFpbAIFC2dvdkNvbnRyYWN0CQETa2V5UHJvcG9zYWxEYXRhQnlJZAEFCnByb3Bvc2FsSWQFA1NFUAULZ292SWR4VHhJZHMFB0xJU1RTRVADCQEBIQEJAQlpc0RlZmluZWQBCQDPCAIFBnR4TGlzdAUEdHhJZAkAAgEJAKwCAgkArAICCQCsAgICDlVua25vd24gdHhJZDogBQR0eElkAhAgZm9yIHByb3Bvc2FsSWQ9CQCkAwEFCnByb3Bvc2FsSWQGCQACAQILTWF0Y2ggZXJyb3IQAWkBDWNvbnN0cnVjdG9yVjEMEm5ldXRyaW5vQXNzZXRJZFBybQ5ib25kQXNzZXRJZFBybRJhdWN0aW9uQ29udHJhY3RQcm0WbGlxdWlkYXRpb25Db250cmFjdFBybQ5ycGRDb250cmFjdFBybRtub2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlQcm0bYmFsYW5jZVdhdmVzTG9ja0ludGVydmFsUHJtHmJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbFBybRVtaW5XYXZlc1N3YXBBbW91bnRQcm0YbWluTmV1dHJpbm9Td2FwQW1vdW50UHJtFW5ldXRyaW5vT3V0RmVlUGFydFBybRJ3YXZlc091dEZlZVBhcnRQcm0EC2NoZWNrQ2FsbGVyCQEIdGhpc09ubHkBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE25vIHBheW1lbnRzIGFsbG93ZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUSTmV1dHJpbm9Bc3NldElkS2V5BRJuZXV0cmlub0Fzc2V0SWRQcm0JAMwIAgkBC1N0cmluZ0VudHJ5AgUOQm9uZEFzc2V0SWRLZXkFDmJvbmRBc3NldElkUHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFEkF1Y3Rpb25Db250cmFjdEtleQUSYXVjdGlvbkNvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFFkxpcXVpZGF0aW9uQ29udHJhY3RLZXkFFmxpcXVpZGF0aW9uQ29udHJhY3RQcm0JAMwIAgkBC1N0cmluZ0VudHJ5AgUOUlBEQ29udHJhY3RLZXkFDnJwZENvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQUbbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRtCYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxLZXkFG2JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUeQmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsS2V5BR5iYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIJARVNaW5Ub2tlblN3YXBBbW91bnRLZXkBAgVXQVZFUwUVbWluV2F2ZXNTd2FwQW1vdW50UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhNaW5OZXV0cmlub1N3YXBBbW91bnRLZXkFGG1pbk5ldXRyaW5vU3dhcEFtb3VudFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUVTmV1dHJpbm9PdXRGZWVQYXJ0S2V5BRVuZXV0cmlub091dEZlZVBhcnRQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFEldhdmVzT3V0RmVlUGFydEtleQUSd2F2ZXNPdXRGZWVQYXJ0UHJtBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY29uc3RydWN0b3JWMgMMbWF0aENvbnRyYWN0E25zYnRTdGFraW5nQ29udHJhY3QUc3dhcHNUaW1lZnJhbWVCbG9ja3MEC2NoZWNrQ2FsbGVyCQEIdGhpc09ubHkBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE25vIHBheW1lbnRzIGFsbG93ZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUPTWF0aENvbnRyYWN0S2V5BQxtYXRoQ29udHJhY3QJAMwIAgkBC1N0cmluZ0VudHJ5AgUWTnNidFN0YWtpbmdDb250cmFjdEtleQUTbnNidFN0YWtpbmdDb250cmFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEXN3YXBzVGltZWZyYW1lS0VZAAUUc3dhcHNUaW1lZnJhbWVCbG9ja3MFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1jb25zdHJ1Y3RvclYzBRFhc3NldHNXZWlnaHRzTWlucwZkUGFyYW0Ga1BhcmFtBmJQYXJhbQpkZWx0YVBhcmFtBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCgEHcHJlcGFyZQIDYWNjBGl0ZW0EBXBhcnRzCQC1CQIFBGl0ZW0CAV8EB2Fzc2V0SWQJAJEDAgUFcGFydHMAAAQGd2VpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQQGbWluVmFsCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAgkAlAoCCQDNCAIIBQNhY2MCXzEFB2Fzc2V0SWQJAM0IAgkAzQgCCAUDYWNjAl8yCQEMSW50ZWdlckVudHJ5AgkBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBBQdhc3NldElkBQZ3ZWlnaHQJAQxJbnRlZ2VyRW50cnkCCQEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQUHYXNzZXRJZAUGbWluVmFsBAFyCgACJGwFEWFzc2V0c1dlaWdodHNNaW5zCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHcHJlcGFyZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIIBQFyAl8yCQEMSW50ZWdlckVudHJ5AgkBCmJhc2tldERLZXkABQZkUGFyYW0JAQxJbnRlZ2VyRW50cnkCCQEKYmFza2V0S0tleQAFBmtQYXJhbQkBDEludGVnZXJFbnRyeQIJAQpiYXNrZXRCS2V5AAUGYlBhcmFtCQEMSW50ZWdlckVudHJ5AgkBEmJhc2tldExvZ2JEZWx0YUtleQAJAG0GBQpkZWx0YVBhcmFtAAYFBmJQYXJhbQAGAAYFBkhBTEZVUAkBC1N0cmluZ0VudHJ5AgkBD2Jhc2tldEFzc2V0c0tleQAJALkJAggFAXICXzEFA1NFUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARNzd2FwVG9rZW5Ub05ldXRyaW5vAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECLHN3YXBUb2tlblRvTmV1dHJpbm8gcmVxdWlyZSBvbmx5IG9uZSBwYXltZW50BANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQMYmFza2V0QXNzZXRzCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9iYXNrZXRBc3NldHNLZXkAAgVXQVZFUwQNcG10QXNzZXRJZFN0cgkA2AQBCQELdmFsdWVPckVsc2UCCAUDcG10B2Fzc2V0SWQFB1dBVkVTSUQDCQEBIQEJAQhjb250YWlucwIFDGJhc2tldEFzc2V0cwUNcG10QXNzZXRJZFN0cgkAAgEJAKwCAgkArAICBQ1wbXRBc3NldElkU3RyAh0gaXMgbm90IG9uZSBvZiBiYXNrZXQgdG9rZW5zOgUMYmFza2V0QXNzZXRzBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkCQEKY29tbW9uU3dhcAUCC291dE5ldXRyaW5vCAUDcG10BmFtb3VudAUNcG10QXNzZXRJZFN0cgULdXNlckFkZHJlc3MFBnR4SWQ1OAFpARRzd2FwTmV1dHJpbm9Ub0Jhc2tldAADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAi1zd2FwTmV1dHJpbm9Ub0Jhc2tldCByZXF1aXJlIG9ubHkgb25lIHBheW1lbnQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQJAAIBAjpPbmx5IGFwcHJvcHJpYXRlIE5ldXRyaW5vIHRva2VucyBhcmUgYWxsb3dlZCBmb3Igc3dhcHBpbmcuBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkCQEKY29tbW9uU3dhcAUCCG91dE11bHRpCAUDcG10BmFtb3VudAkA2AQBBQ9uZXV0cmlub0Fzc2V0SWQFC3VzZXJBZGRyZXNzBQZ0eElkNTgBaQEId2l0aGRyYXcDB2FjY291bnQFaW5kZXgIc3dhcFR4SWQEBHR4SWQJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE25vIHBheW1lbnRzIGFsbG93ZWQED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwEAkJSCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUMbk1ldHJpY0lkeEJSBAt1c2VyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUHYWNjb3VudAQJZGF0YUFycmF5CQESc3dhcERhdGFGYWlsT3JSRUFEAgUHYWNjb3VudAUIc3dhcFR4SWQEEHNlbGZVbmxvY2tIZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkYXRhQXJyYXkFFHNJZHhTZWxmVW5sb2NrSGVpZ2h0BAhzd2FwVHlwZQkAkQMCBQlkYXRhQXJyYXkFDHNJZHhTd2FwVHlwZQQIaW5BbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkYXRhQXJyYXkFDHNJZHhJbkFtb3VudAQKc3dhcFN0YXR1cwkAkQMCBQlkYXRhQXJyYXkFCnNJZHhTdGF0dXMEC3N0YXJ0SGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGF0YUFycmF5BQ9zSWR4U3RhcnRIZWlnaHQEB2luQXNzZXQJAJEDAgUJZGF0YUFycmF5BQtzSWR4SW5Bc3NldAQLdG90YWxMb2NrZWQJAQ90b3RhbExvY2tlZFJFQUQCBQhzd2FwVHlwZQUHaW5Bc3NldAQRdG90YWxMb2NrZWRCeVVzZXIJARV0b3RhbExvY2tlZEJ5VXNlclJFQUQDBQhzd2FwVHlwZQUHYWNjb3VudAUHaW5Bc3NldAQMdW5sb2NrSGVpZ2h0BRBzZWxmVW5sb2NrSGVpZ2h0BAtpbmRleEhlaWdodAkBFWdldEhlaWdodFByaWNlQnlJbmRleAEFBWluZGV4BA9wcmV2SW5kZXhIZWlnaHQJARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBCQBlAgUFaW5kZXgAAQQMcHJpY2VCeUluZGV4CQEPZ2V0UHJpY2VIaXN0b3J5AQULaW5kZXhIZWlnaHQDBQlpc0Jsb2NrZWQJARVlbWVyZ2VuY3lTaHV0ZG93bkZBSUwAAwkBAiE9AgUKc3dhcFN0YXR1cwIHUEVORElORwkAAgECH3N3YXAgaGFzIGJlZW4gYWxyZWFkeSBwcm9jZXNzZWQDCQBmAgUMdW5sb2NrSGVpZ2h0BQZoZWlnaHQJAAIBCQCsAgIJAKwCAgIRcGxlYXNlIHdhaXQgZm9yOiAJAKQDAQUMdW5sb2NrSGVpZ2h0Ah8gYmxvY2sgaGVpZ2h0IHRvIHdpdGhkcmF3IGZ1bmRzAwMDCQBmAgUFaW5kZXgFCnByaWNlSW5kZXgGCQBmAgUMdW5sb2NrSGVpZ2h0BQtpbmRleEhlaWdodAYDCQECIT0CBQ9wcmV2SW5kZXhIZWlnaHQAAAkAZwIFD3ByZXZJbmRleEhlaWdodAUMdW5sb2NrSGVpZ2h0BwkBDnByaWNlSW5kZXhGQUlMBQUFaW5kZXgFCnByaWNlSW5kZXgFC2luZGV4SGVpZ2h0BQx1bmxvY2tIZWlnaHQFD3ByZXZJbmRleEhlaWdodAQNd2l0aGRyYXdUdXBsZQkBDGNhbGNXaXRoZHJhdwUFCHN3YXBUeXBlBQhpbkFtb3VudAUMcHJpY2VCeUluZGV4BQ9uZXV0cmlub01ldHJpY3MFB2luQXNzZXQEDG91dE5ldEFtb3VudAgFDXdpdGhkcmF3VHVwbGUCXzEECm91dEFzc2V0SWQIBQ13aXRoZHJhd1R1cGxlAl8yBApvdXRTdXJmQW10CAUNd2l0aGRyYXdUdXBsZQJfMwQKdW5sZWFzZUFtdAgFDXdpdGhkcmF3VHVwbGUCXzUEDG91dEZlZUFtb3VudAgFDXdpdGhkcmF3VHVwbGUCXzYEC291dEFtdEdyb3NzCAUNd2l0aGRyYXdUdXBsZQJfNwQNd2l0aGRyYXdQcmljZQgFDXdpdGhkcmF3VHVwbGUCXzgEDndpdGhkcmF3QmFza2V0CAUNd2l0aGRyYXdUdXBsZQJfOQMDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQBnAgAABQtvdXRBbXRHcm9zcwcJAAIBAhNiYWxhbmNlIGVxdWFscyB6ZXJvBA1zdXJmQ29uZGl0aW9uAwkAZgIFCm91dFN1cmZBbXQAAAQLaXNzdWVSZXN1bHQJAPwHBAUPYXVjdGlvbkNvbnRyYWN0Aglpc3N1ZVN1cmYJAMwIAgUKb3V0U3VyZkFtdAkAzAgCBQdhY2NvdW50BQNuaWwFA25pbAMJAAACBQtpc3N1ZVJlc3VsdAULaXNzdWVSZXN1bHQAAAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAwkAAAIFDXN1cmZDb25kaXRpb24FDXN1cmZDb25kaXRpb24EEXVubGVhc2VJbnZPckVtcHR5CQD8BwQFBHRoaXMCF2ludGVybmFsVW5sZWFzZUFuZExlYXNlCQDMCAIFCnVubGVhc2VBbXQFA25pbAUDbmlsAwkAAAIFEXVubGVhc2VJbnZPckVtcHR5BRF1bmxlYXNlSW52T3JFbXB0eQQJZ25zYnREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIUZ25zYnRJbmZvU1lTUkVBRE9OTFkJAMwIAgIACQDMCAIAAAkAzAgCAAAFA25pbAUDbmlsBA1nbnNidEFtdFRvdGFsCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQABBBVnbnNidEFtdEZyb21TdXJmVG90YWwJAQVhc0ludAEJAJEDAgkBCWFzQW55TGlzdAEJAJEDAgUJZ25zYnREYXRhAAMAAwQNY29tbW9uQWN0aW9ucwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFHRvdGFsTG9ja2VkQnlVc2VyS0VZAwUIc3dhcFR5cGUFB2FjY291bnQFB2luQXNzZXQJAGUCBRF0b3RhbExvY2tlZEJ5VXNlcgUIaW5BbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b3RhbExvY2tlZEtFWQIFCHN3YXBUeXBlBQdpbkFzc2V0CQBlAgULdG90YWxMb2NrZWQFCGluQW1vdW50CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQdzd2FwS0VZAgUHYWNjb3VudAUIc3dhcFR4SWQJAQ5maW5pc2hTd2FwREFUQQsFCWRhdGFBcnJheQUNd2l0aGRyYXdQcmljZQUMb3V0TmV0QW1vdW50BQxvdXRGZWVBbW91bnQFDHVubG9ja0hlaWdodAUFaW5kZXgFBHR4SWQFCm91dFN1cmZBbXQFAkJSBQ53aXRoZHJhd0Jhc2tldAUHaW5Bc3NldAUDbmlsAwkAAAIFCHN3YXBUeXBlAghvdXRNdWx0aQQGYmFza2V0CQC1CQIFDndpdGhkcmF3QmFza2V0AgFfCgEGbG9vcGVyAgNhY2MEaXRlbQQCaXQJALUJAgUEaXRlbQUHTElTVFNFUAQLdGVtcEFzc2V0SWQJANkEAQkAkQMCBQJpdAAABAdhc3NldElkAwkAAAIFC3RlbXBBc3NldElkBQdXQVZFU0lEBQR1bml0BQt0ZW1wQXNzZXRJZAQJbmV0QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaXQAAgQJZmVlQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaXQAAwQIc3VyZkFtdDEDCQECIT0CBQ1nbnNidEFtdFRvdGFsAAAJAGsDBQlmZWVBbW91bnQFFWduc2J0QW10RnJvbVN1cmZUb3RhbAUNZ25zYnRBbXRUb3RhbAAABAhzdXJmQW10MgMJAQIhPQIFDWduc2J0QW10VG90YWwAAAkAawMFCWZlZUFtb3VudAkAZQIFBU1VTFQ2BQJCUgUFTVVMVDYAAAQHc3VyZkFtdAkAlgMBCQDMCAIFCHN1cmZBbXQxCQDMCAIFCHN1cmZBbXQyBQNuaWwEB25zYnRBbXQJAGUCBQlmZWVBbW91bnQFB3N1cmZBbXQJAJcKBQkAzQgCCAUDYWNjAl8xCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwUJbmV0QW1vdW50BQdhc3NldElkCQDNCAIIBQNhY2MCXzIJAQ9BdHRhY2hlZFBheW1lbnQCBQdhc3NldElkBQdzdXJmQW10CQDNCAIIBQNhY2MCXzMJAQ9BdHRhY2hlZFBheW1lbnQCBQdhc3NldElkBQduc2J0QW10CQBkAggFA2FjYwJfNAUHc3VyZkFtdAkAZAIIBQNhY2MCXzUFB25zYnRBbXQEAXIKAAIkbAUGYmFza2V0CgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlwoFBQNuaWwFA25pbAUDbmlsAAAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGbG9vcGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAtzdXJmRGVwb3NpdAMJAGYCCAUBcgJfNAAABAdzdXJmSW52CQD8BwQFE3N1cmZTdGFraW5nQ29udHJhY3QCB2RlcG9zaXQFA25pbAgFAXICXzIDCQAAAgUHc3VyZkludgUHc3VyZkludgAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAADCQAAAgULc3VyZkRlcG9zaXQFC3N1cmZEZXBvc2l0BAtuc2J0RGVwb3NpdAMJAGYCCAUBcgJfNQAABAduc2J0SW52CQD8BwQFE25zYnRTdGFraW5nQ29udHJhY3QCB2RlcG9zaXQFA25pbAgFAXICXzMDCQAAAgUHbnNidEludgUHbnNidEludgAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAADCQAAAgULbnNidERlcG9zaXQFC25zYnREZXBvc2l0CQDOCAIFDWNvbW1vbkFjdGlvbnMIBQFyAl8xCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBANmZWUJAQ9BdHRhY2hlZFBheW1lbnQCBQpvdXRBc3NldElkBQxvdXRGZWVBbW91bnQEC3N1cmZGZWVBbXQxAwkBAiE9AgUNZ25zYnRBbXRUb3RhbAAACQBrAwgFA2ZlZQZhbW91bnQFFWduc2J0QW10RnJvbVN1cmZUb3RhbAUNZ25zYnRBbXRUb3RhbAAABAtzdXJmRmVlQW10MgMJAQIhPQIFDWduc2J0QW10VG90YWwAAAkAawMIBQNmZWUGYW1vdW50CQBlAgUFTVVMVDYFAkJSBQVNVUxUNgAABApzdXJmRmVlQW10CQCWAwEJAMwIAgULc3VyZkZlZUFtdDEJAMwIAgULc3VyZkZlZUFtdDIFA25pbAQKbnNidEZlZUFtdAkAZQIIBQNmZWUGYW1vdW50BQpzdXJmRmVlQW10BAtzdXJmRGVwb3NpdAMJAGYCBQpzdXJmRmVlQW10AAAEB3N1cmZJbnYJAPwHBAUTc3VyZlN0YWtpbmdDb250cmFjdAIHZGVwb3NpdAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCAUDZmVlB2Fzc2V0SWQFCnN1cmZGZWVBbXQFA25pbAMJAAACBQdzdXJmSW52BQdzdXJmSW52BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4FA25pbAMJAAACBQtzdXJmRGVwb3NpdAULc3VyZkRlcG9zaXQEC25zYnREZXBvc2l0AwkAZgIFCm5zYnRGZWVBbXQAAAQHbnNidEludgkA/AcEBRNuc2J0U3Rha2luZ0NvbnRyYWN0AgdkZXBvc2l0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIIBQNmZWUHYXNzZXRJZAUKbnNidEZlZUFtdAUDbmlsAwkAAAIFB25zYnRJbnYFB25zYnRJbnYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgUDbmlsAwkAAAIFC25zYnREZXBvc2l0BQtuc2J0RGVwb3NpdAkAzQgCBQ1jb21tb25BY3Rpb25zCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwUMb3V0TmV0QW1vdW50BQpvdXRBc3NldElkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBF2ludGVybmFsVW5sZWFzZUFuZExlYXNlAQ11bmxlYXNlQW1vdW50AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIsaW50ZXJuYWxVbmxlYXNlQW5kTGVhc2UgaXMgbm90IHB1YmxpYyBtZXRob2QJARZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAQUNdW5sZWFzZUFtb3VudAFpARJ0cmFuc2ZlclVzZG5Ub1VzZXICBmFtb3VudARhZGRyAwkBAiE9AggFAWkGY2FsbGVyBQ9hdWN0aW9uQ29udHJhY3QJAAIBAiNPbmx5IGF1Y3Rpb24gY29udHJhY3QgaXMgYXV0aG9yaXplZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQRhZGRyBQZhbW91bnQFD25ldXRyaW5vQXNzZXRJZAUDbmlsAWkBC2FjY2VwdFdhdmVzAAMDCQECIT0CCAUBaQZjYWxsZXIFD2F1Y3Rpb25Db250cmFjdAkBAiE9AggFAWkGY2FsbGVyBQtnb3ZDb250cmFjdAcJAAIBAkNDdXJyZW50bHkgb25seSBhdWN0aW9uIGFuZCBnb3Zlcm5hbmNlIGNvbnRyYWN0cyBhcmUgYWxsb3dlZCB0byBjYWxsCQCUCgIJARZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAQAAAgdzdWNjZXNzAWkBD2FwcHJvdmVMZWFzaW5ncwMGbkxpc3RTCGdyb3VwTnVtBGxBbXQEBW5JZHhzCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcFA25pbAQHbW5nUHViUwkBC3ZhbHVlT3JFbHNlAgkAoggBAhwlcyVzX19jZmdfX2xlYXNpbmdNYW5hZ2VyUHViAiw3QVVNWDU0dWtZTVl2UG1tYTd5b0ZmNU5qWmhzNEJ1NW56M0V6OUVWOHN1cgQGbW5nUHViCQDZBAEFB21uZ1B1YlMEDm5vZGVSZWdBZGRyU3RyCQELdmFsdWVPckVsc2UCCQCiCAECHyVzJXNfX2NmZ19fbm9kZXNSZWdpc3RyeUFkZHJlc3MCIzNQOXZLcVFLalVkbXBYQWZpV2F1OGtyUkVZQVkxWHI2OXBFBAtub2RlUmVnQWRkcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUObm9kZVJlZ0FkZHJTdHIEEWxHcm91cE5vZGVMaXN0S0VZCQEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQUIZ3JvdXBOdW0ECmxHck5vZGVPcHQJAJ0IAgUEdGhpcwURbEdyb3VwTm9kZUxpc3RLRVkDCQEJaXNEZWZpbmVkAQUKbEdyTm9kZU9wdAkAAgEJAKwCAgkArAICAgZncm91cCAJAKQDAQUIZ3JvdXBOdW0CFCBhbHJlYWR5IGluaXRpYWxpemVkBAVuTGlzdAkAtQkCBQZuTGlzdFMFA1NFUAQIZXhwQ291bnQJAJADAQUFbklkeHMDCQECIT0CCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBm1uZ1B1YgkAAgECHmFwcHJvdmVMZWFzaW5ncyBub3QgYXV0aG9yaXplZAQNJHQwNDQyNzQ0NDMzNgkBDHJlYWROb2RlSW5mbwEAAAQGbkFkZHIwCAUNJHQwNDQyNzQ0NDMzNgJfMQQIbEFtdEtFWTAIBQ0kdDA0NDI3NDQ0MzM2Al8yBAVsQW10MAgFDSR0MDQ0Mjc0NDQzMzYCXzMEB2xJZEtFWTAIBQ0kdDA0NDI3NDQ0MzM2Al80BARsSWQwCAUNJHQwNDQyNzQ0NDMzNgJfNQQFbmV3TDAJAMQIAgUGbkFkZHIwCQBlAgUFbEFtdDAJAGgCBQRsQW10BQhleHBDb3VudAQKdmFsaWRhdGlvbgkA/AcEBQtub2RlUmVnQWRkcgIadmFsaWRhdGVBbmRBcHByb3ZlTGVhc2luZ3MJAMwIAgUGbkxpc3RTBQNuaWwFA25pbAMJAAACBQp2YWxpZGF0aW9uBQp2YWxpZGF0aW9uCgEjZm9yRWFjaE5vZGVWYWxpZGF0ZUFuZEdlbmVyYXRlTGVhc2UCAWEBaQQEbm9kZQkAkQMCBQVuTGlzdAUBaQQCbGEJAMQIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUEbm9kZQUEbEFtdAkAzggCBQFhCQDMCAIFAmxhCQDMCAIJAQtCaW5hcnlFbnRyeQIJARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQUEbm9kZQkBBWxjYWxjAQUCbGEJAMwIAgkBDEludGVnZXJFbnRyeQIJARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQEFBG5vZGUFBGxBbXQFA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFEWxHcm91cE5vZGVMaXN0S0VZBQZuTGlzdFMJAMwIAgkBC0JpbmFyeUVudHJ5AgUHbElkS0VZMAkBBWxjYWxjAQUFbmV3TDAJAMwIAgkBDEludGVnZXJFbnRyeQIFCGxBbXRLRVkwCAUFbmV3TDAGYW1vdW50CQDMCAIJAQtMZWFzZUNhbmNlbAEFBGxJZDAJAMwIAgUFbmV3TDAFA25pbAoAAiRsBQVuSWR4cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEjZm9yRWFjaE5vZGVWYWxpZGF0ZUFuZEdlbmVyYXRlTGVhc2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAICQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEXJlYmFsYW5jZUxlYXNpbmdzAgZhbW91bnQIZ3JvdXBOdW0EBW5JZHhzCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcFA25pbAQHbW5nUHViUwkBC3ZhbHVlT3JFbHNlAgkAoggBAhwlcyVzX19jZmdfX2xlYXNpbmdNYW5hZ2VyUHViAiw3QVVNWDU0dWtZTVl2UG1tYTd5b0ZmNU5qWmhzNEJ1NW56M0V6OUVWOHN1cgQGbW5nUHViCQDZBAEFB21uZ1B1YlMEEWxHcm91cE5vZGVMaXN0S0VZCQEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQUIZ3JvdXBOdW0EBm5MaXN0UwkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMFEWxHcm91cE5vZGVMaXN0S0VZBAVuTGlzdAkAtQkCBQZuTGlzdFMFA1NFUAMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUGbW5nUHViCQACAQIgcmViYWxhbmNlTGVhc2luZ3Mgbm90IGF1dGhvcml6ZWQECnVubGVhc2VBbXQJAGQCCQBpAgUGYW1vdW50CQCQAwEFBW5MaXN0AAEEDSR0MDQ1NTc2NDU2MzgJAQxyZWFkTm9kZUluZm8BAAAEBm5BZGRyMAgFDSR0MDQ1NTc2NDU2MzgCXzEECGxBbXRLRVkwCAUNJHQwNDU1NzY0NTYzOAJfMgQFbEFtdDAIBQ0kdDA0NTU3NjQ1NjM4Al8zBAdsSWRLRVkwCAUNJHQwNDU1NzY0NTYzOAJfNAQEbElkMAgFDSR0MDQ1NTc2NDU2MzgCXzUEBW5ld0wwCQDECAIFBm5BZGRyMAkAZAIFBWxBbXQwCQBoAgUKdW5sZWFzZUFtdAkAkAMBBQVuTGlzdAoBFGZvckVhY2hOb2RlRG9VbmxlYXNlAgFhAWkEBG5vZGUJAJEDAgUFbkxpc3QFAWkEBmxJZEtFWQkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQRub2RlBANsSWQJARFAZXh0ck5hdGl2ZSgxMDUyKQIFBHRoaXMFBmxJZEtFWQQHbEFtdEtFWQkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUEbm9kZQQEbEFtdAkBEUBleHRyTmF0aXZlKDEwNTApAgUEdGhpcwUHbEFtdEtFWQQDdWxhCQELTGVhc2VDYW5jZWwBCQEFdmFsdWUBBQNsSWQEAmxhCQDECAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBG5vZGUJAGUCBQRsQW10BQp1bmxlYXNlQW10CQDOCAIFAWEJAMwIAgkBC0xlYXNlQ2FuY2VsAQkBBXZhbHVlAQUDbElkCQDMCAIFAmxhCQDMCAIJAQtCaW5hcnlFbnRyeQIFBmxJZEtFWQkBBWxjYWxjAQUCbGEJAMwIAgkBDEludGVnZXJFbnRyeQIFB2xBbXRLRVkIBQJsYQZhbW91bnQFA25pbAkAzggCCgACJGwFBW5JZHhzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARRmb3JFYWNoTm9kZURvVW5sZWFzZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgOAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgJAMwIAgkBC0JpbmFyeUVudHJ5AgUHbElkS0VZMAkBBWxjYWxjAQUFbmV3TDAJAMwIAgkBDEludGVnZXJFbnRyeQIFCGxBbXRLRVkwCAUFbmV3TDAGYW1vdW50CQDMCAIJAQtMZWFzZUNhbmNlbAEFBGxJZDAJAMwIAgUFbmV3TDAFA25pbAFpARtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkCDnVzZXJBZGRyZXNzU3RyCWduc2J0RGlmZgQJZ25zYnREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIUZ25zYnRJbmZvU1lTUkVBRE9OTFkJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgAACQDMCAIAAAUDbmlsBQNuaWwECGduc2J0QW10CQBkAgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAAUJZ25zYnREaWZmBA1nbnNidEFtdFRvdGFsCQBkAgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAQUJZ25zYnREaWZmBA1zd2FwTGltaXREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCFWNhbGNTd2FwTGltaXRSRUFET05MWQkAzAgCBQhnbnNidEFtdAUDbmlsBQNuaWwEF3dhdmVzU3dhcExpbWl0SW5Vc2RuTWF4CQEFYXNJbnQBCQCRAwIFDXN3YXBMaW1pdERhdGEAAAQRd2F2ZXNTd2FwTGltaXRNYXgJAQVhc0ludAEJAJEDAgUNc3dhcExpbWl0RGF0YQABBBB1c2RuU3dhcExpbWl0TWF4CQEFYXNJbnQBCQCRAwIFDXN3YXBMaW1pdERhdGEAAgQObGFzdFN3YXBIZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFWtleVVzZXJMYXN0U3dhcEhlaWdodAEFDnVzZXJBZGRyZXNzU3RyAAAEF3N3YXBMaW1pdFRpbWVsaWZlQmxvY2tzCQESc3dhcHNUaW1lZnJhbWVSRUFEAAQZcGFzc2VkQmxvY2tzQWZ0ZXJMYXN0U3dhcAkAZQIFBmhlaWdodAUObGFzdFN3YXBIZWlnaHQEEWlzU3dhcFRpbWVsaWZlTmV3CQBnAgUZcGFzc2VkQmxvY2tzQWZ0ZXJMYXN0U3dhcAUXc3dhcExpbWl0VGltZWxpZmVCbG9ja3MEFHN3YXBMaW1pdFNwZW50SW5Vc2RuAwURaXNTd2FwVGltZWxpZmVOZXcAAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEYa2V5U3dhcFVzZXJTcGVudEluUGVyaW9kAQUOdXNlckFkZHJlc3NTdHIAAAQOYmxja3MyTG10UmVzZXQDBRFpc1N3YXBUaW1lbGlmZU5ldwAACQBlAgUXc3dhcExpbWl0VGltZWxpZmVCbG9ja3MFGXBhc3NlZEJsb2Nrc0FmdGVyTGFzdFN3YXAJAJQKAgUDbmlsCQCZCgcFF3dhdmVzU3dhcExpbWl0SW5Vc2RuTWF4BRRzd2FwTGltaXRTcGVudEluVXNkbgUOYmxja3MyTG10UmVzZXQFCGduc2J0QW10BQ1nbnNidEFtdFRvdGFsBRF3YXZlc1N3YXBMaW1pdE1heAUQdXNkblN3YXBMaW1pdE1heAFpAR1jYWxjV2l0aGRyYXdSZXN1bHRTWVNSRUFET05MWQQIc3dhcFR5cGUIaW5BbW91bnQFcHJpY2UHaW5Bc3NldAQPbmV1dHJpbm9NZXRyaWNzCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAkAlAoCBQNuaWwJAQxjYWxjV2l0aGRyYXcFBQhzd2FwVHlwZQUIaW5BbW91bnQFBXByaWNlBQ9uZXV0cmlub01ldHJpY3MFB2luQXNzZXQBaQEUcmVwbGFjZUNvbW11bml0eU5vZGUECm9sZEFkZHJTdHIKbmV3QWRkclN0cghncm91cE51bQ1wZW5hbHR5QW1vdW50BAdtbmdQdWJTCQELdmFsdWVPckVsc2UCCQCiCAECHCVzJXNfX2NmZ19fbGVhc2luZ01hbmFnZXJQdWICLDdBVU1YNTR1a1lNWXZQbW1hN3lvRmY1TmpaaHM0QnU1bnozRXo5RVY4c3VyBAZtbmdQdWIJANkEAQUHbW5nUHViUwMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUGbW5nUHViCQACAQIjcmVwbGFjZUNvbW11bml0eU5vZGUgbm90IGF1dGhvcml6ZWQECGdyb3VwS2V5CQEYZ2V0TGVhc2VHcm91cE5vZGVMaXN0S2V5AQUIZ3JvdXBOdW0EDmdyb3VwTm9kZUxpc3RTCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwUIZ3JvdXBLZXkDCQEBIQEJAQhjb250YWlucwIFDmdyb3VwTm9kZUxpc3RTBQpvbGRBZGRyU3RyCQACAQkArAICCQCsAgIJAKwCAgIGR3JvdXAgCQCkAwEFCGdyb3VwTnVtAhogZG9lcyBub3QgY29udGFpbiBhZGRyZXNzIAUKb2xkQWRkclN0cgQJZG9SZXBsYWNlCQD8BwQFFG5vZGVSZWdpc3RyeUNvbnRyYWN0AhNyZXBsYWNlQXBwcm92ZWROb2RlCQDMCAIFCm9sZEFkZHJTdHIJAMwIAgUKbmV3QWRkclN0cgkAzAgCBQhncm91cE51bQkAzAgCBQ1wZW5hbHR5QW1vdW50BQNuaWwFA25pbAMJAAACBQlkb1JlcGxhY2UFCWRvUmVwbGFjZQQNb2xkTGVhc2VJZEtleQkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQpvbGRBZGRyU3RyBA5vbGRMZWFzZUFtdEtleQkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUKb2xkQWRkclN0cgQIbGVhc2VBbXQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFDm9sZExlYXNlQW10S2V5BA1uZXdMZWFzZUlkS2V5CQEWZ2V0TGVhc2VJZEJ5QWRkcmVzc0tleQEFCm5ld0FkZHJTdHIEDm5ld0xlYXNlQW10S2V5CQEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBBQpuZXdBZGRyU3RyBAhuZXdMZWFzZQkAxAgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQpuZXdBZGRyU3RyBQhsZWFzZUFtdAQVdXBkYXRlZEdyb3VwTm9kZUxpc3RTCQC5CQIJALUJAgUOZ3JvdXBOb2RlTGlzdFMFCm9sZEFkZHJTdHIFCm5ld0FkZHJTdHIJAJQKAgkAzAgCCQELTGVhc2VDYW5jZWwBCQERQGV4dHJOYXRpdmUoMTA1NykBBQ1vbGRMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFDW9sZExlYXNlSWRLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUOb2xkTGVhc2VBbXRLZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgUIZ3JvdXBLZXkFFXVwZGF0ZWRHcm91cE5vZGVMaXN0UwkAzAgCBQhuZXdMZWFzZQkAzAgCCQELQmluYXJ5RW50cnkCBQ1uZXdMZWFzZUlkS2V5CQEFbGNhbGMBBQhuZXdMZWFzZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUObmV3TGVhc2VBbXRLZXkFCGxlYXNlQW10BQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEfdXBkYXRlUmVzZXJ2ZXNBbmROZXV0cmlub1N1cHBseQAKARZnZXROdW1iZXJCeUtleUludGVybmFsAQNrZXkEByRtYXRjaDAJAJoIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACA0ludAQBYQUHJG1hdGNoMAUBYQAABAduTWV0cml4CQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAQDaWR4CQEWZ2V0TnVtYmVyQnlLZXlJbnRlcm5hbAECInVwZGF0ZVJlc2VydmVzQW5kTmV1dHJpbm9TdXBwbHlJZHgEBm5ld0lkeAkAZAIFA2lkeAABCQDMCAIJAQxJbnRlZ2VyRW50cnkCAiJ1cGRhdGVSZXNlcnZlc0FuZE5ldXRyaW5vU3VwcGx5SWR4BQZuZXdJZHgJAMwIAgkBDEludGVnZXJFbnRyeQICB3Jlc2VydmUJAQVhc0ludAEJAJEDAgUHbk1ldHJpeAADCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg5uZXV0cmlub1N1cHBseQkBBWFzSW50AQkAkQMCBQduTWV0cml4AAUJAMwIAgkBDEludGVnZXJFbnRyeQICDnJlc2VydmVzSW5Vc2RuCQEWY29udmVydFdhdmVzVG9OZXV0cmlubwIJAQVhc0ludAEJAJEDAgUHbk1ldHJpeAADCQEFYXNJbnQBCQCRAwIFB25NZXRyaXgAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgIHc3VycGx1cwkBBWFzSW50AQkAkQMCBQduTWV0cml4AAYJAMwIAgkBDEludGVnZXJFbnRyeQICB2RlZmljaXQJAQEtAQkBBWFzSW50AQkAkQMCBQduTWV0cml4AAYFA25pbAFpARZ3YXZlc0JhbGFuY2VzVnNQYXltZW50AAQBYgkA7wcBBQR0aGlzCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhZ3YXZlc0JhbGFuY2VfYXZhaWxhYmxlCAUBYglhdmFpbGFibGUJAMwIAgkBDEludGVnZXJFbnRyeQICFHdhdmVzQmFsYW5jZV9yZWd1bGFyCAUBYgdyZWd1bGFyCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhd3YXZlc0JhbGFuY2VfZ2VuZXJhdGluZwgFAWIKZ2VuZXJhdGluZwkAzAgCCQEMSW50ZWdlckVudHJ5AgIWd2F2ZXNCYWxhbmNlX2VmZmVjdGl2ZQgFAWIJZWZmZWN0aXZlCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg13YXZlc19wYXltZW50CAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAUDbmlsAQJ0eAEGdmVyaWZ5AAQTcHViS2V5QWRtaW5zTGlzdFN0cgkAuQkCCQDMCAICLEV4dEVFSzE5bm1LajltQ3BuV3l2RUVKRllBVExNY1ZFTXZvaGhVSGt5SE5tCQDMCAICLEV2NXB5NUZmQlFYOWNacFlLbmZRclRCNDlCeWY4UW1wWldlRFZSaW00eVY3CQDMCAICLERVdXVMalh1OThuQndaYzdmcXdDVGp0QTNublJ3Z1Ria01TcjVTVTJObURSCQDMCAICLERVdXVMalh1OThuQndaYzdmcXdDVGp0QTNublJ3Z1Ria01TcjVTVTJObURSBQNuaWwFA1NFUAQQcHViS2V5QWRtaW5zTGlzdAkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFD2NvbnRyb2xDb250cmFjdAIMJXNfX211bHRpc2lnBRNwdWJLZXlBZG1pbnNMaXN0U3RyBQNTRVAEBWNvdW50CQBkAgkAZAIJAGQCAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAAABAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwABCQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAABAAEAAAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAIJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAIAAQAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAwkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAwACAAADAwUJaXNCbG9ja2VkCQAAAgkBEUBleHRyTmF0aXZlKDEwNTMpAgUPY29udHJvbENvbnRyYWN0AhFpc19ibG9ja2VkX2NhbGxlcgkApQgBBQtnb3ZDb250cmFjdAcJAQ52YWxpZGF0ZVVwZGF0ZQEFAnR4BAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhVTcG9uc29yRmVlVHJhbnNhY3Rpb24ECXNwb25zb3JUeAUHJG1hdGNoMAMJARtjaGVja0lzVmFsaWRNaW5TcG9uc29yZWRGZWUBBQlzcG9uc29yVHgJAGcCBQVjb3VudAADBwkAZwIFBWNvdW50AAO4FSQV", "height": 2448062, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: Bi6w1hpzb6bjRUTXkGGV8UXiVBQpKLuDqzpkx2Ktyskq Next: HrvA2fyuXh2wFLNEfwYzVDszX633VY1ycmDS35HK7UAj Diff:
OldNewDifferences
383383 else {
384384 let outAmount = fraction(amount, reserv, neutrinoSupply)
385385 let wavesTuple = if ((assetId == "WAVES"))
386- then throw(((((("amount=" + toString(amount)) + " reserv=") + toString(reserv)) + "nS=") + toString(neutrinoSupply)))
386+ then $Tuple2(outAmount, price)
387387 else $Tuple2(acc._2, acc._3)
388388 $Tuple3((acc._1 :+ $Tuple4(assetId, outAmount, price, share)), wavesTuple._1, wavesTuple._2)
389389 }
677677 else 0
678678 let allowedUsdn = (allowedUsdnBeforeMinBr + allowedUsdnAfterMinBr)
679679 let usdn2SURF = (usdnIn - allowedUsdn)
680- let outAmtGross = convertNeutrinoToBasket(allowedUsdn, basketInfo, neutrinoSupply)
681- $Tuple12(outAmtGross._2, unit, usdn2SURF, neutrinoAssetId, outAmtGross._2, outAmtGross._3, allowedUsdn, maxAllowedUsdnBeforeMinBr, allowedUsdnBeforeMinBr, allowedUsdnAfterMinBr, outAmtGross._1, nil)
680+ if ((1 == 1))
681+ then throw(((((((((("usdnIn=" + toString(usdnIn)) + "mA") + toString(maxAllowedUsdnBeforeMinBr)) + " aBef=") + toString(allowedUsdnBeforeMinBr)) + " aAft=") + toString(allowedUsdnAfterMinBr)) + " allowedUsdn=") + toString(allowedUsdn)))
682+ else {
683+ let outAmtGross = convertNeutrinoToBasket(allowedUsdn, basketInfo, neutrinoSupply)
684+ $Tuple12(outAmtGross._2, unit, usdn2SURF, neutrinoAssetId, outAmtGross._2, outAmtGross._3, allowedUsdn, maxAllowedUsdnBeforeMinBr, allowedUsdnBeforeMinBr, allowedUsdnAfterMinBr, outAmtGross._1, nil)
685+ }
682686 }
683687
684688
10481052 if ((i.callerPublicKey != mngPub))
10491053 then throw("approveLeasings not authorized")
10501054 else {
1051- let $t04412644188 = readNodeInfo(0)
1052- let nAddr0 = $t04412644188._1
1053- let lAmtKEY0 = $t04412644188._2
1054- let lAmt0 = $t04412644188._3
1055- let lIdKEY0 = $t04412644188._4
1056- let lId0 = $t04412644188._5
1055+ let $t04427444336 = readNodeInfo(0)
1056+ let nAddr0 = $t04427444336._1
1057+ let lAmtKEY0 = $t04427444336._2
1058+ let lAmt0 = $t04427444336._3
1059+ let lIdKEY0 = $t04427444336._4
1060+ let lId0 = $t04427444336._5
10571061 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
10581062 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
10591063 if ((validation == validation))
10981102 then throw("rebalanceLeasings not authorized")
10991103 else {
11001104 let unleaseAmt = ((amount / size(nList)) + 1)
1101- let $t04542845490 = readNodeInfo(0)
1102- let nAddr0 = $t04542845490._1
1103- let lAmtKEY0 = $t04542845490._2
1104- let lAmt0 = $t04542845490._3
1105- let lIdKEY0 = $t04542845490._4
1106- let lId0 = $t04542845490._5
1105+ let $t04557645638 = readNodeInfo(0)
1106+ let nAddr0 = $t04557645638._1
1107+ let lAmtKEY0 = $t04557645638._2
1108+ let lAmt0 = $t04557645638._3
1109+ let lIdKEY0 = $t04557645638._4
1110+ let lId0 = $t04557645638._5
11071111 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
11081112 func forEachNodeDoUnlease (a,i) = {
11091113 let node = nList[i]
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
55
66
77 func lcalc (l) = calculateLeaseId(l)
88
99
1010 func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0)
1111
1212
1313 func getStringByKey (key) = valueOrElse(getString(this, key), "")
1414
1515
1616 func getBoolByKey (key) = valueOrElse(getBoolean(this, key), false)
1717
1818
1919 func getNumberByAddressAndKey (address,key) = valueOrElse(getInteger(address, key), 0)
2020
2121
2222 func getStringByAddressAndKey (address,key) = valueOrElse(getString(addressFromStringValue(address), key), "")
2323
2424
2525 func getBoolByAddressAndKey (address,key) = valueOrElse(getBoolean(address, key), false)
2626
2727
2828 func asAnyList (v) = match v {
2929 case l: List[Any] =>
3030 l
3131 case _ =>
3232 throw("fail to cast into List[Any]")
3333 }
3434
3535
3636 func asString (v) = match v {
3737 case s: String =>
3838 s
3939 case _ =>
4040 throw("fail to cast into String")
4141 }
4242
4343
4444 func asInt (v) = match v {
4545 case i: Int =>
4646 i
4747 case _ =>
4848 throw("fail to cast into Int")
4949 }
5050
5151
5252 func asBytes (val) = match val {
5353 case valByte: ByteVector =>
5454 valByte
5555 case _ =>
5656 throw("fail to cast into ByteVector")
5757 }
5858
5959
6060 func asPayment (v) = match v {
6161 case p: AttachedPayment =>
6262 p
6363 case _ =>
6464 throw("fail to cast into AttachedPayment")
6565 }
6666
6767
6868 func asSwapParamsSTRUCT (v) = match v {
6969 case struct: (Int, Int, Int, Int, Int, Int, Int) =>
7070 struct
7171 case _ =>
7272 throw("fail to cast into Tuple5 ints")
7373 }
7474
7575
7676 let SEP = "__"
7777
7878 let LISTSEP = ":"
7979
8080 let MULT8 = 100000000
8181
8282 let MULT6 = 1000000
8383
8484 let DEFAULTSWAPFEE = 20000
8585
8686 let BRPROTECTED = 100000
8787
8888 let WAVESID = base58'WAVES'
8989
9090 let nMetricIdxPrice = 0
9191
9292 let nMetricIdxUsdnLockedBalance = 1
9393
9494 let nMetricIdxWavesLockedBalance = 2
9595
9696 let nMetricIdxReserve = 3
9797
9898 let nMetricIdxReserveInUsdn = 4
9999
100100 let nMetricIdxUsdnSupply = 5
101101
102102 let nMetricIdxSurplus = 6
103103
104104 let nMetricIdxSurplusPercent = 7
105105
106106 let nMetricIdxBR = 8
107107
108108 let nMetricIdxNsbtSupply = 9
109109
110110 let nMetricIdxMaxNsbtSupply = 10
111111
112112 let nMetricIdxSurfSupply = 11
113113
114114 let nMetricUsdnUsdtPeg = 12
115115
116116 let nMetricCurrentPriceAdj = 13
117117
118118 let nMetricBasketInfo = 14
119119
120120 let nMetricWeightedPrice = 15
121121
122122 let nMetricTotalReservesUsd = 16
123123
124124 let IdxControlCfgNeutrinoDapp = 1
125125
126126 let IdxControlCfgAuctionDapp = 2
127127
128128 let IdxControlCfgRpdDapp = 3
129129
130130 let IdxControlCfgMathDapp = 4
131131
132132 let IdxControlCfgLiquidationDapp = 5
133133
134134 let IdxControlCfgRestDapp = 6
135135
136136 let IdxControlCfgNodeRegistryDapp = 7
137137
138138 let IdxControlCfgNsbtStakingDapp = 8
139139
140140 let IdxControlCfgMediatorDapp = 9
141141
142142 let IdxControlCfgSurfStakingDapp = 10
143143
144144 let IdxControlCfgGnsbtControllerDapp = 11
145145
146146 let IdxControlCfgRestV2Dapp = 12
147147
148148 let IdxControlCfgGovernanceDapp = 13
149149
150150 func keyControlAddress () = "%s%s__config__controlAddress"
151151
152152
153153 func keyControlCfg () = "%s__controlConfig"
154154
155155
156156 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
157157
158158
159159 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
160160
161161
162162 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3N4NS7d4Jo9a6F14LiFUKKYVdUkkf2eP4Zx"))
163163
164164 let controlCfg = readControlCfgOrFail(controlContract)
165165
166166 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
167167
168168 let nsbtStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgNsbtStakingDapp)
169169
170170 let surfStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgSurfStakingDapp)
171171
172172 let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
173173
174174 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
175175
176176 let nodeRegistryContract = getContractAddressOrFail(controlCfg, IdxControlCfgNodeRegistryDapp)
177177
178178 let govContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
179179
180180 let NeutrinoAssetIdKey = "neutrino_asset_id"
181181
182182 let BondAssetIdKey = "bond_asset_id"
183183
184184 let AuctionContractKey = "auction_contract"
185185
186186 let NsbtStakingContractKey = "nsbtStakingContract"
187187
188188 let LiquidationContractKey = "liquidation_contract"
189189
190190 let RPDContractKey = "rpd_contract"
191191
192192 let ContolContractKey = "control_contract"
193193
194194 let MathContractKey = "math_contract"
195195
196196 let BalanceWavesLockIntervalKey = "balance_waves_lock_interval"
197197
198198 let BalanceNeutrinoLockIntervalKey = "balance_neutrino_lock_interval"
199199
200200 func MinTokenSwapAmountKey (assetId) = ("min_outNeutrino_swap_amount_" + assetId)
201201
202202
203203 let MinNeutrinoSwapAmountKey = "min_outMulti_swap_amount"
204204
205205 let NodeOracleProviderPubKeyKey = "node_oracle_provider"
206206
207207 let NeutrinoOutFeePartKey = "neutrinoOut_swap_feePart"
208208
209209 let WavesOutFeePartKey = "wavesOut_swap_feePart"
210210
211211 func keyNodeRegistry (address) = ("%s__" + address)
212212
213213
214214 let PriceKey = "price"
215215
216216 let PriceIndexKey = "price_index"
217217
218218 let IsBlockedKey = "is_blocked"
219219
220220 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
221221
222222
223223 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
224224
225225
226226 func getStakingNodeByIndex (idx) = getStringByKey(makeString(["%s%d%s", "lease", toString(idx), "nodeAddress"], SEP))
227227
228228
229229 func getStakingNodeAddressByIndex (idx) = addressFromStringValue(getStakingNodeByIndex(idx))
230230
231231
232232 func getReservedAmountForSponsorship () = valueOrElse(getInteger(this, makeString(["%s%s", "lease", "sponsorshipWavesReserve"], SEP)), (1000 * MULT8))
233233
234234
235235 func getBalanceUnlockBlockKey (owner) = ("balance_unlock_block_" + owner)
236236
237237
238238 func getLeaseIdKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "id"], SEP)
239239
240240
241241 func getLeaseIdByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "id"], SEP)
242242
243243
244244 func getLeaseAmountKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "amount"], SEP)
245245
246246
247247 func getLeaseAmountByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "amount"], SEP)
248248
249249
250250 func getLeaseGroupNodeListKey (groupNum) = makeString(["%s%d%s", "leaseGroup", toString(groupNum), "nodeList"], SEP)
251251
252252
253253 func minSwapAmountKEY (swapType) = (("min_" + swapType) + "_swap_amount")
254254
255255
256256 func totalLockedKEY (swapType,assetId) = makeString(["%s%s%s", "balanceLock", swapType, assetId], SEP)
257257
258258
259259 func totalLockedByUserKEY (swapType,owner,assetId) = makeString(["%s%s%s%s", "balanceLock", swapType, owner, assetId], "_")
260260
261261
262262 func balanceLockIntervalKEY (swapType) = if ((swapType == "outMulti"))
263263 then BalanceNeutrinoLockIntervalKey
264264 else BalanceWavesLockIntervalKey
265265
266266
267267 func nodeBalanceLockIntervalKEY () = "balance_node_lock_interval"
268268
269269
270270 func swapsTimeframeKEY () = "swaps_timeframe"
271271
272272
273273 func brProtectedKEY () = "min_BR_protection_level"
274274
275275
276276 func basketAssetsKey () = "%s%s__common__basketAssets"
277277
278278
279279 func basketDKey () = "%s%s__common__basketD"
280280
281281
282282 func basketKKey () = "%s%s__common__basketK"
283283
284284
285285 func basketBKey () = "%s%s__common__basketB"
286286
287287
288288 func basketLogbDeltaKey () = "%s%s__common__basketLogbDelta"
289289
290290
291291 func basketWeightByAssetKey (assetId) = ("%s%s%s__common__weightByAsset__" + assetId)
292292
293293
294294 func minSwapAmountREAD (swapType,assetId) = valueOrElse(if ((swapType == "outMulti"))
295295 then getInteger(MinNeutrinoSwapAmountKey)
296296 else getInteger(MinTokenSwapAmountKey(assetId)), 0)
297297
298298
299299 func swapsTimeframeREAD () = valueOrElse(getInteger(this, swapsTimeframeKEY()), 1440)
300300
301301
302302 func totalLockedREAD (swapType,assetId) = valueOrElse(getInteger(this, totalLockedKEY(swapType, assetId)), 0)
303303
304304
305305 func totalLockedByUserREAD (swapType,owner,assetId) = valueOrElse(getInteger(this, totalLockedByUserKEY(swapType, owner, assetId)), 0)
306306
307307
308308 func balanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, balanceLockIntervalKEY(swapType)), 1440)
309309
310310
311311 func nodeBalanceLockIntervalREAD () = valueOrElse(getInteger(this, nodeBalanceLockIntervalKEY()), 1)
312312
313313
314314 func keySwapUserSpentInPeriod (userAddress) = makeString(["%s%s", "swapUserSpentInPeriod", userAddress], SEP)
315315
316316
317317 func keyUserLastSwapHeight (userAddress) = makeString(["%s%s", "userLastSwapHeight", userAddress], SEP)
318318
319319
320320 func convertNeutrinoToWaves (amount,price) = fraction(amount, MULT8, price)
321321
322322
323323 func convertWavesToNeutrino (amount,price) = fraction(amount, price, MULT8)
324324
325325
326326 func convertWavesToBond (amount,price) = convertWavesToNeutrino(amount, price)
327327
328328
329329 func convertJsonArrayToList (jsonArray) = split(jsonArray, ",")
330330
331331
332332 func convertBasketItemToNeutrino (inAmount,inAsset,basketInfoStr,neutrinoPrice) = {
333333 let basketInfo = split(basketInfoStr, "_")
334334 func findItem (acc,item) = {
335335 let bItem = split(item, LISTSEP)
336336 if ((bItem[0] == inAsset))
337337 then bItem
338338 else acc
339339 }
340340
341341 let it = {
342342 let $l = basketInfo
343343 let $s = size($l)
344344 let $acc0 = nil
345345 func $f0_1 ($a,$i) = if (($i >= $s))
346346 then $a
347347 else findItem($a, $l[$i])
348348
349349 func $f0_2 ($a,$i) = if (($i >= $s))
350350 then $a
351351 else throw("List size exceeds 10")
352352
353353 $f0_2($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)
354354 }
355355 let dlog6 = valueOrElse(getInteger(basketLogbDeltaKey()), -18820642)
356356 let d6 = valueOrElse(getInteger(basketDKey()), 50000)
357357 let b6 = valueOrElse(getInteger(basketBKey()), 1250000)
358358 let w6 = valueOrElse(getInteger(basketWeightByAssetKey(inAsset)), 166666)
359359 let p6 = ((dlog6 - w6) + parseIntValue(it[1]))
360360 let pp6 = pow(b6, 6, p6, 6, 6, HALFUP)
361361 let outAmountGross = fraction(inAmount, parseIntValue(it[2]), if ((neutrinoPrice == 0))
362362 then MULT8
363363 else (neutrinoPrice * 100))
364364 let multiplier = ((MULT6 + d6) - pp6)
365365 let netAmount = fraction(outAmountGross, multiplier, MULT6)
366366 let feeAmount = if ((netAmount >= outAmountGross))
367367 then 0
368368 else (outAmountGross - netAmount)
369369 [outAmountGross, netAmount, feeAmount]
370370 }
371371
372372
373373 func convertNeutrinoToBasket (amount,basketInfoStr,neutrinoSupply) = {
374374 let basketInfo = split(basketInfoStr, "_")
375375 func conv (acc,item) = {
376376 let parts = split(item, LISTSEP)
377377 let assetId = parts[0]
378378 let share = parseIntValue(parts[1])
379379 let price = parseIntValue(parts[2])
380380 let reserv = parseIntValue(parts[3])
381381 if ((neutrinoSupply == 0))
382382 then throw("Attempt to burn neutrino at zero supply")
383383 else {
384384 let outAmount = fraction(amount, reserv, neutrinoSupply)
385385 let wavesTuple = if ((assetId == "WAVES"))
386- then throw(((((("amount=" + toString(amount)) + " reserv=") + toString(reserv)) + "nS=") + toString(neutrinoSupply)))
386+ then $Tuple2(outAmount, price)
387387 else $Tuple2(acc._2, acc._3)
388388 $Tuple3((acc._1 :+ $Tuple4(assetId, outAmount, price, share)), wavesTuple._1, wavesTuple._2)
389389 }
390390 }
391391
392392 let $l = basketInfo
393393 let $s = size($l)
394394 let $acc0 = $Tuple3(nil, 0, 0)
395395 func $f0_1 ($a,$i) = if (($i >= $s))
396396 then $a
397397 else conv($a, $l[$i])
398398
399399 func $f0_2 ($a,$i) = if (($i >= $s))
400400 then $a
401401 else throw("List size exceeds 10")
402402
403403 $f0_2($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)
404404 }
405405
406406
407407 func minSwapAmountFAIL (swapType,minSwapAmount) = throw(((("The specified amount in " + swapType) + " swap is less than the required minimum of ") + toString(minSwapAmount)))
408408
409409
410410 func emergencyShutdownFAIL () = throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
411411
412412
413413 func priceIndexFAIL (index,priceIndex,indexHeight,unlockHeight,prevIndexHeight) = throw(((((((((("invalid price history index: index=" + toString(index)) + " priceIndex=") + toString(priceIndex)) + " indexHeight=") + toString(indexHeight)) + " unlockHeight=") + toString(unlockHeight)) + " prevIndexHeight=") + toString(prevIndexHeight)))
414414
415415
416416 let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
417417
418418 let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
419419
420420 let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
421421
422422 let nodeOracleProviderPubKey = fromBase58String(getStringByKey(NodeOracleProviderPubKeyKey))
423423
424424 let bondAssetId = fromBase58String("F3iaxzruFeKujfVfYSZEkejpjh67wmRfPCRHiNmWKp3Z")
425425
426426 let deprecatedBondAssetId = fromBase58String("975akZBfnMj513U7MZaHKzQrmsEx5aE3wdWKTrHBhbjF")
427427
428428 let neutrinoContract = this
429429
430430 let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
431431
432432 func checkIsValidMinSponsoredFee (tx) = {
433433 let MINTRANSFERFEE = 100000
434434 let SponsoredFeeUpperBound = 1000
435435 let realNeutrinoFee = convertWavesToNeutrino(MINTRANSFERFEE, currentPrice)
436436 let minNeutrinoFee = (realNeutrinoFee * 2)
437437 let maxNeutrinoFee = fraction(realNeutrinoFee, SponsoredFeeUpperBound, 100)
438438 let inputFee = value(tx.minSponsoredAssetFee)
439439 if (if ((inputFee >= minNeutrinoFee))
440440 then (maxNeutrinoFee >= inputFee)
441441 else false)
442442 then (tx.assetId == neutrinoAssetId)
443443 else false
444444 }
445445
446446
447447 func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
448448
449449
450450 func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
451451
452452
453453 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", userAddress, "amount"], SEP)
454454
455455
456456 let sIdxSwapType = 1
457457
458458 let sIdxStatus = 2
459459
460460 let sIdxInAmount = 3
461461
462462 let sIdxStartHeight = 7
463463
464464 let sIdxStartTimestamp = 8
465465
466466 let sIdxSelfUnlockHeight = 11
467467
468468 let sIdxMinRand = 15
469469
470470 let sIdxMaxRand = 16
471471
472472 let sIdxInAsset = 20
473473
474474 func swapKEY (userAddress,txId) = makeString(["%s%s", userAddress, txId], SEP)
475475
476476
477477 func strSwapDATA (swapType,status,inAmount,price,outNetAmount,outFeeAmount,startHeight,startTimestamp,endHeight,endTimestamp,selfUnlockHeight,randUnlockHeight,index,withdrawTxId,randMin,randMax,outSurfAmt,br,basketData,inAsset) = makeString(["%s%s%d%d%d%d%d%d%d%d%d%d%d%s%d%d%d%d%s%s", swapType, status, inAmount, price, outNetAmount, outFeeAmount, startHeight, startTimestamp, endHeight, endTimestamp, selfUnlockHeight, randUnlockHeight, index, withdrawTxId, randMin, randMax, outSurfAmt, br, basketData, inAsset], SEP)
478478
479479
480480 func pendingSwapDATA (swapType,inAssetAmount,selfUnlockHeight,inAsset) = strSwapDATA(swapType, "PENDING", toString(inAssetAmount), "0", "0", "0", toString(height), toString(lastBlock.timestamp), "0", "0", toString(selfUnlockHeight), "0", "0", "NULL", "0", "0", "0", "0", "", inAsset)
481481
482482
483483 func finishSwapDATA (dataArray,price,outNetAmount,outFeeAmount,randUnlockHeight,index,withdrawTxId,outSurfAmt,br,basketData,inAsset) = strSwapDATA(dataArray[sIdxSwapType], "FINISHED", dataArray[sIdxInAmount], toString(price), toString(outNetAmount), toString(outFeeAmount), dataArray[sIdxStartHeight], dataArray[sIdxStartTimestamp], toString(height), toString(lastBlock.timestamp), dataArray[sIdxSelfUnlockHeight], toString(randUnlockHeight), toString(index), withdrawTxId, dataArray[sIdxMinRand], dataArray[sIdxMaxRand], toString(outSurfAmt), toString(br), basketData, inAsset)
484484
485485
486486 func swapDataFailOrREAD (userAddress,swapTxId) = {
487487 let swapKey = swapKEY(userAddress, swapTxId)
488488 split_4C(valueOrErrorMessage(getString(swapKey), ("no swap data for " + swapKey)), SEP)
489489 }
490490
491491
492492 func applyFees (amountOutGross,inAmtToSURF,feePart) = {
493493 let feeAmount = fraction(amountOutGross, feePart, MULT6)
494494 [(amountOutGross - feeAmount), feeAmount]
495495 }
496496
497497
498498 func applyFeesBasket (basketOut) = {
499499 let k6 = valueOrElse(getInteger(basketKKey()), MULT6)
500500 let d6 = valueOrElse(getInteger(basketDKey()), 50000)
501501 let feePart = fraction(k6, d6, MULT6)
502502 func feeApplier (acc,item) = {
503503 let feeAmount = fraction(item._2, feePart, MULT6)
504504 (acc :+ makeString([item._1, toString(item._3), toString((item._2 - feeAmount)), toString(feeAmount), toString(item._4)], LISTSEP))
505505 }
506506
507507 let a = {
508508 let $l = basketOut
509509 let $s = size($l)
510510 let $acc0 = nil
511511 func $f0_1 ($a,$i) = if (($i >= $s))
512512 then $a
513513 else feeApplier($a, $l[$i])
514514
515515 func $f0_2 ($a,$i) = if (($i >= $s))
516516 then $a
517517 else throw("List size exceeds 10")
518518
519519 $f0_2($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)
520520 }
521521 makeString(a, SEP)
522522 }
523523
524524
525525 func abs (x) = if ((0 > x))
526526 then -(x)
527527 else x
528528
529529
530530 func selectNode (unleaseAmount) = {
531531 let amountToLease = ((wavesBalance(neutrinoContract).available - unleaseAmount) - getReservedAmountForSponsorship())
532532 let oldLeased0 = getNumberByKey(getLeaseAmountKey(0))
533533 let oldLeased1 = getNumberByKey(getLeaseAmountKey(1))
534534 let newLeased0 = (amountToLease + oldLeased0)
535535 let newLeased1 = (amountToLease + oldLeased1)
536536 if (if ((newLeased0 > 0))
537537 then true
538538 else (newLeased1 > 0))
539539 then {
540540 let delta0 = abs((newLeased0 - oldLeased1))
541541 let delta1 = abs((newLeased1 - oldLeased0))
542542 if ((delta1 >= delta0))
543543 then $Tuple2(0, newLeased0)
544544 else $Tuple2(1, newLeased1)
545545 }
546546 else $Tuple2(-1, 0)
547547 }
548548
549549
550550 func thisOnly (i) = if ((i.caller != this))
551551 then throw("Permission denied: this contract only allowed")
552552 else true
553553
554554
555555 func prepareUnleaseAndLease (unleaseAmount) = {
556556 let nodeTuple = selectNode(unleaseAmount)
557557 let nodeIndex = nodeTuple._1
558558 let newLeaseAmount = nodeTuple._2
559559 if ((newLeaseAmount > 0))
560560 then {
561561 let leaseIdKey = getLeaseIdKey(nodeIndex)
562562 let oldLease = getBinary(this, leaseIdKey)
563563 let unleaseOrEmpty = if (isDefined(oldLease))
564564 then [LeaseCancel(value(oldLease))]
565565 else nil
566566 let leaseAmountKey = getLeaseAmountKey(nodeIndex)
567567 let lease = Lease(getStakingNodeAddressByIndex(nodeIndex), newLeaseAmount)
568568 (unleaseOrEmpty ++ [lease, BinaryEntry(leaseIdKey, lcalc(lease)), IntegerEntry(getLeaseAmountKey(nodeIndex), newLeaseAmount)])
569569 }
570570 else nil
571571 }
572572
573573
574574 func readNodeInfo (nodeIdx) = {
575575 let nodeAddress = getStakingNodeAddressByIndex(nodeIdx)
576576 let leasedAmtKEY = getLeaseAmountKey(nodeIdx)
577577 let leasedAmt = getNumberByKey(leasedAmtKEY)
578578 let leaseIdKEY = getLeaseIdKey(nodeIdx)
579579 let leaseId = value(getBinary(this, leaseIdKEY))
580580 $Tuple5(nodeAddress, leasedAmtKEY, leasedAmt, leaseIdKEY, leaseId)
581581 }
582582
583583
584584 func commonSwap (swapType,pmtAmount,inAsset,userAddressStr,txId58) = {
585585 let swapParamsSTRUCT = asSwapParamsSTRUCT(invoke(this, "swapParamsByUserSYSREADONLY", [userAddressStr, 0], nil))
586586 let swapLimitSpent = swapParamsSTRUCT._2
587587 let blcks2LmtReset = swapParamsSTRUCT._3
588588 let wavesSwapLimitMax = swapParamsSTRUCT._6
589589 let usdnSwapLimitMax = swapParamsSTRUCT._7
590590 let minSwapAmount = minSwapAmountREAD(swapType, inAsset)
591591 let totalLocked = totalLockedREAD(swapType, inAsset)
592592 let totalLockedByUser = totalLockedByUserREAD(swapType, userAddressStr, inAsset)
593593 let nodeAddress = getStakingNodeByIndex(0)
594594 let priceByIndex = getPriceHistory(getHeightPriceByIndex(priceIndex))
595595 let isSwapByNode = (nodeAddress == userAddressStr)
596596 let balanceLockMaxInterval = if (isSwapByNode)
597597 then nodeBalanceLockIntervalREAD()
598598 else balanceLockIntervalREAD(swapType)
599599 let selfUnlockHeight = (height + balanceLockMaxInterval)
600600 let swapUsdnVolume = if ((swapType == "outNeutrino"))
601601 then convertWavesToNeutrino(pmtAmount, priceByIndex)
602602 else pmtAmount
603603 let swapLimitMax = if ((swapType == "outNeutrino"))
604604 then convertWavesToNeutrino(wavesSwapLimitMax, priceByIndex)
605605 else usdnSwapLimitMax
606606 if ((minSwapAmount > pmtAmount))
607607 then minSwapAmountFAIL(swapType, minSwapAmount)
608608 else if (if (!(isSwapByNode))
609609 then (swapLimitSpent > 0)
610610 else false)
611611 then throw(("You have exceeded swap limit! Next allowed swap height is " + toString((height + blcks2LmtReset))))
612612 else if (if (!(isSwapByNode))
613613 then (swapUsdnVolume > swapLimitMax)
614614 else false)
615615 then throw(((("You have exceeded your swap limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(swapLimitMax)))
616616 else if (isBlocked)
617617 then emergencyShutdownFAIL()
618618 else {
619619 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
620620 let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
621621 let weightedPrice = asInt(neutrinoMetrics[nMetricWeightedPrice])
622622 let out = convertBasketItemToNeutrino(pmtAmount, inAsset, basketInfo, weightedPrice)
623623 if (if ((swapType == "outNeutrino"))
624624 then (0 >= out[1])
625625 else false)
626626 then throw((((((("Net amount is non-positive, cannot swap. (gross, net, fee) = (" + toString(out[0])) + ", ") + toString(out[1])) + ", ") + toString(out[2])) + ")"))
627627 else {
628628 let leasePart = if (if ((swapType == "outNeutrino"))
629629 then (inAsset == "WAVES")
630630 else false)
631631 then prepareUnleaseAndLease(0)
632632 else nil
633633 $Tuple2(([IntegerEntry(keySwapUserSpentInPeriod(userAddressStr), swapUsdnVolume), IntegerEntry(keyUserLastSwapHeight(userAddressStr), height), IntegerEntry(totalLockedByUserKEY(swapType, userAddressStr, inAsset), (totalLockedByUser + pmtAmount)), IntegerEntry(getBalanceUnlockBlockKey(userAddressStr), selfUnlockHeight), IntegerEntry(totalLockedKEY(swapType, inAsset), (totalLocked + pmtAmount)), StringEntry(swapKEY(userAddressStr, txId58), pendingSwapDATA(swapType, pmtAmount, selfUnlockHeight, inAsset))] ++ leasePart), unit)
634634 }
635635 }
636636 }
637637
638638
639639 let bFuncIdxSurf = 0
640640
641641 let bFuncIdxWaves = 1
642642
643643 let bFuncIdxUsdn = 2
644644
645645 let bFuncIdxReserveStart = 3
646646
647647 let bFuncIdxSupplyStart = 4
648648
649649 let bFuncIdxBRStart = 5
650650
651651 let bFuncIdxReserveEnd = 6
652652
653653 let bFuncIdxSupplyEnd = 7
654654
655655 let bFuncIdxBREnd = 8
656656
657657 let bFuncIdxRest = 9
658658
659659 let bFuncIdxWavesPrice = 10
660660
661661 func calcWithdrawT2U (inAmount,inAsset,basketInfo,weightedPrice) = {
662662 let outAmt = convertBasketItemToNeutrino(inAmount, inAsset, basketInfo, weightedPrice)
663663 $Tuple12(outAmt[0], neutrinoAssetId, 0, inAsset, 0, weightedPrice, inAmount, 0, 0, 0, nil, [outAmt[1], outAmt[2]])
664664 }
665665
666666
667667 func calcWithdrawU2Basket (usdnIn,basketInfo,br,reservesInUsdn,neutrinoSupply) = {
668668 let brProtected = valueOrElse(getInteger(this, brProtectedKEY()), BRPROTECTED)
669669 let maxAllowedUsdnBeforeMinBr = if ((brProtected >= br))
670670 then 0
671671 else fraction((reservesInUsdn - fraction(brProtected, neutrinoSupply, MULT6)), MULT6, (MULT6 - brProtected))
672672 let allowedUsdnBeforeMinBr = if ((usdnIn > maxAllowedUsdnBeforeMinBr))
673673 then maxAllowedUsdnBeforeMinBr
674674 else usdnIn
675675 let allowedUsdnAfterMinBr = if ((usdnIn > maxAllowedUsdnBeforeMinBr))
676676 then fraction((usdnIn - maxAllowedUsdnBeforeMinBr), br, MULT6)
677677 else 0
678678 let allowedUsdn = (allowedUsdnBeforeMinBr + allowedUsdnAfterMinBr)
679679 let usdn2SURF = (usdnIn - allowedUsdn)
680- let outAmtGross = convertNeutrinoToBasket(allowedUsdn, basketInfo, neutrinoSupply)
681- $Tuple12(outAmtGross._2, unit, usdn2SURF, neutrinoAssetId, outAmtGross._2, outAmtGross._3, allowedUsdn, maxAllowedUsdnBeforeMinBr, allowedUsdnBeforeMinBr, allowedUsdnAfterMinBr, outAmtGross._1, nil)
680+ if ((1 == 1))
681+ then throw(((((((((("usdnIn=" + toString(usdnIn)) + "mA") + toString(maxAllowedUsdnBeforeMinBr)) + " aBef=") + toString(allowedUsdnBeforeMinBr)) + " aAft=") + toString(allowedUsdnAfterMinBr)) + " allowedUsdn=") + toString(allowedUsdn)))
682+ else {
683+ let outAmtGross = convertNeutrinoToBasket(allowedUsdn, basketInfo, neutrinoSupply)
684+ $Tuple12(outAmtGross._2, unit, usdn2SURF, neutrinoAssetId, outAmtGross._2, outAmtGross._3, allowedUsdn, maxAllowedUsdnBeforeMinBr, allowedUsdnBeforeMinBr, allowedUsdnAfterMinBr, outAmtGross._1, nil)
685+ }
682686 }
683687
684688
685689 func calcWithdraw (swapType,inAmount,price,neutrinoMetrics,inAsset) = {
686690 let brProtected = valueOrElse(getInteger(this, brProtectedKEY()), BRPROTECTED)
687691 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
688692 let reservesInUsd = asInt(neutrinoMetrics[nMetricTotalReservesUsd])
689693 let neutrinoSupply = asInt(neutrinoMetrics[nMetricIdxUsdnSupply])
690694 let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
691695 let weightedPrice = asInt(neutrinoMetrics[nMetricWeightedPrice])
692696 let outDataTuple = if ((swapType == "outNeutrino"))
693697 then calcWithdrawT2U(inAmount, inAsset, basketInfo, weightedPrice)
694698 else if ((swapType == "outMulti"))
695699 then calcWithdrawU2Basket(inAmount, basketInfo, BR, reservesInUsd, neutrinoSupply)
696700 else throw(("Unsupported swap type " + swapType))
697701 let outAmtGross = outDataTuple._1
698702 let outAssetId = outDataTuple._2
699703 let inAmtToSurfPart = outDataTuple._3
700704 let inAssetId = outDataTuple._4
701705 let unleaseAmt = outDataTuple._5
702706 let withdrawPrice = outDataTuple._6
703707 let basketData = outDataTuple._11
704708 let netFeeData = outDataTuple._12
705709 let outNetAmt = if ((swapType == "outNeutrino"))
706710 then netFeeData[0]
707711 else 0
708712 let outFeeAmt = if ((swapType == "outNeutrino"))
709713 then netFeeData[1]
710714 else 0
711715 let outSurfAmt = if ((0 >= inAmtToSurfPart))
712716 then 0
713717 else asInt(asAnyList(invoke(mathContract, "surfFunctionREADONLY", [inAmtToSurfPart, inAssetId], nil))[bFuncIdxSurf])
714718 let withdrawBasket = if ((swapType == "outMulti"))
715719 then applyFeesBasket(basketData)
716720 else ""
717721 $Tuple9(outNetAmt, outAssetId, outSurfAmt, inAmtToSurfPart, unleaseAmt, outFeeAmt, outAmtGross, withdrawPrice, withdrawBasket)
718722 }
719723
720724
721725 func keyApplyInProgress () = "%s__applyInProgress"
722726
723727
724728 func keyProposalDataById (proposalId) = ("%s%d__proposalData__" + toString(proposalId))
725729
726730
727731 let govIdxTxIds = 9
728732
729733 func validateUpdate (tx) = match tx {
730734 case o: Order =>
731735 throw("Orders aren't allowed")
732736 case t: DataTransaction|SponsorFeeTransaction|SetScriptTransaction|CreateAliasTransaction|LeaseCancelTransaction|LeaseTransaction|IssueTransaction|InvokeExpressionTransaction|UpdateAssetInfoTransaction|InvokeScriptTransaction|SetAssetScriptTransaction|TransferTransaction|ExchangeTransaction|MassTransferTransaction|BurnTransaction|ReissueTransaction =>
733737 let txId = toBase58String(t.id)
734738 let proposalId = valueOrErrorMessage(getInteger(govContract, keyApplyInProgress()), "Apply is not happening")
735739 let txList = split(split(getStringOrFail(govContract, keyProposalDataById(proposalId)), SEP)[govIdxTxIds], LISTSEP)
736740 if (!(isDefined(indexOf(txList, txId))))
737741 then throw(((("Unknown txId: " + txId) + " for proposalId=") + toString(proposalId)))
738742 else true
739743 case _ =>
740744 throw("Match error")
741745 }
742746
743747
744748 @Callable(i)
745749 func constructorV1 (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,nodeOracleProviderPubKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
746750 let checkCaller = thisOnly(i)
747751 if ((checkCaller == checkCaller))
748752 then if ((size(i.payments) != 0))
749753 then throw("no payments allowed")
750754 else [StringEntry(NeutrinoAssetIdKey, neutrinoAssetIdPrm), StringEntry(BondAssetIdKey, bondAssetIdPrm), StringEntry(AuctionContractKey, auctionContractPrm), StringEntry(LiquidationContractKey, liquidationContractPrm), StringEntry(RPDContractKey, rpdContractPrm), StringEntry(NodeOracleProviderPubKeyKey, nodeOracleProviderPubKeyPrm), IntegerEntry(BalanceWavesLockIntervalKey, balanceWavesLockIntervalPrm), IntegerEntry(BalanceNeutrinoLockIntervalKey, balanceNeutrinoLockIntervalPrm), IntegerEntry(MinTokenSwapAmountKey("WAVES"), minWavesSwapAmountPrm), IntegerEntry(MinNeutrinoSwapAmountKey, minNeutrinoSwapAmountPrm), IntegerEntry(NeutrinoOutFeePartKey, neutrinoOutFeePartPrm), IntegerEntry(WavesOutFeePartKey, wavesOutFeePartPrm)]
751755 else throw("Strict value is not equal to itself.")
752756 }
753757
754758
755759
756760 @Callable(i)
757761 func constructorV2 (mathContract,nsbtStakingContract,swapsTimeframeBlocks) = {
758762 let checkCaller = thisOnly(i)
759763 if ((checkCaller == checkCaller))
760764 then if ((size(i.payments) != 0))
761765 then throw("no payments allowed")
762766 else [StringEntry(MathContractKey, mathContract), StringEntry(NsbtStakingContractKey, nsbtStakingContract), IntegerEntry(swapsTimeframeKEY(), swapsTimeframeBlocks)]
763767 else throw("Strict value is not equal to itself.")
764768 }
765769
766770
767771
768772 @Callable(i)
769773 func constructorV3 (assetsWeightsMins,dParam,kParam,bParam,deltaParam) = {
770774 let checkCaller = thisOnly(i)
771775 if ((checkCaller == checkCaller))
772776 then if ((size(i.payments) != 0))
773777 then throw("no payments allowed")
774778 else {
775779 func prepare (acc,item) = {
776780 let parts = split(item, "_")
777781 let assetId = parts[0]
778782 let weight = parseIntValue(parts[1])
779783 let minVal = parseIntValue(parts[2])
780784 $Tuple2((acc._1 :+ assetId), ((acc._2 :+ IntegerEntry(basketWeightByAssetKey(assetId), weight)) :+ IntegerEntry(MinTokenSwapAmountKey(assetId), minVal)))
781785 }
782786
783787 let r = {
784788 let $l = assetsWeightsMins
785789 let $s = size($l)
786790 let $acc0 = $Tuple2(nil, nil)
787791 func $f0_1 ($a,$i) = if (($i >= $s))
788792 then $a
789793 else prepare($a, $l[$i])
790794
791795 func $f0_2 ($a,$i) = if (($i >= $s))
792796 then $a
793797 else throw("List size exceeds 10")
794798
795799 $f0_2($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)
796800 }
797801 (((((r._2 :+ IntegerEntry(basketDKey(), dParam)) :+ IntegerEntry(basketKKey(), kParam)) :+ IntegerEntry(basketBKey(), bParam)) :+ IntegerEntry(basketLogbDeltaKey(), log(deltaParam, 6, bParam, 6, 6, HALFUP))) :+ StringEntry(basketAssetsKey(), makeString(r._1, SEP)))
798802 }
799803 else throw("Strict value is not equal to itself.")
800804 }
801805
802806
803807
804808 @Callable(i)
805809 func swapTokenToNeutrino () = if ((size(i.payments) != 1))
806810 then throw("swapTokenToNeutrino require only one payment")
807811 else {
808812 let pmt = value(i.payments[0])
809813 let basketAssets = valueOrElse(getString(basketAssetsKey()), "WAVES")
810814 let pmtAssetIdStr = toBase58String(valueOrElse(pmt.assetId, WAVESID))
811815 if (!(contains(basketAssets, pmtAssetIdStr)))
812816 then throw(((pmtAssetIdStr + " is not one of basket tokens:") + basketAssets))
813817 else {
814818 let userAddress = toString(i.caller)
815819 let txId58 = toBase58String(i.transactionId)
816820 commonSwap("outNeutrino", pmt.amount, pmtAssetIdStr, userAddress, txId58)
817821 }
818822 }
819823
820824
821825
822826 @Callable(i)
823827 func swapNeutrinoToBasket () = if ((size(i.payments) != 1))
824828 then throw("swapNeutrinoToBasket require only one payment")
825829 else {
826830 let pmt = value(i.payments[0])
827831 if ((pmt.assetId != neutrinoAssetId))
828832 then throw("Only appropriate Neutrino tokens are allowed for swapping.")
829833 else {
830834 let userAddress = toString(i.caller)
831835 let txId58 = toBase58String(i.transactionId)
832836 commonSwap("outMulti", pmt.amount, toBase58String(neutrinoAssetId), userAddress, txId58)
833837 }
834838 }
835839
836840
837841
838842 @Callable(i)
839843 func withdraw (account,index,swapTxId) = {
840844 let txId = toBase58String(i.transactionId)
841845 if ((size(i.payments) != 0))
842846 then throw("no payments allowed")
843847 else {
844848 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
845849 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
846850 let userAddress = addressFromStringValue(account)
847851 let dataArray = swapDataFailOrREAD(account, swapTxId)
848852 let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
849853 let swapType = dataArray[sIdxSwapType]
850854 let inAmount = parseIntValue(dataArray[sIdxInAmount])
851855 let swapStatus = dataArray[sIdxStatus]
852856 let startHeight = parseIntValue(dataArray[sIdxStartHeight])
853857 let inAsset = dataArray[sIdxInAsset]
854858 let totalLocked = totalLockedREAD(swapType, inAsset)
855859 let totalLockedByUser = totalLockedByUserREAD(swapType, account, inAsset)
856860 let unlockHeight = selfUnlockHeight
857861 let indexHeight = getHeightPriceByIndex(index)
858862 let prevIndexHeight = getHeightPriceByIndex((index - 1))
859863 let priceByIndex = getPriceHistory(indexHeight)
860864 if (isBlocked)
861865 then emergencyShutdownFAIL()
862866 else if ((swapStatus != "PENDING"))
863867 then throw("swap has been already processed")
864868 else if ((unlockHeight > height))
865869 then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
866870 else if (if (if ((index > priceIndex))
867871 then true
868872 else (unlockHeight > indexHeight))
869873 then true
870874 else if ((prevIndexHeight != 0))
871875 then (prevIndexHeight >= unlockHeight)
872876 else false)
873877 then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
874878 else {
875879 let withdrawTuple = calcWithdraw(swapType, inAmount, priceByIndex, neutrinoMetrics, inAsset)
876880 let outNetAmount = withdrawTuple._1
877881 let outAssetId = withdrawTuple._2
878882 let outSurfAmt = withdrawTuple._3
879883 let unleaseAmt = withdrawTuple._5
880884 let outFeeAmount = withdrawTuple._6
881885 let outAmtGross = withdrawTuple._7
882886 let withdrawPrice = withdrawTuple._8
883887 let withdrawBasket = withdrawTuple._9
884888 if (if ((swapType == "outNeutrino"))
885889 then (0 >= outAmtGross)
886890 else false)
887891 then throw("balance equals zero")
888892 else {
889893 let surfCondition = if ((outSurfAmt > 0))
890894 then {
891895 let issueResult = invoke(auctionContract, "issueSurf", [outSurfAmt, account], nil)
892896 if ((issueResult == issueResult))
893897 then 0
894898 else throw("Strict value is not equal to itself.")
895899 }
896900 else 0
897901 if ((surfCondition == surfCondition))
898902 then {
899903 let unleaseInvOrEmpty = invoke(this, "internalUnleaseAndLease", [unleaseAmt], nil)
900904 if ((unleaseInvOrEmpty == unleaseInvOrEmpty))
901905 then {
902906 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", ["", 0, 0], nil))
903907 let gnsbtAmtTotal = asInt(gnsbtData[1])
904908 let gnsbtAmtFromSurfTotal = asInt(asAnyList(gnsbtData[3])[3])
905909 let commonActions = [IntegerEntry(totalLockedByUserKEY(swapType, account, inAsset), (totalLockedByUser - inAmount)), IntegerEntry(totalLockedKEY(swapType, inAsset), (totalLocked - inAmount)), StringEntry(swapKEY(account, swapTxId), finishSwapDATA(dataArray, withdrawPrice, outNetAmount, outFeeAmount, unlockHeight, index, txId, outSurfAmt, BR, withdrawBasket, inAsset))]
906910 if ((swapType == "outMulti"))
907911 then {
908912 let basket = split(withdrawBasket, "_")
909913 func looper (acc,item) = {
910914 let it = split(item, LISTSEP)
911915 let tempAssetId = fromBase58String(it[0])
912916 let assetId = if ((tempAssetId == WAVESID))
913917 then unit
914918 else tempAssetId
915919 let netAmount = parseIntValue(it[2])
916920 let feeAmount = parseIntValue(it[3])
917921 let surfAmt1 = if ((gnsbtAmtTotal != 0))
918922 then fraction(feeAmount, gnsbtAmtFromSurfTotal, gnsbtAmtTotal)
919923 else 0
920924 let surfAmt2 = if ((gnsbtAmtTotal != 0))
921925 then fraction(feeAmount, (MULT6 - BR), MULT6)
922926 else 0
923927 let surfAmt = max([surfAmt1, surfAmt2])
924928 let nsbtAmt = (feeAmount - surfAmt)
925929 $Tuple5((acc._1 :+ ScriptTransfer(userAddress, netAmount, assetId)), (acc._2 :+ AttachedPayment(assetId, surfAmt)), (acc._3 :+ AttachedPayment(assetId, nsbtAmt)), (acc._4 + surfAmt), (acc._5 + nsbtAmt))
926930 }
927931
928932 let r = {
929933 let $l = basket
930934 let $s = size($l)
931935 let $acc0 = $Tuple5(nil, nil, nil, 0, 0)
932936 func $f0_1 ($a,$i) = if (($i >= $s))
933937 then $a
934938 else looper($a, $l[$i])
935939
936940 func $f0_2 ($a,$i) = if (($i >= $s))
937941 then $a
938942 else throw("List size exceeds 10")
939943
940944 $f0_2($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)
941945 }
942946 let surfDeposit = if ((r._4 > 0))
943947 then {
944948 let surfInv = invoke(surfStakingContract, "deposit", nil, r._2)
945949 if ((surfInv == surfInv))
946950 then 0
947951 else throw("Strict value is not equal to itself.")
948952 }
949953 else 0
950954 if ((surfDeposit == surfDeposit))
951955 then {
952956 let nsbtDeposit = if ((r._5 > 0))
953957 then {
954958 let nsbtInv = invoke(nsbtStakingContract, "deposit", nil, r._3)
955959 if ((nsbtInv == nsbtInv))
956960 then 0
957961 else throw("Strict value is not equal to itself.")
958962 }
959963 else 0
960964 if ((nsbtDeposit == nsbtDeposit))
961965 then (commonActions ++ r._1)
962966 else throw("Strict value is not equal to itself.")
963967 }
964968 else throw("Strict value is not equal to itself.")
965969 }
966970 else {
967971 let fee = AttachedPayment(outAssetId, outFeeAmount)
968972 let surfFeeAmt1 = if ((gnsbtAmtTotal != 0))
969973 then fraction(fee.amount, gnsbtAmtFromSurfTotal, gnsbtAmtTotal)
970974 else 0
971975 let surfFeeAmt2 = if ((gnsbtAmtTotal != 0))
972976 then fraction(fee.amount, (MULT6 - BR), MULT6)
973977 else 0
974978 let surfFeeAmt = max([surfFeeAmt1, surfFeeAmt2])
975979 let nsbtFeeAmt = (fee.amount - surfFeeAmt)
976980 let surfDeposit = if ((surfFeeAmt > 0))
977981 then {
978982 let surfInv = invoke(surfStakingContract, "deposit", nil, [AttachedPayment(fee.assetId, surfFeeAmt)])
979983 if ((surfInv == surfInv))
980984 then nil
981985 else throw("Strict value is not equal to itself.")
982986 }
983987 else nil
984988 if ((surfDeposit == surfDeposit))
985989 then {
986990 let nsbtDeposit = if ((nsbtFeeAmt > 0))
987991 then {
988992 let nsbtInv = invoke(nsbtStakingContract, "deposit", nil, [AttachedPayment(fee.assetId, nsbtFeeAmt)])
989993 if ((nsbtInv == nsbtInv))
990994 then nil
991995 else throw("Strict value is not equal to itself.")
992996 }
993997 else nil
994998 if ((nsbtDeposit == nsbtDeposit))
995999 then (commonActions :+ ScriptTransfer(userAddress, outNetAmount, outAssetId))
9961000 else throw("Strict value is not equal to itself.")
9971001 }
9981002 else throw("Strict value is not equal to itself.")
9991003 }
10001004 }
10011005 else throw("Strict value is not equal to itself.")
10021006 }
10031007 else throw("Strict value is not equal to itself.")
10041008 }
10051009 }
10061010 }
10071011 }
10081012
10091013
10101014
10111015 @Callable(i)
10121016 func internalUnleaseAndLease (unleaseAmount) = if ((i.caller != this))
10131017 then throw("internalUnleaseAndLease is not public method")
10141018 else prepareUnleaseAndLease(unleaseAmount)
10151019
10161020
10171021
10181022 @Callable(i)
10191023 func transferUsdnToUser (amount,addr) = if ((i.caller != auctionContract))
10201024 then throw("Only auction contract is authorized")
10211025 else [ScriptTransfer(addressFromStringValue(addr), amount, neutrinoAssetId)]
10221026
10231027
10241028
10251029 @Callable(i)
10261030 func acceptWaves () = if (if ((i.caller != auctionContract))
10271031 then (i.caller != govContract)
10281032 else false)
10291033 then throw("Currently only auction and governance contracts are allowed to call")
10301034 else $Tuple2(prepareUnleaseAndLease(0), "success")
10311035
10321036
10331037
10341038 @Callable(i)
10351039 func approveLeasings (nListS,groupNum,lAmt) = {
10361040 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
10371041 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
10381042 let mngPub = fromBase58String(mngPubS)
10391043 let nodeRegAddrStr = valueOrElse(getString("%s%s__cfg__nodesRegistryAddress"), "3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE")
10401044 let nodeRegAddr = addressFromStringValue(nodeRegAddrStr)
10411045 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
10421046 let lGrNodeOpt = getString(this, lGroupNodeListKEY)
10431047 if (isDefined(lGrNodeOpt))
10441048 then throw((("group " + toString(groupNum)) + " already initialized"))
10451049 else {
10461050 let nList = split(nListS, SEP)
10471051 let expCount = size(nIdxs)
10481052 if ((i.callerPublicKey != mngPub))
10491053 then throw("approveLeasings not authorized")
10501054 else {
1051- let $t04412644188 = readNodeInfo(0)
1052- let nAddr0 = $t04412644188._1
1053- let lAmtKEY0 = $t04412644188._2
1054- let lAmt0 = $t04412644188._3
1055- let lIdKEY0 = $t04412644188._4
1056- let lId0 = $t04412644188._5
1055+ let $t04427444336 = readNodeInfo(0)
1056+ let nAddr0 = $t04427444336._1
1057+ let lAmtKEY0 = $t04427444336._2
1058+ let lAmt0 = $t04427444336._3
1059+ let lIdKEY0 = $t04427444336._4
1060+ let lId0 = $t04427444336._5
10571061 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
10581062 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
10591063 if ((validation == validation))
10601064 then {
10611065 func forEachNodeValidateAndGenerateLease (a,i) = {
10621066 let node = nList[i]
10631067 let la = Lease(addressFromStringValue(node), lAmt)
10641068 (a ++ [la, BinaryEntry(getLeaseIdByAddressKey(node), lcalc(la)), IntegerEntry(getLeaseAmountByAddressKey(node), lAmt)])
10651069 }
10661070
10671071 ([StringEntry(lGroupNodeListKEY, nListS), BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0] ++ {
10681072 let $l = nIdxs
10691073 let $s = size($l)
10701074 let $acc0 = nil
10711075 func $f0_1 ($a,$i) = if (($i >= $s))
10721076 then $a
10731077 else forEachNodeValidateAndGenerateLease($a, $l[$i])
10741078
10751079 func $f0_2 ($a,$i) = if (($i >= $s))
10761080 then $a
10771081 else throw("List size exceeds 8")
10781082
10791083 $f0_2($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)
10801084 })
10811085 }
10821086 else throw("Strict value is not equal to itself.")
10831087 }
10841088 }
10851089 }
10861090
10871091
10881092
10891093 @Callable(i)
10901094 func rebalanceLeasings (amount,groupNum) = {
10911095 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
10921096 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
10931097 let mngPub = fromBase58String(mngPubS)
10941098 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
10951099 let nListS = getStringOrFail(this, lGroupNodeListKEY)
10961100 let nList = split(nListS, SEP)
10971101 if ((i.callerPublicKey != mngPub))
10981102 then throw("rebalanceLeasings not authorized")
10991103 else {
11001104 let unleaseAmt = ((amount / size(nList)) + 1)
1101- let $t04542845490 = readNodeInfo(0)
1102- let nAddr0 = $t04542845490._1
1103- let lAmtKEY0 = $t04542845490._2
1104- let lAmt0 = $t04542845490._3
1105- let lIdKEY0 = $t04542845490._4
1106- let lId0 = $t04542845490._5
1105+ let $t04557645638 = readNodeInfo(0)
1106+ let nAddr0 = $t04557645638._1
1107+ let lAmtKEY0 = $t04557645638._2
1108+ let lAmt0 = $t04557645638._3
1109+ let lIdKEY0 = $t04557645638._4
1110+ let lId0 = $t04557645638._5
11071111 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
11081112 func forEachNodeDoUnlease (a,i) = {
11091113 let node = nList[i]
11101114 let lIdKEY = getLeaseIdByAddressKey(node)
11111115 let lId = getBinaryValue(this, lIdKEY)
11121116 let lAmtKEY = getLeaseAmountByAddressKey(node)
11131117 let lAmt = getIntegerValue(this, lAmtKEY)
11141118 let ula = LeaseCancel(value(lId))
11151119 let la = Lease(addressFromStringValue(node), (lAmt - unleaseAmt))
11161120 (a ++ [LeaseCancel(value(lId)), la, BinaryEntry(lIdKEY, lcalc(la)), IntegerEntry(lAmtKEY, la.amount)])
11171121 }
11181122
11191123 ({
11201124 let $l = nIdxs
11211125 let $s = size($l)
11221126 let $acc0 = nil
11231127 func $f0_1 ($a,$i) = if (($i >= $s))
11241128 then $a
11251129 else forEachNodeDoUnlease($a, $l[$i])
11261130
11271131 func $f0_2 ($a,$i) = if (($i >= $s))
11281132 then $a
11291133 else throw("List size exceeds 8")
11301134
11311135 $f0_2($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)
11321136 } ++ [BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0])
11331137 }
11341138 }
11351139
11361140
11371141
11381142 @Callable(i)
11391143 func swapParamsByUserSYSREADONLY (userAddressStr,gnsbtDiff) = {
11401144 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStr, 0, 0], nil))
11411145 let gnsbtAmt = (asInt(gnsbtData[0]) + gnsbtDiff)
11421146 let gnsbtAmtTotal = (asInt(gnsbtData[1]) + gnsbtDiff)
11431147 let swapLimitData = asAnyList(invoke(mathContract, "calcSwapLimitREADONLY", [gnsbtAmt], nil))
11441148 let wavesSwapLimitInUsdnMax = asInt(swapLimitData[0])
11451149 let wavesSwapLimitMax = asInt(swapLimitData[1])
11461150 let usdnSwapLimitMax = asInt(swapLimitData[2])
11471151 let lastSwapHeight = valueOrElse(getInteger(this, keyUserLastSwapHeight(userAddressStr)), 0)
11481152 let swapLimitTimelifeBlocks = swapsTimeframeREAD()
11491153 let passedBlocksAfterLastSwap = (height - lastSwapHeight)
11501154 let isSwapTimelifeNew = (passedBlocksAfterLastSwap >= swapLimitTimelifeBlocks)
11511155 let swapLimitSpentInUsdn = if (isSwapTimelifeNew)
11521156 then 0
11531157 else valueOrElse(getInteger(this, keySwapUserSpentInPeriod(userAddressStr)), 0)
11541158 let blcks2LmtReset = if (isSwapTimelifeNew)
11551159 then 0
11561160 else (swapLimitTimelifeBlocks - passedBlocksAfterLastSwap)
11571161 $Tuple2(nil, $Tuple7(wavesSwapLimitInUsdnMax, swapLimitSpentInUsdn, blcks2LmtReset, gnsbtAmt, gnsbtAmtTotal, wavesSwapLimitMax, usdnSwapLimitMax))
11581162 }
11591163
11601164
11611165
11621166 @Callable(i)
11631167 func calcWithdrawResultSYSREADONLY (swapType,inAmount,price,inAsset) = {
11641168 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
11651169 $Tuple2(nil, calcWithdraw(swapType, inAmount, price, neutrinoMetrics, inAsset))
11661170 }
11671171
11681172
11691173
11701174 @Callable(i)
11711175 func replaceCommunityNode (oldAddrStr,newAddrStr,groupNum,penaltyAmount) = {
11721176 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
11731177 let mngPub = fromBase58String(mngPubS)
11741178 if ((i.callerPublicKey != mngPub))
11751179 then throw("replaceCommunityNode not authorized")
11761180 else {
11771181 let groupKey = getLeaseGroupNodeListKey(groupNum)
11781182 let groupNodeListS = getStringOrFail(this, groupKey)
11791183 if (!(contains(groupNodeListS, oldAddrStr)))
11801184 then throw(((("Group " + toString(groupNum)) + " does not contain address ") + oldAddrStr))
11811185 else {
11821186 let doReplace = invoke(nodeRegistryContract, "replaceApprovedNode", [oldAddrStr, newAddrStr, groupNum, penaltyAmount], nil)
11831187 if ((doReplace == doReplace))
11841188 then {
11851189 let oldLeaseIdKey = getLeaseIdByAddressKey(oldAddrStr)
11861190 let oldLeaseAmtKey = getLeaseAmountByAddressKey(oldAddrStr)
11871191 let leaseAmt = getIntegerValue(oldLeaseAmtKey)
11881192 let newLeaseIdKey = getLeaseIdByAddressKey(newAddrStr)
11891193 let newLeaseAmtKey = getLeaseAmountByAddressKey(newAddrStr)
11901194 let newLease = Lease(addressFromStringValue(newAddrStr), leaseAmt)
11911195 let updatedGroupNodeListS = makeString(split(groupNodeListS, oldAddrStr), newAddrStr)
11921196 $Tuple2([LeaseCancel(getBinaryValue(oldLeaseIdKey)), DeleteEntry(oldLeaseIdKey), DeleteEntry(oldLeaseAmtKey), StringEntry(groupKey, updatedGroupNodeListS), newLease, BinaryEntry(newLeaseIdKey, lcalc(newLease)), IntegerEntry(newLeaseAmtKey, leaseAmt)], unit)
11931197 }
11941198 else throw("Strict value is not equal to itself.")
11951199 }
11961200 }
11971201 }
11981202
11991203
12001204
12011205 @Callable(i)
12021206 func updateReservesAndNeutrinoSupply () = {
12031207 func getNumberByKeyInternal (key) = match getInteger(this, key) {
12041208 case a: Int =>
12051209 a
12061210 case _ =>
12071211 0
12081212 }
12091213
12101214 let nMetrix = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
12111215 let idx = getNumberByKeyInternal("updateReservesAndNeutrinoSupplyIdx")
12121216 let newIdx = (idx + 1)
12131217 [IntegerEntry("updateReservesAndNeutrinoSupplyIdx", newIdx), IntegerEntry("reserve", asInt(nMetrix[3])), IntegerEntry("neutrinoSupply", asInt(nMetrix[5])), IntegerEntry("reservesInUsdn", convertWavesToNeutrino(asInt(nMetrix[3]), asInt(nMetrix[0]))), IntegerEntry("surplus", asInt(nMetrix[6])), IntegerEntry("deficit", -(asInt(nMetrix[6])))]
12141218 }
12151219
12161220
12171221
12181222 @Callable(i)
12191223 func wavesBalancesVsPayment () = {
12201224 let b = wavesBalance(this)
12211225 [IntegerEntry("wavesBalance_available", b.available), IntegerEntry("wavesBalance_regular", b.regular), IntegerEntry("wavesBalance_generating", b.generating), IntegerEntry("wavesBalance_effective", b.effective), IntegerEntry("waves_payment", value(i.payments[0]).amount)]
12221226 }
12231227
12241228
12251229 @Verifier(tx)
12261230 func verify () = {
12271231 let pubKeyAdminsListStr = makeString(["ExtEEK19nmKj9mCpnWyvEEJFYATLMcVEMvohhUHkyHNm", "Ev5py5FfBQX9cZpYKnfQrTB49Byf8QmpZWeDVRim4yV7", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR"], SEP)
12281232 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
12291233 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
12301234 then 1
12311235 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
12321236 then 1
12331237 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
12341238 then 1
12351239 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
12361240 then 2
12371241 else 0))
12381242 if (if (isBlocked)
12391243 then (getStringValue(controlContract, "is_blocked_caller") == toString(govContract))
12401244 else false)
12411245 then validateUpdate(tx)
12421246 else match tx {
12431247 case sponsorTx: SponsorFeeTransaction =>
12441248 if (checkIsValidMinSponsoredFee(sponsorTx))
12451249 then (count >= 3)
12461250 else false
12471251 case _ =>
12481252 (count >= 3)
12491253 }
12501254 }
12511255

github/deemru/w8io/3ef1775 
235.17 ms