tx · 5SCn7iV7KEbqt5TrKx39Kxsox49yM92aEtpL1qhmD3Ag

3N9be2mwrA52WJho6DiesZkk4351GvpnWuj:  -0.04100000 Waves

2023.03.01 18:28 [2471180] smart account 3N9be2mwrA52WJho6DiesZkk4351GvpnWuj > SELF 0.00000000 Waves

{ "type": 13, "id": "5SCn7iV7KEbqt5TrKx39Kxsox49yM92aEtpL1qhmD3Ag", "fee": 4100000, "feeAssetId": null, "timestamp": 1677684551359, "version": 2, "chainId": 84, "sender": "3N9be2mwrA52WJho6DiesZkk4351GvpnWuj", "senderPublicKey": "6mzmbCza9iqbzxMEELcEA4Xc9NeF4CYpbTtz1zMK3C7x", "proofs": [ "5p34bSF1zrqjTUGZRZrqCUUaHRXenaSdZMXH1qw2UwyywjordFiZLVtiigvJpwyLhgxy8owRNcxRyAdqpjumYoGP", "3UEhfV5CVYzDksHU3k9J11JNTaFG1D5uMERDHeLws2k8Z58P4L4w6fyTTb6y1s6aKNpjHnH9wwSQhdXoQtDsiq16", "hFmi5WoPwf6T1QUXghFnF5BE94kMfwgjoKtiqW7a4vaM9WJCBvs8Z9umjfraarxQmmphq3TeDWLtKh6We2jEovA" ], "script": "base64:BgJjCAISDgoMCAgICAgIAQEBAQEBEgUKAwgIARIHCgUYAQEBARIAEgASBAoCCAESBQoDCAEIEgMKAQESBAoCAQgSABIFCgMIAQESBAoCAQESBAoCCAESBgoECAEBCBIGCgQICAEBswEBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUHYWRkcmVzcwkAzAgCAgEuCQDMCAIFA2tleQkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQVsY2FsYwEBbAkAuQgBBQFsAQ5nZXROdW1iZXJCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQ5nZXRTdHJpbmdCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQIAAQxnZXRCb29sQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQNrZXkHARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFB2FkZHJlc3MFA2tleQAAARhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB2FkZHJlc3MFA2tleQIAARZnZXRCb29sQnlBZGRyZXNzQW5kS2V5AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQdhZGRyZXNzBQNrZXkHAQlhc0FueUxpc3QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAFsBQckbWF0Y2gwBQFsCQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBBWFzSW50AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACA0ludAQBaQUHJG1hdGNoMAUBaQkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEHYXNCeXRlcwEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQHdmFsQnl0ZQUHJG1hdGNoMAUHdmFsQnl0ZQkAAgECHGZhaWwgdG8gY2FzdCBpbnRvIEJ5dGVWZWN0b3IBCWFzUGF5bWVudAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAg9BdHRhY2hlZFBheW1lbnQEAXAFByRtYXRjaDAFAXAJAAIBAiFmYWlsIHRvIGNhc3QgaW50byBBdHRhY2hlZFBheW1lbnQBEmFzU3dhcFBhcmFtc1NUUlVDVAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAiMoSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50KQQGc3RydWN0BQckbWF0Y2gwBQZzdHJ1Y3QJAAIBAh1mYWlsIHRvIGNhc3QgaW50byBUdXBsZTUgaW50cwADU0VQAgJfXwAHTElTVFNFUAIBOgAFTVVMVDgAgMLXLwAFTVVMVDYAwIQ9AA5ERUZBVUxUU1dBUEZFRQCgnAEAC0JSUFJPVEVDVEVEAKCNBgAHV0FWRVNJRAEEE6vZMwAPbk1ldHJpY0lkeFByaWNlAAAAG25NZXRyaWNJZHhVc2RuTG9ja2VkQmFsYW5jZQABABxuTWV0cmljSWR4V2F2ZXNMb2NrZWRCYWxhbmNlAAIAEW5NZXRyaWNJZHhSZXNlcnZlAAMAF25NZXRyaWNJZHhSZXNlcnZlSW5Vc2RuAAQAFG5NZXRyaWNJZHhVc2RuU3VwcGx5AAUAEW5NZXRyaWNJZHhTdXJwbHVzAAYAGG5NZXRyaWNJZHhTdXJwbHVzUGVyY2VudAAHAAxuTWV0cmljSWR4QlIACAAUbk1ldHJpY0lkeE5zYnRTdXBwbHkACQAXbk1ldHJpY0lkeE1heE5zYnRTdXBwbHkACgAUbk1ldHJpY0lkeFN1cmZTdXBwbHkACwASbk1ldHJpY1VzZG5Vc2R0UGVnAAwAFm5NZXRyaWNDdXJyZW50UHJpY2VBZGoADQARbk1ldHJpY0Jhc2tldEluZm8ADgAUbk1ldHJpY1dlaWdodGVkUHJpY2UADwAXbk1ldHJpY1RvdGFsUmVzZXJ2ZXNVc2QAEAAZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAABABhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAAgAUSWR4Q29udHJvbENmZ1JwZERhcHAAAwAVSWR4Q29udHJvbENmZ01hdGhEYXBwAAQAHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAABQAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAYAHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAcAHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAACAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAJABxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwAAoAIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAAsAF0lkeENvbnRyb2xDZmdSZXN0VjJEYXBwAAwAG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAANARFrZXlDb250cm9sQWRkcmVzcwACHCVzJXNfX2NvbmZpZ19fY29udHJvbEFkZHJlc3MBDWtleUNvbnRyb2xDZmcAAhElc19fY29udHJvbENvbmZpZwEUcmVhZENvbnRyb2xDZmdPckZhaWwBB2NvbnRyb2wJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFB2NvbnRyb2wJAQ1rZXlDb250cm9sQ2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCCmNvbnRyb2xDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpjb250cm9sQ2ZnBQNpZHgJAKwCAgItQ29udHJvbCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAPY29udHJvbENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJARFrZXlDb250cm9sQWRkcmVzcwACIzNONE5TN2Q0Sm85YTZGMTRMaUZVS0tZVmRVa2tmMmVQNFp4AApjb250cm9sQ2ZnCQEUcmVhZENvbnRyb2xDZmdPckZhaWwBBQ9jb250cm9sQ29udHJhY3QADG1hdGhDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFFUlkeENvbnRyb2xDZmdNYXRoRGFwcAATbnNidFN0YWtpbmdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAAE3N1cmZTdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwABdnbnNidENvbnRyb2xsZXJDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAA9hdWN0aW9uQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAFG5vZGVSZWdpc3RyeUNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUdSWR4Q29udHJvbENmZ05vZGVSZWdpc3RyeURhcHAAC2dvdkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUbSWR4Q29udHJvbENmZ0dvdmVybmFuY2VEYXBwABJOZXV0cmlub0Fzc2V0SWRLZXkCEW5ldXRyaW5vX2Fzc2V0X2lkAA5Cb25kQXNzZXRJZEtleQINYm9uZF9hc3NldF9pZAASQXVjdGlvbkNvbnRyYWN0S2V5AhBhdWN0aW9uX2NvbnRyYWN0ABZOc2J0U3Rha2luZ0NvbnRyYWN0S2V5AhNuc2J0U3Rha2luZ0NvbnRyYWN0ABZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5AhRsaXF1aWRhdGlvbl9jb250cmFjdAAOUlBEQ29udHJhY3RLZXkCDHJwZF9jb250cmFjdAARQ29udG9sQ29udHJhY3RLZXkCEGNvbnRyb2xfY29udHJhY3QAD01hdGhDb250cmFjdEtleQINbWF0aF9jb250cmFjdAAbQmFsYW5jZVdhdmVzTG9ja0ludGVydmFsS2V5AhtiYWxhbmNlX3dhdmVzX2xvY2tfaW50ZXJ2YWwAHkJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbEtleQIeYmFsYW5jZV9uZXV0cmlub19sb2NrX2ludGVydmFsARVNaW5Ub2tlblN3YXBBbW91bnRLZXkBB2Fzc2V0SWQJAKwCAgIcbWluX291dE5ldXRyaW5vX3N3YXBfYW1vdW50XwUHYXNzZXRJZAAYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5AhhtaW5fb3V0TXVsdGlfc3dhcF9hbW91bnQAHkxlZ2FjeU1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQIYbWluX25ldXRyaW5vX3N3YXBfYW1vdW50ABtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkCFG5vZGVfb3JhY2xlX3Byb3ZpZGVyABVOZXV0cmlub091dEZlZVBhcnRLZXkCGG5ldXRyaW5vT3V0X3N3YXBfZmVlUGFydAASV2F2ZXNPdXRGZWVQYXJ0S2V5AhV3YXZlc091dF9zd2FwX2ZlZVBhcnQBD2tleU5vZGVSZWdpc3RyeQEHYWRkcmVzcwkArAICAgQlc19fBQdhZGRyZXNzAAhQcmljZUtleQIFcHJpY2UADVByaWNlSW5kZXhLZXkCC3ByaWNlX2luZGV4AAxJc0Jsb2NrZWRLZXkCCmlzX2Jsb2NrZWQBEmdldFByaWNlSGlzdG9yeUtleQEFYmxvY2sJAKwCAgkArAICBQhQcmljZUtleQIBXwkApAMBBQVibG9jawEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQVpbmRleAkArAICCQCsAgIFDVByaWNlSW5kZXhLZXkCAV8JAKQDAQUFaW5kZXgBFWdldFN0YWtpbmdOb2RlQnlJbmRleAEDaWR4CQEOZ2V0U3RyaW5nQnlLZXkBCQC5CQIJAMwIAgIGJXMlZCVzCQDMCAICBWxlYXNlCQDMCAIJAKQDAQUDaWR4CQDMCAICC25vZGVBZGRyZXNzBQNuaWwFA1NFUAEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEDaWR4CQERQGV4dHJOYXRpdmUoMTA2MikBCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQUDaWR4AR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVsZWFzZQkAzAgCAhdzcG9uc29yc2hpcFdhdmVzUmVzZXJ2ZQUDbmlsBQNTRVAJAGgCAOgHBQVNVUxUOAEYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AQVvd25lcgkArAICAhViYWxhbmNlX3VubG9ja19ibG9ja18FBW93bmVyAQ1nZXRMZWFzZUlkS2V5AQlub2RlSW5kZXgJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIFbGVhc2UJAMwIAgkApAMBBQlub2RlSW5kZXgJAMwIAgICaWQFA25pbAUDU0VQARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQtub2RlQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAg5sZWFzZUJ5QWRkcmVzcwkAzAgCBQtub2RlQWRkcmVzcwkAzAgCAgJpZAUDbmlsBQNTRVABEWdldExlYXNlQW1vdW50S2V5AQlub2RlSW5kZXgJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIFbGVhc2UJAMwIAgkApAMBBQlub2RlSW5kZXgJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBC25vZGVBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICDmxlYXNlQnlBZGRyZXNzCQDMCAIFC25vZGVBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQNTRVABGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEIZ3JvdXBOdW0JALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIKbGVhc2VHcm91cAkAzAgCCQCkAwEFCGdyb3VwTnVtCQDMCAICCG5vZGVMaXN0BQNuaWwFA1NFUAEQbWluU3dhcEFtb3VudEtFWQEIc3dhcFR5cGUJAKwCAgkArAICAgRtaW5fBQhzd2FwVHlwZQIMX3N3YXBfYW1vdW50AQ50b3RhbExvY2tlZEtFWQIIc3dhcFR5cGUHYXNzZXRJZAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtiYWxhbmNlTG9jawkAzAgCBQhzd2FwVHlwZQkAzAgCBQdhc3NldElkBQNuaWwFA1NFUAEUdG90YWxMb2NrZWRCeVVzZXJLRVkDCHN3YXBUeXBlBW93bmVyB2Fzc2V0SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCAgtiYWxhbmNlTG9jawkAzAgCBQhzd2FwVHlwZQkAzAgCBQVvd25lcgkAzAgCBQdhc3NldElkBQNuaWwCAV8BFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBCHN3YXBUeXBlAwkAAAIFCHN3YXBUeXBlAghvdXRNdWx0aQUeQmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsS2V5BRtCYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxLZXkBGm5vZGVCYWxhbmNlTG9ja0ludGVydmFsS0VZAAIaYmFsYW5jZV9ub2RlX2xvY2tfaW50ZXJ2YWwBEXN3YXBzVGltZWZyYW1lS0VZAAIPc3dhcHNfdGltZWZyYW1lAQ5iclByb3RlY3RlZEtFWQACF21pbl9CUl9wcm90ZWN0aW9uX2xldmVsAQ9iYXNrZXRBc3NldHNLZXkAAholcyVzX19jb21tb25fX2Jhc2tldEFzc2V0cwEKYmFza2V0REtleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0RAEKYmFza2V0S0tleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0SwEKYmFza2V0QktleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0QgESYmFza2V0TG9nYkRlbHRhS2V5AAIdJXMlc19fY29tbW9uX19iYXNrZXRMb2diRGVsdGEBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBB2Fzc2V0SWQJAKwCAgIfJXMlcyVzX19jb21tb25fX3dlaWdodEJ5QXNzZXRfXwUHYXNzZXRJZAEPa2V5UHJpY2VCeUFzc2V0AQdhc3NldElkCQCsAgICHiVzJXMlc19fY29tbW9uX19wcmljZUJ5QXNzZXRfXwUHYXNzZXRJZAERbWluU3dhcEFtb3VudFJFQUQCCHN3YXBUeXBlB2Fzc2V0SWQDCQAAAgUIc3dhcFR5cGUCCG91dE11bHRpCQELdmFsdWVPckVsc2UCCQCfCAEFGE1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQkBDmdldE51bWJlckJ5S2V5AQUeTGVnYWN5TWluTmV1dHJpbm9Td2FwQW1vdW50S2V5CQEOZ2V0TnVtYmVyQnlLZXkBCQEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQUHYXNzZXRJZAESc3dhcHNUaW1lZnJhbWVSRUFEAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQERc3dhcHNUaW1lZnJhbWVLRVkAAKALAQ90b3RhbExvY2tlZFJFQUQCCHN3YXBUeXBlB2Fzc2V0SWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvdGFsTG9ja2VkS0VZAgUIc3dhcFR5cGUFB2Fzc2V0SWQAAAEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAwhzd2FwVHlwZQVvd25lcgdhc3NldElkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARR0b3RhbExvY2tlZEJ5VXNlcktFWQMFCHN3YXBUeXBlBQVvd25lcgUHYXNzZXRJZAAAARdiYWxhbmNlTG9ja0ludGVydmFsUkVBRAEIc3dhcFR5cGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBBQhzd2FwVHlwZQCgCwEbbm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEabm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkAAAEBGGtleVN3YXBVc2VyU3BlbnRJblBlcmlvZAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAICFXN3YXBVc2VyU3BlbnRJblBlcmlvZAkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQNTRVABFWtleVVzZXJMYXN0U3dhcEhlaWdodAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAICEnVzZXJMYXN0U3dhcEhlaWdodAkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQNTRVABFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMCBmFtb3VudAVwcmljZQkAawMFBmFtb3VudAUFTVVMVDgFBXByaWNlARFjb252ZXJ0VG9rZW5Ub1VzZAIGYW1vdW50BXByaWNlCQBrAwUGYW1vdW50BQVwcmljZQUFTVVMVDgBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBmFtb3VudAVwcmljZQkAawMFBmFtb3VudAUFcHJpY2UFBU1VTFQ4ARJjb252ZXJ0V2F2ZXNUb0JvbmQCBmFtb3VudAVwcmljZQkBEWNvbnZlcnRUb2tlblRvVXNkAgUGYW1vdW50BQVwcmljZQEWY29udmVydEpzb25BcnJheVRvTGlzdAEJanNvbkFycmF5CQC1CQIFCWpzb25BcnJheQIBLAEbY29udmVydEJhc2tldEl0ZW1Ub05ldXRyaW5vBAhpbkFtb3VudAdpbkFzc2V0DWJhc2tldEluZm9TdHINbmV1dHJpbm9QcmljZQQKYmFza2V0SW5mbwkAvAkCBQ1iYXNrZXRJbmZvU3RyAgFfCgEIZmluZEl0ZW0CA2FjYwRpdGVtBAViSXRlbQkAtQkCBQRpdGVtBQdMSVNUU0VQAwkAAAIJAJEDAgUFYkl0ZW0AAAUHaW5Bc3NldAUFYkl0ZW0FA2FjYwQCaXQKAAIkbAUKYmFza2V0SW5mbwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmluZEl0ZW0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEBWRsb2c2CQEFdmFsdWUBCQCfCAEJARJiYXNrZXRMb2diRGVsdGFLZXkABAJkNgkBBXZhbHVlAQkAnwgBCQEKYmFza2V0REtleQAEAmI2CQEFdmFsdWUBCQCfCAEJAQpiYXNrZXRCS2V5AAQCdzYJAQV2YWx1ZQEJAJ8IAQkBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBBQdpbkFzc2V0BAJwNgkAZAIJAGUCBQVkbG9nNgUCdzYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJpdAABBANwcDYJAGwGBQJiNgAGBQJwNgAGAAYFBkhBTEZVUAQOb3V0QW1vdW50R3Jvc3MJAGsDBQhpbkFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAml0AAIDCQAAAgUNbmV1dHJpbm9QcmljZQAABQVNVUxUOAkAaAIFDW5ldXRyaW5vUHJpY2UAZAQKbXVsdGlwbGllcgkAZQIJAGQCBQVNVUxUNgUCZDYFA3BwNgQJbmV0QW1vdW50CQBrAwUOb3V0QW1vdW50R3Jvc3MFCm11bHRpcGxpZXIFBU1VTFQ2BAlmZWVBbW91bnQDCQBnAgUJbmV0QW1vdW50BQ5vdXRBbW91bnRHcm9zcwAACQBlAgUOb3V0QW1vdW50R3Jvc3MFCW5ldEFtb3VudAkAzAgCBQ5vdXRBbW91bnRHcm9zcwkAzAgCBQluZXRBbW91bnQJAMwIAgUJZmVlQW1vdW50BQNuaWwBF2NvbnZlcnROZXV0cmlub1RvQmFza2V0AwZhbW91bnQNYmFza2V0SW5mb1N0cg5uZXV0cmlub1N1cHBseQQKYmFza2V0SW5mbwkAvAkCBQ1iYXNrZXRJbmZvU3RyAgFfCgEEY29udgIDYWNjBGl0ZW0EBXBhcnRzCQC1CQIFBGl0ZW0FB0xJU1RTRVAEB2Fzc2V0SWQJAJEDAgUFcGFydHMAAAQFc2hhcmUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwYXJ0cwABBAVwcmljZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAIEBnJlc2VydgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAMDCQAAAgUObmV1dHJpbm9TdXBwbHkAAAkAAgECJ0F0dGVtcHQgdG8gYnVybiBuZXV0cmlubyBhdCB6ZXJvIHN1cHBseQQJb3V0QW1vdW50CQBrAwUGYW1vdW50BQZyZXNlcnYFDm5ldXRyaW5vU3VwcGx5BAp3YXZlc1R1cGxlAwkAAAIFB2Fzc2V0SWQCBVdBVkVTCQCUCgIFCW91dEFtb3VudAUFcHJpY2UJAJQKAggFA2FjYwJfMggFA2FjYwJfMwkAlQoDCQDNCAIIBQNhY2MCXzEJAJYKBAUHYXNzZXRJZAUJb3V0QW1vdW50BQVwcmljZQUFc2hhcmUIBQp3YXZlc1R1cGxlAl8xCAUKd2F2ZXNUdXBsZQJfMgoAAiRsBQpiYXNrZXRJbmZvCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlQoDBQNuaWwAAAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQRjb252AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARFtaW5Td2FwQW1vdW50RkFJTAIIc3dhcFR5cGUNbWluU3dhcEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICGFRoZSBzcGVjaWZpZWQgYW1vdW50IGluIAUIc3dhcFR5cGUCKyBzd2FwIGlzIGxlc3MgdGhhbiB0aGUgcmVxdWlyZWQgbWluaW11bSBvZiAJAKQDAQUNbWluU3dhcEFtb3VudAEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAkAAgECWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwEOcHJpY2VJbmRleEZBSUwFBWluZGV4CnByaWNlSW5kZXgLaW5kZXhIZWlnaHQMdW5sb2NrSGVpZ2h0D3ByZXZJbmRleEhlaWdodAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICI2ludmFsaWQgcHJpY2UgaGlzdG9yeSBpbmRleDogaW5kZXg9CQCkAwEFBWluZGV4AgwgcHJpY2VJbmRleD0JAKQDAQUKcHJpY2VJbmRleAINIGluZGV4SGVpZ2h0PQkApAMBBQtpbmRleEhlaWdodAIOIHVubG9ja0hlaWdodD0JAKQDAQUMdW5sb2NrSGVpZ2h0AhEgcHJldkluZGV4SGVpZ2h0PQkApAMBBQ9wcmV2SW5kZXhIZWlnaHQAD25ldXRyaW5vQXNzZXRJZAkA2QQBCQEOZ2V0U3RyaW5nQnlLZXkBBRJOZXV0cmlub0Fzc2V0SWRLZXkACnByaWNlSW5kZXgJARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDVByaWNlSW5kZXhLZXkACWlzQmxvY2tlZAkBFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDElzQmxvY2tlZEtleQAYbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5CQDZBAEJAQ5nZXRTdHJpbmdCeUtleQEFG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQALYm9uZEFzc2V0SWQJANkEAQIsRjNpYXh6cnVGZUt1amZWZllTWkVrZWpwamg2N3dtUmZQQ1JIaU5tV0twM1oAFWRlcHJlY2F0ZWRCb25kQXNzZXRJZAkA2QQBAiw5NzVha1pCZm5NajUxM1U3TVphSEt6UXJtc0V4NWFFM3dkV0tUckhCaGJqRgAQbmV1dHJpbm9Db250cmFjdAUEdGhpcwAMY3VycmVudFByaWNlCQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0BQhQcmljZUtleQEbY2hlY2tJc1ZhbGlkTWluU3BvbnNvcmVkRmVlAQJ0eAQOTUlOVFJBTlNGRVJGRUUAoI0GBBZTcG9uc29yZWRGZWVVcHBlckJvdW5kAOgHBA9yZWFsTmV1dHJpbm9GZWUJARFjb252ZXJ0VG9rZW5Ub1VzZAIFDk1JTlRSQU5TRkVSRkVFBQxjdXJyZW50UHJpY2UEDm1pbk5ldXRyaW5vRmVlCQBoAgUPcmVhbE5ldXRyaW5vRmVlAAIEDm1heE5ldXRyaW5vRmVlCQBrAwUPcmVhbE5ldXRyaW5vRmVlBRZTcG9uc29yZWRGZWVVcHBlckJvdW5kAGQECGlucHV0RmVlCQEFdmFsdWUBCAUCdHgUbWluU3BvbnNvcmVkQXNzZXRGZWUDAwkAZwIFCGlucHV0RmVlBQ5taW5OZXV0cmlub0ZlZQkAZwIFDm1heE5ldXRyaW5vRmVlBQhpbnB1dEZlZQcJAAACCAUCdHgHYXNzZXRJZAUPbmV1dHJpbm9Bc3NldElkBwEPZ2V0UHJpY2VIaXN0b3J5AQVibG9jawkBGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQIFD2NvbnRyb2xDb250cmFjdAkBEmdldFByaWNlSGlzdG9yeUtleQEFBWJsb2NrARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBBWluZGV4CQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0CQEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQUFaW5kZXgBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQNTRVAADHNJZHhTd2FwVHlwZQABAApzSWR4U3RhdHVzAAIADHNJZHhJbkFtb3VudAADAA9zSWR4U3RhcnRIZWlnaHQABwASc0lkeFN0YXJ0VGltZXN0YW1wAAgAFHNJZHhTZWxmVW5sb2NrSGVpZ2h0AAsAC3NJZHhNaW5SYW5kAA8AC3NJZHhNYXhSYW5kABAAC3NJZHhJbkFzc2V0ABQBB3N3YXBLRVkCC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFBHR4SWQFA25pbAUDU0VQAQtzdHJTd2FwREFUQRQIc3dhcFR5cGUGc3RhdHVzCGluQW1vdW50BXByaWNlDG91dE5ldEFtb3VudAxvdXRGZWVBbW91bnQLc3RhcnRIZWlnaHQOc3RhcnRUaW1lc3RhbXAJZW5kSGVpZ2h0DGVuZFRpbWVzdGFtcBBzZWxmVW5sb2NrSGVpZ2h0EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkB3JhbmRNaW4HcmFuZE1heApvdXRTdXJmQW10AmJyCmJhc2tldERhdGEHaW5Bc3NldAkAugkCCQDMCAICKCVzJXMlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJXMlZCVkJWQlZCVzJXMJAMwIAgUIc3dhcFR5cGUJAMwIAgUGc3RhdHVzCQDMCAIFCGluQW1vdW50CQDMCAIFBXByaWNlCQDMCAIFDG91dE5ldEFtb3VudAkAzAgCBQxvdXRGZWVBbW91bnQJAMwIAgULc3RhcnRIZWlnaHQJAMwIAgUOc3RhcnRUaW1lc3RhbXAJAMwIAgUJZW5kSGVpZ2h0CQDMCAIFDGVuZFRpbWVzdGFtcAkAzAgCBRBzZWxmVW5sb2NrSGVpZ2h0CQDMCAIFEHJhbmRVbmxvY2tIZWlnaHQJAMwIAgUFaW5kZXgJAMwIAgUMd2l0aGRyYXdUeElkCQDMCAIFB3JhbmRNaW4JAMwIAgUHcmFuZE1heAkAzAgCBQpvdXRTdXJmQW10CQDMCAIFAmJyCQDMCAIFCmJhc2tldERhdGEJAMwIAgUHaW5Bc3NldAUDbmlsBQNTRVABD3BlbmRpbmdTd2FwREFUQQQIc3dhcFR5cGUNaW5Bc3NldEFtb3VudBBzZWxmVW5sb2NrSGVpZ2h0B2luQXNzZXQJAQtzdHJTd2FwREFUQRQFCHN3YXBUeXBlAgdQRU5ESU5HCQCkAwEFDWluQXNzZXRBbW91bnQCATACATACATAJAKQDAQUGaGVpZ2h0CQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgEwAgEwCQCkAwEFEHNlbGZVbmxvY2tIZWlnaHQCATACATACBE5VTEwCATACATACATACATACAAUHaW5Bc3NldAEOZmluaXNoU3dhcERBVEELCWRhdGFBcnJheQVwcmljZQxvdXROZXRBbW91bnQMb3V0RmVlQW1vdW50EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkCm91dFN1cmZBbXQCYnIKYmFza2V0RGF0YQdpbkFzc2V0CQELc3RyU3dhcERBVEEUCQCRAwIFCWRhdGFBcnJheQUMc0lkeFN3YXBUeXBlAghGSU5JU0hFRAkAkQMCBQlkYXRhQXJyYXkFDHNJZHhJbkFtb3VudAkApAMBBQVwcmljZQkApAMBBQxvdXROZXRBbW91bnQJAKQDAQUMb3V0RmVlQW1vdW50CQCRAwIFCWRhdGFBcnJheQUPc0lkeFN0YXJ0SGVpZ2h0CQCRAwIFCWRhdGFBcnJheQUSc0lkeFN0YXJ0VGltZXN0YW1wCQCkAwEFBmhlaWdodAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAkQMCBQlkYXRhQXJyYXkFFHNJZHhTZWxmVW5sb2NrSGVpZ2h0CQCkAwEFEHJhbmRVbmxvY2tIZWlnaHQJAKQDAQUFaW5kZXgFDHdpdGhkcmF3VHhJZAkAkQMCBQlkYXRhQXJyYXkFC3NJZHhNaW5SYW5kCQCRAwIFCWRhdGFBcnJheQULc0lkeE1heFJhbmQJAKQDAQUKb3V0U3VyZkFtdAkApAMBBQJicgUKYmFza2V0RGF0YQUHaW5Bc3NldAESc3dhcERhdGFGYWlsT3JSRUFEAgt1c2VyQWRkcmVzcwhzd2FwVHhJZAQHc3dhcEtleQkBB3N3YXBLRVkCBQt1c2VyQWRkcmVzcwUIc3dhcFR4SWQJALwJAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEFB3N3YXBLZXkJAKwCAgIRbm8gc3dhcCBkYXRhIGZvciAFB3N3YXBLZXkFA1NFUAEJYXBwbHlGZWVzAw5hbW91bnRPdXRHcm9zcwtpbkFtdFRvU1VSRgdmZWVQYXJ0BAlmZWVBbW91bnQJAGsDBQ5hbW91bnRPdXRHcm9zcwUHZmVlUGFydAUFTVVMVDYJAMwIAgkAZQIFDmFtb3VudE91dEdyb3NzBQlmZWVBbW91bnQJAMwIAgUJZmVlQW1vdW50BQNuaWwBD2FwcGx5RmVlc0Jhc2tldAEJYmFza2V0T3V0BAJrNgkBBXZhbHVlAQkAnwgBCQEKYmFza2V0S0tleQAEAmQ2CQEFdmFsdWUBCQCfCAEJAQpiYXNrZXRES2V5AAQHZmVlUGFydAkAawMFAms2BQJkNgUFTVVMVDYKAQpmZWVBcHBsaWVyAgNhY2MEaXRlbQQJZmVlQW1vdW50CQBrAwgFBGl0ZW0CXzIFB2ZlZVBhcnQFBU1VTFQ2CQDNCAIFA2FjYwkAuQkCCQDMCAIIBQRpdGVtAl8xCQDMCAIJAKQDAQgFBGl0ZW0CXzMJAMwIAgkApAMBCQBlAggFBGl0ZW0CXzIFCWZlZUFtb3VudAkAzAgCCQCkAwEFCWZlZUFtb3VudAkAzAgCCQCkAwEIBQRpdGVtAl80BQNuaWwFB0xJU1RTRVAEAWEKAAIkbAUJYmFza2V0T3V0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpmZWVBcHBsaWVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQC6CQIFAWECAV8BA2FicwEBeAMJAGYCAAAFAXgJAQEtAQUBeAUBeAEKc2VsZWN0Tm9kZQENdW5sZWFzZUFtb3VudAQNYW1vdW50VG9MZWFzZQkAZQIJAGUCCAkA7wcBBRBuZXV0cmlub0NvbnRyYWN0CWF2YWlsYWJsZQUNdW5sZWFzZUFtb3VudAkBH2dldFJlc2VydmVkQW1vdW50Rm9yU3BvbnNvcnNoaXAABApvbGRMZWFzZWQwCQEOZ2V0TnVtYmVyQnlLZXkBCQERZ2V0TGVhc2VBbW91bnRLZXkBAAAECm9sZExlYXNlZDEJAQ5nZXROdW1iZXJCeUtleQEJARFnZXRMZWFzZUFtb3VudEtleQEAAQQKbmV3TGVhc2VkMAkAZAIFDWFtb3VudFRvTGVhc2UFCm9sZExlYXNlZDAECm5ld0xlYXNlZDEJAGQCBQ1hbW91bnRUb0xlYXNlBQpvbGRMZWFzZWQxAwMJAGYCBQpuZXdMZWFzZWQwAAAGCQBmAgUKbmV3TGVhc2VkMQAABAZkZWx0YTAJAQNhYnMBCQBlAgUKbmV3TGVhc2VkMAUKb2xkTGVhc2VkMQQGZGVsdGExCQEDYWJzAQkAZQIFCm5ld0xlYXNlZDEFCm9sZExlYXNlZDADCQBnAgUGZGVsdGExBQZkZWx0YTAJAJQKAgAABQpuZXdMZWFzZWQwCQCUCgIAAQUKbmV3TGVhc2VkMQkAlAoCAP///////////wEAAAEIdGhpc09ubHkBAWkDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAi1QZXJtaXNzaW9uIGRlbmllZDogdGhpcyBjb250cmFjdCBvbmx5IGFsbG93ZWQGARZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAQ11bmxlYXNlQW1vdW50BAlub2RlVHVwbGUJAQpzZWxlY3ROb2RlAQUNdW5sZWFzZUFtb3VudAQJbm9kZUluZGV4CAUJbm9kZVR1cGxlAl8xBA5uZXdMZWFzZUFtb3VudAgFCW5vZGVUdXBsZQJfMgMJAGYCBQ5uZXdMZWFzZUFtb3VudAAABApsZWFzZUlkS2V5CQENZ2V0TGVhc2VJZEtleQEFCW5vZGVJbmRleAQIb2xkTGVhc2UJAJwIAgUEdGhpcwUKbGVhc2VJZEtleQQOdW5sZWFzZU9yRW1wdHkDCQEJaXNEZWZpbmVkAQUIb2xkTGVhc2UJAMwIAgkBC0xlYXNlQ2FuY2VsAQkBBXZhbHVlAQUIb2xkTGVhc2UFA25pbAUDbmlsBA5sZWFzZUFtb3VudEtleQkBEWdldExlYXNlQW1vdW50S2V5AQUJbm9kZUluZGV4BAVsZWFzZQkAxAgCCQEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEFCW5vZGVJbmRleAUObmV3TGVhc2VBbW91bnQJAM4IAgUOdW5sZWFzZU9yRW1wdHkJAMwIAgUFbGVhc2UJAMwIAgkBC0JpbmFyeUVudHJ5AgUKbGVhc2VJZEtleQkBBWxjYWxjAQUFbGVhc2UJAMwIAgkBDEludGVnZXJFbnRyeQIJARFnZXRMZWFzZUFtb3VudEtleQEFCW5vZGVJbmRleAUObmV3TGVhc2VBbW91bnQFA25pbAUDbmlsAQxyZWFkTm9kZUluZm8BB25vZGVJZHgEC25vZGVBZGRyZXNzCQEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEFB25vZGVJZHgEDGxlYXNlZEFtdEtFWQkBEWdldExlYXNlQW1vdW50S2V5AQUHbm9kZUlkeAQJbGVhc2VkQW10CQEOZ2V0TnVtYmVyQnlLZXkBBQxsZWFzZWRBbXRLRVkECmxlYXNlSWRLRVkJAQ1nZXRMZWFzZUlkS2V5AQUHbm9kZUlkeAQHbGVhc2VJZAkBBXZhbHVlAQkAnAgCBQR0aGlzBQpsZWFzZUlkS0VZCQCXCgUFC25vZGVBZGRyZXNzBQxsZWFzZWRBbXRLRVkFCWxlYXNlZEFtdAUKbGVhc2VJZEtFWQUHbGVhc2VJZAEKY29tbW9uU3dhcAUIc3dhcFR5cGUJcG10QW1vdW50B2luQXNzZXQOdXNlckFkZHJlc3NTdHIGdHhJZDU4BBBzd2FwUGFyYW1zU1RSVUNUCQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/AcEBQR0aGlzAhtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgAABQNuaWwFA25pbAQRdG9rZW5Td2FwTGltaXRVc2QIBRBzd2FwUGFyYW1zU1RSVUNUAl8xBA5zd2FwTGltaXRTcGVudAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzIEDmJsY2tzMkxtdFJlc2V0CAUQc3dhcFBhcmFtc1NUUlVDVAJfMwQQdXNkblN3YXBMaW1pdE1heAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzcEDW1pblN3YXBBbW91bnQJARFtaW5Td2FwQW1vdW50UkVBRAIFCHN3YXBUeXBlBQdpbkFzc2V0BBF0b3RhbExvY2tlZEJ5VXNlcgkBFXRvdGFsTG9ja2VkQnlVc2VyUkVBRAMFCHN3YXBUeXBlBQ51c2VyQWRkcmVzc1N0cgUHaW5Bc3NldAQLbm9kZUFkZHJlc3MJARVnZXRTdGFraW5nTm9kZUJ5SW5kZXgBAAAEDGlzU3dhcEJ5Tm9kZQkAAAIFC25vZGVBZGRyZXNzBQ51c2VyQWRkcmVzc1N0cgQWYmFsYW5jZUxvY2tNYXhJbnRlcnZhbAMFDGlzU3dhcEJ5Tm9kZQkBG25vZGVCYWxhbmNlTG9ja0ludGVydmFsUkVBRAAJARdiYWxhbmNlTG9ja0ludGVydmFsUkVBRAEFCHN3YXBUeXBlBBBzZWxmVW5sb2NrSGVpZ2h0CQBkAgUGaGVpZ2h0BRZiYWxhbmNlTG9ja01heEludGVydmFsBAJwcgkBBXZhbHVlAQkAmggCBQ9jb250cm9sQ29udHJhY3QJAQ9rZXlQcmljZUJ5QXNzZXQBBQdpbkFzc2V0BA5zd2FwVXNkblZvbHVtZQMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8JARFjb252ZXJ0VG9rZW5Ub1VzZAIFCXBtdEFtb3VudAUCcHIFCXBtdEFtb3VudAQMc3dhcExpbWl0TWF4AwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwURdG9rZW5Td2FwTGltaXRVc2QFEHVzZG5Td2FwTGltaXRNYXgDCQBmAgUNbWluU3dhcEFtb3VudAUJcG10QW1vdW50CQERbWluU3dhcEFtb3VudEZBSUwCBQhzd2FwVHlwZQUNbWluU3dhcEFtb3VudAMDCQEBIQEFDGlzU3dhcEJ5Tm9kZQkAZgIFDnN3YXBMaW1pdFNwZW50AAAHCQACAQkArAICAjpZb3UgaGF2ZSBleGNlZWRlZCBzd2FwIGxpbWl0ISBOZXh0IGFsbG93ZWQgc3dhcCBoZWlnaHQgaXMgCQCkAwEJAGQCBQZoZWlnaHQFDmJsY2tzMkxtdFJlc2V0AwMJAQEhAQUMaXNTd2FwQnlOb2RlCQBmAgUOc3dhcFVzZG5Wb2x1bWUFDHN3YXBMaW1pdE1heAcJAAIBCQCsAgIJAKwCAgkArAICAi5Zb3UgaGF2ZSBleGNlZWRlZCB5b3VyIHN3YXAgbGltaXQhIFJlcXVlc3RlZDogCQCkAwEFDnN3YXBVc2RuVm9sdW1lAg0sIGF2YWlsYWJsZTogCQCkAwEFDHN3YXBMaW1pdE1heAMFCWlzQmxvY2tlZAkBFWVtZXJnZW5jeVNodXRkb3duRkFJTAAED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwECmJhc2tldEluZm8JAQhhc1N0cmluZwEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBRFuTWV0cmljQmFza2V0SW5mbwQNd2VpZ2h0ZWRQcmljZQkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFFG5NZXRyaWNXZWlnaHRlZFByaWNlBANvdXQJARtjb252ZXJ0QmFza2V0SXRlbVRvTmV1dHJpbm8EBQlwbXRBbW91bnQFB2luQXNzZXQFCmJhc2tldEluZm8FDXdlaWdodGVkUHJpY2UDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAZwIAAAkAkQMCBQNvdXQAAQcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAj5OZXQgYW1vdW50IGlzIG5vbi1wb3NpdGl2ZSwgY2Fubm90IHN3YXAuIChncm9zcywgbmV0LCBmZWUpID0gKAkApAMBCQCRAwIFA291dAAAAgIsIAkApAMBCQCRAwIFA291dAABAgIsIAkApAMBCQCRAwIFA291dAACAgEpBAlsZWFzZVBhcnQDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAAAIFB2luQXNzZXQCBVdBVkVTBwkBFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UBAAAFA25pbAkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARhrZXlTd2FwVXNlclNwZW50SW5QZXJpb2QBBQ51c2VyQWRkcmVzc1N0cgUOc3dhcFVzZG5Wb2x1bWUJAMwIAgkBDEludGVnZXJFbnRyeQIJARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBBQ51c2VyQWRkcmVzc1N0cgUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUdG90YWxMb2NrZWRCeVVzZXJLRVkDBQhzd2FwVHlwZQUOdXNlckFkZHJlc3NTdHIFB2luQXNzZXQJAGQCBRF0b3RhbExvY2tlZEJ5VXNlcgUJcG10QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AQUOdXNlckFkZHJlc3NTdHIFEHNlbGZVbmxvY2tIZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB3N3YXBLRVkCBQ51c2VyQWRkcmVzc1N0cgUGdHhJZDU4CQEPcGVuZGluZ1N3YXBEQVRBBAUIc3dhcFR5cGUFCXBtdEFtb3VudAUQc2VsZlVubG9ja0hlaWdodAUHaW5Bc3NldAUDbmlsBQlsZWFzZVBhcnQFBHVuaXQADGJGdW5jSWR4U3VyZgAAAA1iRnVuY0lkeFdhdmVzAAEADGJGdW5jSWR4VXNkbgACABRiRnVuY0lkeFJlc2VydmVTdGFydAADABNiRnVuY0lkeFN1cHBseVN0YXJ0AAQAD2JGdW5jSWR4QlJTdGFydAAFABJiRnVuY0lkeFJlc2VydmVFbmQABgARYkZ1bmNJZHhTdXBwbHlFbmQABwANYkZ1bmNJZHhCUkVuZAAIAAxiRnVuY0lkeFJlc3QACQASYkZ1bmNJZHhXYXZlc1ByaWNlAAoBD2NhbGNXaXRoZHJhd1QyVQQIaW5BbW91bnQHaW5Bc3NldApiYXNrZXRJbmZvDXdlaWdodGVkUHJpY2UEBm91dEFtdAkBG2NvbnZlcnRCYXNrZXRJdGVtVG9OZXV0cmlubwQFCGluQW1vdW50BQdpbkFzc2V0BQpiYXNrZXRJbmZvBQ13ZWlnaHRlZFByaWNlCQCeCgwJAJEDAgUGb3V0QW10AAAFD25ldXRyaW5vQXNzZXRJZAAABQdpbkFzc2V0AAAFDXdlaWdodGVkUHJpY2UFCGluQW1vdW50AAAAAAAABQNuaWwJAMwIAgkAkQMCBQZvdXRBbXQAAQkAzAgCCQCRAwIFBm91dEFtdAACBQNuaWwBFGNhbGNXaXRoZHJhd1UyQmFza2V0AwZ1c2RuSW4KYmFza2V0SW5mbw5uZXV0cmlub1N1cHBseQQLb3V0QW10R3Jvc3MJARdjb252ZXJ0TmV1dHJpbm9Ub0Jhc2tldAMFBnVzZG5JbgUKYmFza2V0SW5mbwUObmV1dHJpbm9TdXBwbHkJAJ4KDAgFC291dEFtdEdyb3NzAl8yBQR1bml0AAAFD25ldXRyaW5vQXNzZXRJZAgFC291dEFtdEdyb3NzAl8yCAULb3V0QW10R3Jvc3MCXzMFBnVzZG5JbgUObmV1dHJpbm9TdXBwbHkFBnVzZG5JbgAACAULb3V0QW10R3Jvc3MCXzEFA25pbAEMY2FsY1dpdGhkcmF3BQhzd2FwVHlwZQhpbkFtb3VudAVwcmljZQ9uZXV0cmlub01ldHJpY3MHaW5Bc3NldAQObmV1dHJpbm9TdXBwbHkJAQVhc0ludAEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBRRuTWV0cmljSWR4VXNkblN1cHBseQQKYmFza2V0SW5mbwkBCGFzU3RyaW5nAQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFEW5NZXRyaWNCYXNrZXRJbmZvBA13ZWlnaHRlZFByaWNlCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUUbk1ldHJpY1dlaWdodGVkUHJpY2UEDG91dERhdGFUdXBsZQMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8JAQ9jYWxjV2l0aGRyYXdUMlUEBQhpbkFtb3VudAUHaW5Bc3NldAUKYmFza2V0SW5mbwUNd2VpZ2h0ZWRQcmljZQMJAAACBQhzd2FwVHlwZQIIb3V0TXVsdGkJARRjYWxjV2l0aGRyYXdVMkJhc2tldAMFCGluQW1vdW50BQpiYXNrZXRJbmZvBQ5uZXV0cmlub1N1cHBseQkAAgEJAKwCAgIWVW5zdXBwb3J0ZWQgc3dhcCB0eXBlIAUIc3dhcFR5cGUEC291dEFtdEdyb3NzCAUMb3V0RGF0YVR1cGxlAl8xBApvdXRBc3NldElkCAUMb3V0RGF0YVR1cGxlAl8yBA9pbkFtdFRvU3VyZlBhcnQIBQxvdXREYXRhVHVwbGUCXzMECWluQXNzZXRJZAgFDG91dERhdGFUdXBsZQJfNAQKdW5sZWFzZUFtdAgFDG91dERhdGFUdXBsZQJfNQQNd2l0aGRyYXdQcmljZQgFDG91dERhdGFUdXBsZQJfNgQKYmFza2V0RGF0YQgFDG91dERhdGFUdXBsZQNfMTEECm5ldEZlZURhdGEIBQxvdXREYXRhVHVwbGUDXzEyBAlvdXROZXRBbXQDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQCRAwIFCm5ldEZlZURhdGEAAAAABAlvdXRGZWVBbXQDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQCRAwIFCm5ldEZlZURhdGEAAQAABApvdXRTdXJmQW10AwkAZwIAAAUPaW5BbXRUb1N1cmZQYXJ0AAAJAQVhc0ludAEJAJEDAgkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhRzdXJmRnVuY3Rpb25SRUFET05MWQkAzAgCBQ9pbkFtdFRvU3VyZlBhcnQJAMwIAgUJaW5Bc3NldElkBQNuaWwFA25pbAUMYkZ1bmNJZHhTdXJmBA53aXRoZHJhd0Jhc2tldAMJAAACBQhzd2FwVHlwZQIIb3V0TXVsdGkJAQ9hcHBseUZlZXNCYXNrZXQBBQpiYXNrZXREYXRhAgAJAJsKCQUJb3V0TmV0QW10BQpvdXRBc3NldElkBQpvdXRTdXJmQW10BQ9pbkFtdFRvU3VyZlBhcnQFCnVubGVhc2VBbXQFCW91dEZlZUFtdAULb3V0QW10R3Jvc3MFDXdpdGhkcmF3UHJpY2UFDndpdGhkcmF3QmFza2V0ARJrZXlBcHBseUluUHJvZ3Jlc3MAAhMlc19fYXBwbHlJblByb2dyZXNzARNrZXlQcm9wb3NhbERhdGFCeUlkAQpwcm9wb3NhbElkCQCsAgICFCVzJWRfX3Byb3Bvc2FsRGF0YV9fCQCkAwEFCnByb3Bvc2FsSWQAC2dvdklkeFR4SWRzAAkBDnZhbGlkYXRlVXBkYXRlAQJ0eAQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIFT3JkZXIEAW8FByRtYXRjaDAJAAIBAhVPcmRlcnMgYXJlbid0IGFsbG93ZWQDAwkAAQIFByRtYXRjaDACD0RhdGFUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIVU3BvbnNvckZlZVRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhRTZXRTY3JpcHRUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIWQ3JlYXRlQWxpYXNUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIWTGVhc2VDYW5jZWxUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIQTGVhc2VUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIQSXNzdWVUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIbSW52b2tlRXhwcmVzc2lvblRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhpVcGRhdGVBc3NldEluZm9UcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIXSW52b2tlU2NyaXB0VHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACGVNldEFzc2V0U2NyaXB0VHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACE1RyYW5zZmVyVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACE0V4Y2hhbmdlVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACF01hc3NUcmFuc2ZlclRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAg9CdXJuVHJhbnNhY3Rpb24GCQABAgUHJG1hdGNoMAISUmVpc3N1ZVRyYW5zYWN0aW9uBAF0BQckbWF0Y2gwBAR0eElkCQDYBAEIBQF0AmlkBApwcm9wb3NhbElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgULZ292Q29udHJhY3QJARJrZXlBcHBseUluUHJvZ3Jlc3MAAhZBcHBseSBpcyBub3QgaGFwcGVuaW5nBAZ0eExpc3QJALUJAgkAkQMCCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQtnb3ZDb250cmFjdAkBE2tleVByb3Bvc2FsRGF0YUJ5SWQBBQpwcm9wb3NhbElkBQNTRVAFC2dvdklkeFR4SWRzBQdMSVNUU0VQAwkBASEBCQEJaXNEZWZpbmVkAQkAzwgCBQZ0eExpc3QFBHR4SWQJAAIBCQCsAgIJAKwCAgkArAICAg5Vbmtub3duIHR4SWQ6IAUEdHhJZAIQIGZvciBwcm9wb3NhbElkPQkApAMBBQpwcm9wb3NhbElkBgkAAgECC01hdGNoIGVycm9yDwFpAQ1jb25zdHJ1Y3RvclYxDBJuZXV0cmlub0Fzc2V0SWRQcm0OYm9uZEFzc2V0SWRQcm0SYXVjdGlvbkNvbnRyYWN0UHJtFmxpcXVpZGF0aW9uQ29udHJhY3RQcm0OcnBkQ29udHJhY3RQcm0bbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5UHJtG2JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbFBybR5iYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxQcm0VbWluV2F2ZXNTd2FwQW1vdW50UHJtGG1pbk5ldXRyaW5vU3dhcEFtb3VudFBybRVuZXV0cmlub091dEZlZVBhcnRQcm0Sd2F2ZXNPdXRGZWVQYXJ0UHJtBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCQDMCAIJAQtTdHJpbmdFbnRyeQIFEk5ldXRyaW5vQXNzZXRJZEtleQUSbmV1dHJpbm9Bc3NldElkUHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFDkJvbmRBc3NldElkS2V5BQ5ib25kQXNzZXRJZFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRJBdWN0aW9uQ29udHJhY3RLZXkFEmF1Y3Rpb25Db250cmFjdFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5BRZsaXF1aWRhdGlvbkNvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFDlJQRENvbnRyYWN0S2V5BQ5ycGRDb250cmFjdFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkFG25vZGVPcmFjbGVQcm92aWRlclB1YktleVBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUbQmFsYW5jZVdhdmVzTG9ja0ludGVydmFsS2V5BRtiYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFHkJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbEtleQUeYmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsUHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQIFV0FWRVMFFW1pbldhdmVzU3dhcEFtb3VudFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5BRhtaW5OZXV0cmlub1N3YXBBbW91bnRQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFFU5ldXRyaW5vT3V0RmVlUGFydEtleQUVbmV1dHJpbm9PdXRGZWVQYXJ0UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJXYXZlc091dEZlZVBhcnRLZXkFEndhdmVzT3V0RmVlUGFydFBybQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNvbnN0cnVjdG9yVjIDDG1hdGhDb250cmFjdBNuc2J0U3Rha2luZ0NvbnRyYWN0FHN3YXBzVGltZWZyYW1lQmxvY2tzBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCQDMCAIJAQtTdHJpbmdFbnRyeQIFD01hdGhDb250cmFjdEtleQUMbWF0aENvbnRyYWN0CQDMCAIJAQtTdHJpbmdFbnRyeQIFFk5zYnRTdGFraW5nQ29udHJhY3RLZXkFE25zYnRTdGFraW5nQ29udHJhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIJARFzd2Fwc1RpbWVmcmFtZUtFWQAFFHN3YXBzVGltZWZyYW1lQmxvY2tzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY29uc3RydWN0b3JWMwURYXNzZXRzV2VpZ2h0c01pbnMGZFBhcmFtBmtQYXJhbQZiUGFyYW0KZGVsdGFQYXJhbQQLY2hlY2tDYWxsZXIJAQh0aGlzT25seQEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQITbm8gcGF5bWVudHMgYWxsb3dlZAoBB3ByZXBhcmUCA2FjYwRpdGVtBAVwYXJ0cwkAtQkCBQRpdGVtAgFfBAdhc3NldElkCQCRAwIFBXBhcnRzAAAEBndlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAEEBm1pblZhbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAIJAJQKAgkAzQgCCAUDYWNjAl8xBQdhc3NldElkCQDNCAIJAM0IAggFA2FjYwJfMgkBDEludGVnZXJFbnRyeQIJARZiYXNrZXRXZWlnaHRCeUFzc2V0S2V5AQUHYXNzZXRJZAUGd2VpZ2h0CQEMSW50ZWdlckVudHJ5AgkBFU1pblRva2VuU3dhcEFtb3VudEtleQEFB2Fzc2V0SWQFBm1pblZhbAQBcgoAAiRsBRFhc3NldHNXZWlnaHRzTWlucwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3ByZXBhcmUCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAUBcgJfMgkBDEludGVnZXJFbnRyeQIJAQpiYXNrZXRES2V5AAUGZFBhcmFtCQEMSW50ZWdlckVudHJ5AgkBCmJhc2tldEtLZXkABQZrUGFyYW0JAQxJbnRlZ2VyRW50cnkCCQEKYmFza2V0QktleQAFBmJQYXJhbQkBDEludGVnZXJFbnRyeQIJARJiYXNrZXRMb2diRGVsdGFLZXkACQBtBgUKZGVsdGFQYXJhbQAGBQZiUGFyYW0ABgAGBQZIQUxGVVAJAQtTdHJpbmdFbnRyeQIJAQ9iYXNrZXRBc3NldHNLZXkACQC5CQIIBQFyAl8xBQNTRVAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETc3dhcFRva2VuVG9OZXV0cmlubwADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAixzd2FwVG9rZW5Ub05ldXRyaW5vIHJlcXVpcmUgb25seSBvbmUgcGF5bWVudAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEDGJhc2tldEFzc2V0cwkBBXZhbHVlAQkAoggBCQEPYmFza2V0QXNzZXRzS2V5AAQNcG10QXNzZXRJZFN0cgkA2AQBCQELdmFsdWVPckVsc2UCCAUDcG10B2Fzc2V0SWQFB1dBVkVTSUQDCQEBIQEJAQhjb250YWlucwIFDGJhc2tldEFzc2V0cwUNcG10QXNzZXRJZFN0cgkAAgEJAKwCAgkArAICBQ1wbXRBc3NldElkU3RyAh0gaXMgbm90IG9uZSBvZiBiYXNrZXQgdG9rZW5zOgUMYmFza2V0QXNzZXRzBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBAt0b3RhbExvY2tlZAkBD3RvdGFsTG9ja2VkUkVBRAICC291dE5ldXRyaW5vBQ1wbXRBc3NldElkU3RyBAlwbXRBbW91bnQIBQNwbXQGYW1vdW50BA9zYXZlVG90YWxMb2NrZWQJAPwHBAUEdGhpcwITaW50ZXJuYWxTYXZlSW50ZWdlcgkAzAgCCQEOdG90YWxMb2NrZWRLRVkCAgtvdXROZXV0cmlubwUNcG10QXNzZXRJZFN0cgkAzAgCCQBkAgULdG90YWxMb2NrZWQFCXBtdEFtb3VudAUDbmlsBQNuaWwDCQAAAgUPc2F2ZVRvdGFsTG9ja2VkBQ9zYXZlVG90YWxMb2NrZWQJAQpjb21tb25Td2FwBQILb3V0TmV1dHJpbm8FCXBtdEFtb3VudAUNcG10QXNzZXRJZFN0cgULdXNlckFkZHJlc3MFBnR4SWQ1OAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARRzd2FwTmV1dHJpbm9Ub0Jhc2tldAADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAi1zd2FwTmV1dHJpbm9Ub0Jhc2tldCByZXF1aXJlIG9ubHkgb25lIHBheW1lbnQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQJAAIBAjpPbmx5IGFwcHJvcHJpYXRlIE5ldXRyaW5vIHRva2VucyBhcmUgYWxsb3dlZCBmb3Igc3dhcHBpbmcuBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBBJuZXV0cmlub0Fzc2V0SWRTdHIJANgEAQUPbmV1dHJpbm9Bc3NldElkBAt0b3RhbExvY2tlZAkBD3RvdGFsTG9ja2VkUkVBRAICCG91dE11bHRpBRJuZXV0cmlub0Fzc2V0SWRTdHIECXBtdEFtb3VudAgFA3BtdAZhbW91bnQED3NhdmVUb3RhbExvY2tlZAkA/AcEBQR0aGlzAhNpbnRlcm5hbFNhdmVJbnRlZ2VyCQDMCAIJAQ50b3RhbExvY2tlZEtFWQICCG91dE11bHRpBRJuZXV0cmlub0Fzc2V0SWRTdHIJAMwIAgkAZAIFC3RvdGFsTG9ja2VkBQlwbXRBbW91bnQFA25pbAUDbmlsAwkAAAIFD3NhdmVUb3RhbExvY2tlZAUPc2F2ZVRvdGFsTG9ja2VkCQEKY29tbW9uU3dhcAUCCG91dE11bHRpCAUDcG10BmFtb3VudAUSbmV1dHJpbm9Bc3NldElkU3RyBQt1c2VyQWRkcmVzcwUGdHhJZDU4CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBE2ludGVybmFsU2F2ZUludGVnZXICA2tleQZhbW91bnQDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAihpbnRlcm5hbFNhdmVJbnRlZ2VyIGlzIG5vdCBwdWJsaWMgbWV0aG9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQNrZXkFBmFtb3VudAUDbmlsAWkBCHdpdGhkcmF3AwdhY2NvdW50BWluZGV4CHN3YXBUeElkBAR0eElkCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkBA9uZXV0cmlub01ldHJpY3MJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIaY2FsY05ldXRpbm9NZXRyaWNzUkVBRE9OTFkFA25pbAUDbmlsBAJCUgkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFDG5NZXRyaWNJZHhCUgQLdXNlckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB2FjY291bnQECWRhdGFBcnJheQkBEnN3YXBEYXRhRmFpbE9yUkVBRAIFB2FjY291bnQFCHN3YXBUeElkBBBzZWxmVW5sb2NrSGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGF0YUFycmF5BRRzSWR4U2VsZlVubG9ja0hlaWdodAQIc3dhcFR5cGUJAJEDAgUJZGF0YUFycmF5BQxzSWR4U3dhcFR5cGUECGluQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGF0YUFycmF5BQxzSWR4SW5BbW91bnQECnN3YXBTdGF0dXMJAJEDAgUJZGF0YUFycmF5BQpzSWR4U3RhdHVzBAtzdGFydEhlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRhdGFBcnJheQUPc0lkeFN0YXJ0SGVpZ2h0BAdpbkFzc2V0CQCRAwIFCWRhdGFBcnJheQULc0lkeEluQXNzZXQEC3RvdGFsTG9ja2VkCQEPdG90YWxMb2NrZWRSRUFEAgUIc3dhcFR5cGUFB2luQXNzZXQEEXRvdGFsTG9ja2VkQnlVc2VyCQEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAwUIc3dhcFR5cGUFB2FjY291bnQFB2luQXNzZXQEDHVubG9ja0hlaWdodAUQc2VsZlVubG9ja0hlaWdodAQLaW5kZXhIZWlnaHQJARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBBQVpbmRleAQPcHJldkluZGV4SGVpZ2h0CQEVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AQkAZQIFBWluZGV4AAEEDHByaWNlQnlJbmRleAkBD2dldFByaWNlSGlzdG9yeQEFC2luZGV4SGVpZ2h0AwUJaXNCbG9ja2VkCQEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAMJAQIhPQIFCnN3YXBTdGF0dXMCB1BFTkRJTkcJAAIBAh9zd2FwIGhhcyBiZWVuIGFscmVhZHkgcHJvY2Vzc2VkAwkAZgIFDHVubG9ja0hlaWdodAUGaGVpZ2h0CQACAQkArAICCQCsAgICEXBsZWFzZSB3YWl0IGZvcjogCQCkAwEFDHVubG9ja0hlaWdodAIfIGJsb2NrIGhlaWdodCB0byB3aXRoZHJhdyBmdW5kcwMDAwkAZgIFBWluZGV4BQpwcmljZUluZGV4BgkAZgIFDHVubG9ja0hlaWdodAULaW5kZXhIZWlnaHQGAwkBAiE9AgUPcHJldkluZGV4SGVpZ2h0AAAJAGcCBQ9wcmV2SW5kZXhIZWlnaHQFDHVubG9ja0hlaWdodAcJAQ5wcmljZUluZGV4RkFJTAUFBWluZGV4BQpwcmljZUluZGV4BQtpbmRleEhlaWdodAUMdW5sb2NrSGVpZ2h0BQ9wcmV2SW5kZXhIZWlnaHQEDXdpdGhkcmF3VHVwbGUJAQxjYWxjV2l0aGRyYXcFBQhzd2FwVHlwZQUIaW5BbW91bnQFDHByaWNlQnlJbmRleAUPbmV1dHJpbm9NZXRyaWNzBQdpbkFzc2V0BAxvdXROZXRBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl8xBApvdXRBc3NldElkCAUNd2l0aGRyYXdUdXBsZQJfMgQKb3V0U3VyZkFtdAgFDXdpdGhkcmF3VHVwbGUCXzMECnVubGVhc2VBbXQIBQ13aXRoZHJhd1R1cGxlAl81BAxvdXRGZWVBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl82BAtvdXRBbXRHcm9zcwgFDXdpdGhkcmF3VHVwbGUCXzcEDXdpdGhkcmF3UHJpY2UIBQ13aXRoZHJhd1R1cGxlAl84BA53aXRoZHJhd0Jhc2tldAgFDXdpdGhkcmF3VHVwbGUCXzkDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAZwIAAAULb3V0QW10R3Jvc3MHCQACAQITYmFsYW5jZSBlcXVhbHMgemVybwQNc3VyZkNvbmRpdGlvbgMJAGYCBQpvdXRTdXJmQW10AAAEC2lzc3VlUmVzdWx0CQD8BwQFD2F1Y3Rpb25Db250cmFjdAIJaXNzdWVTdXJmCQDMCAIFCm91dFN1cmZBbXQJAMwIAgUHYWNjb3VudAUDbmlsBQNuaWwDCQAAAgULaXNzdWVSZXN1bHQFC2lzc3VlUmVzdWx0AAAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAMJAAACBQ1zdXJmQ29uZGl0aW9uBQ1zdXJmQ29uZGl0aW9uBBF1bmxlYXNlSW52T3JFbXB0eQkA/AcEBQR0aGlzAhdpbnRlcm5hbFVubGVhc2VBbmRMZWFzZQkAzAgCBQp1bmxlYXNlQW10BQNuaWwFA25pbAMJAAACBRF1bmxlYXNlSW52T3JFbXB0eQURdW5sZWFzZUludk9yRW1wdHkECWduc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUXZ25zYnRDb250cm9sbGVyQ29udHJhY3QCFGduc2J0SW5mb1NZU1JFQURPTkxZCQDMCAICAAkAzAgCAAAJAMwIAgAABQNuaWwFA25pbAQNZ25zYnRBbXRUb3RhbAkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAQQVZ25zYnRBbXRGcm9tU3VyZlRvdGFsCQEFYXNJbnQBCQCRAwIJAQlhc0FueUxpc3QBCQCRAwIFCWduc2J0RGF0YQADAAMEDWNvbW1vbkFjdGlvbnMJAMwIAgkBDEludGVnZXJFbnRyeQIJARR0b3RhbExvY2tlZEJ5VXNlcktFWQMFCHN3YXBUeXBlBQdhY2NvdW50BQdpbkFzc2V0CQBlAgURdG90YWxMb2NrZWRCeVVzZXIFCGluQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG90YWxMb2NrZWRLRVkCBQhzd2FwVHlwZQUHaW5Bc3NldAkAZQIFC3RvdGFsTG9ja2VkBQhpbkFtb3VudAkAzAgCCQELU3RyaW5nRW50cnkCCQEHc3dhcEtFWQIFB2FjY291bnQFCHN3YXBUeElkCQEOZmluaXNoU3dhcERBVEELBQlkYXRhQXJyYXkFDXdpdGhkcmF3UHJpY2UFDG91dE5ldEFtb3VudAUMb3V0RmVlQW1vdW50BQx1bmxvY2tIZWlnaHQFBWluZGV4BQR0eElkBQpvdXRTdXJmQW10BQJCUgUOd2l0aGRyYXdCYXNrZXQFB2luQXNzZXQFA25pbAoBCGRlcG9zaXRzBAhzdXJmRmVlcwhuc2J0RmVlcwxzdXJmUGF5bWVudHMMbnNidFBheW1lbnRzBAtzdXJmRGVwb3NpdAMJAGYCBQhzdXJmRmVlcwAACQEFYXNJbnQBCQD8BwQFE3N1cmZTdGFraW5nQ29udHJhY3QCB2RlcG9zaXQFA25pbAUMc3VyZlBheW1lbnRzAAAEC25zYnREZXBvc2l0AwkAZgIFCG5zYnRGZWVzAAAJAQVhc0ludAEJAPwHBAUTbnNidFN0YWtpbmdDb250cmFjdAIHZGVwb3NpdAUDbmlsBQxuc2J0UGF5bWVudHMAAAkAZAIFC3N1cmZEZXBvc2l0BQtuc2J0RGVwb3NpdAoBCmRpdmlkZUZlZXMBCWZlZUFtb3VudAQIc3VyZkFtdDEDCQECIT0CBQ1nbnNidEFtdFRvdGFsAAAJAGsDBQlmZWVBbW91bnQFFWduc2J0QW10RnJvbVN1cmZUb3RhbAUNZ25zYnRBbXRUb3RhbAAABAhzdXJmQW10MgMJAQIhPQIFDWduc2J0QW10VG90YWwAAAkAawMFCWZlZUFtb3VudAkAZQIFBU1VTFQ2BQJCUgUFTVVMVDYAAAQHc3VyZkFtdAkAlgMBCQDMCAIFCHN1cmZBbXQxCQDMCAIFCHN1cmZBbXQyBQNuaWwEB25zYnRBbXQJAGUCBQlmZWVBbW91bnQFB3N1cmZBbXQJAMwIAgUHc3VyZkFtdAkAzAgCBQduc2J0QW10BQNuaWwECXRyYW5zZmVycwMJAAACBQhzd2FwVHlwZQIIb3V0TXVsdGkEBmJhc2tldAkAvAkCBQ53aXRoZHJhd0Jhc2tldAIBXwoBBmxvb3BlcgIDYWNjBGl0ZW0EAml0CQC1CQIFBGl0ZW0FB0xJU1RTRVAEC3RlbXBBc3NldElkCQDZBAEJAJEDAgUCaXQAAAQHYXNzZXRJZAMJAAACBQt0ZW1wQXNzZXRJZAUHV0FWRVNJRAUEdW5pdAULdGVtcEFzc2V0SWQECW5ldEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAml0AAIECWZlZUFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAml0AAMEBGZlZXMJAQpkaXZpZGVGZWVzAQUJZmVlQW1vdW50CQCXCgUJAM0IAggFA2FjYwJfMQkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFCW5ldEFtb3VudAUHYXNzZXRJZAkAzQgCCAUDYWNjAl8yCQEPQXR0YWNoZWRQYXltZW50AgUHYXNzZXRJZAkAkQMCBQRmZWVzAAAJAM0IAggFA2FjYwJfMwkBD0F0dGFjaGVkUGF5bWVudAIFB2Fzc2V0SWQJAJEDAgUEZmVlcwABCQBkAggFA2FjYwJfNAkAkQMCBQRmZWVzAAAJAGQCCAUDYWNjAl81CQCRAwIFBGZlZXMAAQQBcgoAAiRsBQZiYXNrZXQKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCXCgUFA25pbAUDbmlsBQNuaWwAAAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQZsb29wZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoECmRlcG9SZXN1bHQJAQhkZXBvc2l0cwQIBQFyAl80CAUBcgJfNQgFAXICXzIIBQFyAl8zCQCUCgIIBQFyAl8xBQpkZXBvUmVzdWx0BARmZWVzCQEKZGl2aWRlRmVlcwEFDG91dEZlZUFtb3VudAQKZGVwb1Jlc3VsdAkBCGRlcG9zaXRzBAkAkQMCBQRmZWVzAAAJAJEDAgUEZmVlcwABCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQpvdXRBc3NldElkCQCRAwIFBGZlZXMAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQpvdXRBc3NldElkCQCRAwIFBGZlZXMAAQUDbmlsCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFDG91dE5ldEFtb3VudAUKb3V0QXNzZXRJZAUDbmlsBQpkZXBvUmVzdWx0CQCUCgIJAM4IAgUNY29tbW9uQWN0aW9ucwgFCXRyYW5zZmVycwJfMQgFCXRyYW5zZmVycwJfMgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARdpbnRlcm5hbFVubGVhc2VBbmRMZWFzZQENdW5sZWFzZUFtb3VudAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLGludGVybmFsVW5sZWFzZUFuZExlYXNlIGlzIG5vdCBwdWJsaWMgbWV0aG9kCQEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQEFDXVubGVhc2VBbW91bnQBaQESdHJhbnNmZXJVc2RuVG9Vc2VyAgZhbW91bnQEYWRkcgMJAQIhPQIIBQFpBmNhbGxlcgUPYXVjdGlvbkNvbnRyYWN0CQACAQIjT25seSBhdWN0aW9uIGNvbnRyYWN0IGlzIGF1dGhvcml6ZWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUEYWRkcgUGYW1vdW50BQ9uZXV0cmlub0Fzc2V0SWQFA25pbAFpAQthY2NlcHRXYXZlcwADAwkBAiE9AggFAWkGY2FsbGVyBQ9hdWN0aW9uQ29udHJhY3QJAQIhPQIIBQFpBmNhbGxlcgULZ292Q29udHJhY3QHCQACAQJDQ3VycmVudGx5IG9ubHkgYXVjdGlvbiBhbmQgZ292ZXJuYW5jZSBjb250cmFjdHMgYXJlIGFsbG93ZWQgdG8gY2FsbAkAlAoCCQEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQEAAAIHc3VjY2VzcwFpAQ9hcHByb3ZlTGVhc2luZ3MDBm5MaXN0Uwhncm91cE51bQRsQW10BAVuSWR4cwkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHBQNuaWwEB21uZ1B1YlMJAQt2YWx1ZU9yRWxzZQIJAKIIAQIcJXMlc19fY2ZnX19sZWFzaW5nTWFuYWdlclB1YgIsN0FVTVg1NHVrWU1ZdlBtbWE3eW9GZjVOalpoczRCdTVuejNFejlFVjhzdXIEBm1uZ1B1YgkA2QQBBQdtbmdQdWJTBA5ub2RlUmVnQWRkclN0cgkBC3ZhbHVlT3JFbHNlAgkAoggBAh8lcyVzX19jZmdfX25vZGVzUmVnaXN0cnlBZGRyZXNzAiMzUDl2S3FRS2pVZG1wWEFmaVdhdThrclJFWUFZMVhyNjlwRQQLbm9kZVJlZ0FkZHIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDm5vZGVSZWdBZGRyU3RyBBFsR3JvdXBOb2RlTGlzdEtFWQkBGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEFCGdyb3VwTnVtBApsR3JOb2RlT3B0CQCdCAIFBHRoaXMFEWxHcm91cE5vZGVMaXN0S0VZAwkBCWlzRGVmaW5lZAEFCmxHck5vZGVPcHQJAAIBCQCsAgIJAKwCAgIGZ3JvdXAgCQCkAwEFCGdyb3VwTnVtAhQgYWxyZWFkeSBpbml0aWFsaXplZAQFbkxpc3QJALUJAgUGbkxpc3RTBQNTRVAECGV4cENvdW50CQCQAwEFBW5JZHhzAwkBAiE9AggFAWkPY2FsbGVyUHVibGljS2V5BQZtbmdQdWIJAAIBAh5hcHByb3ZlTGVhc2luZ3Mgbm90IGF1dGhvcml6ZWQEDSR0MDQ0NDI1NDQ0ODcJAQxyZWFkTm9kZUluZm8BAAAEBm5BZGRyMAgFDSR0MDQ0NDI1NDQ0ODcCXzEECGxBbXRLRVkwCAUNJHQwNDQ0MjU0NDQ4NwJfMgQFbEFtdDAIBQ0kdDA0NDQyNTQ0NDg3Al8zBAdsSWRLRVkwCAUNJHQwNDQ0MjU0NDQ4NwJfNAQEbElkMAgFDSR0MDQ0NDI1NDQ0ODcCXzUEBW5ld0wwCQDECAIFBm5BZGRyMAkAZQIFBWxBbXQwCQBoAgUEbEFtdAUIZXhwQ291bnQECnZhbGlkYXRpb24JAPwHBAULbm9kZVJlZ0FkZHICGnZhbGlkYXRlQW5kQXBwcm92ZUxlYXNpbmdzCQDMCAIFBm5MaXN0UwUDbmlsBQNuaWwDCQAAAgUKdmFsaWRhdGlvbgUKdmFsaWRhdGlvbgoBI2ZvckVhY2hOb2RlVmFsaWRhdGVBbmRHZW5lcmF0ZUxlYXNlAgFhAWkEBG5vZGUJAJEDAgUFbkxpc3QFAWkEAmxhCQDECAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBG5vZGUFBGxBbXQJAM4IAgUBYQkAzAgCBQJsYQkAzAgCCQELQmluYXJ5RW50cnkCCQEWZ2V0TGVhc2VJZEJ5QWRkcmVzc0tleQEFBG5vZGUJAQVsY2FsYwEFAmxhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBBQRub2RlBQRsQW10BQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBRFsR3JvdXBOb2RlTGlzdEtFWQUGbkxpc3RTCQDMCAIJAQtCaW5hcnlFbnRyeQIFB2xJZEtFWTAJAQVsY2FsYwEFBW5ld0wwCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhsQW10S0VZMAgFBW5ld0wwBmFtb3VudAkAzAgCCQELTGVhc2VDYW5jZWwBBQRsSWQwCQDMCAIFBW5ld0wwBQNuaWwKAAIkbAUFbklkeHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBI2ZvckVhY2hOb2RlVmFsaWRhdGVBbmRHZW5lcmF0ZUxlYXNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA4CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARFyZWJhbGFuY2VMZWFzaW5ncwIGYW1vdW50CGdyb3VwTnVtBAVuSWR4cwkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHBQNuaWwEB21uZ1B1YlMJAQt2YWx1ZU9yRWxzZQIJAKIIAQIcJXMlc19fY2ZnX19sZWFzaW5nTWFuYWdlclB1YgIsN0FVTVg1NHVrWU1ZdlBtbWE3eW9GZjVOalpoczRCdTVuejNFejlFVjhzdXIEBm1uZ1B1YgkA2QQBBQdtbmdQdWJTBBFsR3JvdXBOb2RlTGlzdEtFWQkBGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEFCGdyb3VwTnVtBAZuTGlzdFMJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzBRFsR3JvdXBOb2RlTGlzdEtFWQQFbkxpc3QJALUJAgUGbkxpc3RTBQNTRVADCQECIT0CCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBm1uZ1B1YgkAAgECIHJlYmFsYW5jZUxlYXNpbmdzIG5vdCBhdXRob3JpemVkBAp1bmxlYXNlQW10CQBkAgkAaQIFBmFtb3VudAkAkAMBBQVuTGlzdAABBA0kdDA0NTcyNzQ1Nzg5CQEMcmVhZE5vZGVJbmZvAQAABAZuQWRkcjAIBQ0kdDA0NTcyNzQ1Nzg5Al8xBAhsQW10S0VZMAgFDSR0MDQ1NzI3NDU3ODkCXzIEBWxBbXQwCAUNJHQwNDU3Mjc0NTc4OQJfMwQHbElkS0VZMAgFDSR0MDQ1NzI3NDU3ODkCXzQEBGxJZDAIBQ0kdDA0NTcyNzQ1Nzg5Al81BAVuZXdMMAkAxAgCBQZuQWRkcjAJAGQCBQVsQW10MAkAaAIFCnVubGVhc2VBbXQJAJADAQUFbkxpc3QKARRmb3JFYWNoTm9kZURvVW5sZWFzZQIBYQFpBARub2RlCQCRAwIFBW5MaXN0BQFpBAZsSWRLRVkJARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQUEbm9kZQQDbElkCQERQGV4dHJOYXRpdmUoMTA1MikCBQR0aGlzBQZsSWRLRVkEB2xBbXRLRVkJARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQEFBG5vZGUEBGxBbXQJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMFB2xBbXRLRVkEA3VsYQkBC0xlYXNlQ2FuY2VsAQkBBXZhbHVlAQUDbElkBAJsYQkAxAgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQRub2RlCQBlAgUEbEFtdAUKdW5sZWFzZUFtdAkAzggCBQFhCQDMCAIJAQtMZWFzZUNhbmNlbAEJAQV2YWx1ZQEFA2xJZAkAzAgCBQJsYQkAzAgCCQELQmluYXJ5RW50cnkCBQZsSWRLRVkJAQVsY2FsYwEFAmxhCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQdsQW10S0VZCAUCbGEGYW1vdW50BQNuaWwJAM4IAgoAAiRsBQVuSWR4cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEUZm9yRWFjaE5vZGVEb1VubGVhc2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAICQDMCAIJAQtCaW5hcnlFbnRyeQIFB2xJZEtFWTAJAQVsY2FsYwEFBW5ld0wwCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhsQW10S0VZMAgFBW5ld0wwBmFtb3VudAkAzAgCCQELTGVhc2VDYW5jZWwBBQRsSWQwCQDMCAIFBW5ld0wwBQNuaWwBaQEbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZAg51c2VyQWRkcmVzc1N0cglnbnNidERpZmYECWduc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUXZ25zYnRDb250cm9sbGVyQ29udHJhY3QCFGduc2J0SW5mb1NZU1JFQURPTkxZCQDMCAIFDnVzZXJBZGRyZXNzU3RyCQDMCAIAAAkAzAgCAAAFA25pbAUDbmlsBAhnbnNidEFtdAkAZAIJAQVhc0ludAEJAJEDAgUJZ25zYnREYXRhAAAFCWduc2J0RGlmZgQNZ25zYnRBbXRUb3RhbAkAZAIJAQVhc0ludAEJAJEDAgUJZ25zYnREYXRhAAEFCWduc2J0RGlmZgQNc3dhcExpbWl0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhVjYWxjU3dhcExpbWl0UkVBRE9OTFkJAMwIAgUIZ25zYnRBbXQFA25pbAUDbmlsBBZ0b2tlblN3YXBMaW1pdEluVXNkTWF4CQEFYXNJbnQBCQCRAwIFDXN3YXBMaW1pdERhdGEAAAQQdXNkblN3YXBMaW1pdE1heAkBBWFzSW50AQkAkQMCBQ1zd2FwTGltaXREYXRhAAIEDmxhc3RTd2FwSGVpZ2h0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBBQ51c2VyQWRkcmVzc1N0cgAABBdzd2FwTGltaXRUaW1lbGlmZUJsb2NrcwkBEnN3YXBzVGltZWZyYW1lUkVBRAAEGXBhc3NlZEJsb2Nrc0FmdGVyTGFzdFN3YXAJAGUCBQZoZWlnaHQFDmxhc3RTd2FwSGVpZ2h0BBFpc1N3YXBUaW1lbGlmZU5ldwkAZwIFGXBhc3NlZEJsb2Nrc0FmdGVyTGFzdFN3YXAFF3N3YXBMaW1pdFRpbWVsaWZlQmxvY2tzBBRzd2FwTGltaXRTcGVudEluVXNkbgMFEWlzU3dhcFRpbWVsaWZlTmV3AAAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBGGtleVN3YXBVc2VyU3BlbnRJblBlcmlvZAEFDnVzZXJBZGRyZXNzU3RyAAAEDmJsY2tzMkxtdFJlc2V0AwURaXNTd2FwVGltZWxpZmVOZXcAAAkAZQIFF3N3YXBMaW1pdFRpbWVsaWZlQmxvY2tzBRlwYXNzZWRCbG9ja3NBZnRlckxhc3RTd2FwCQCUCgIFA25pbAkAmQoHBRZ0b2tlblN3YXBMaW1pdEluVXNkTWF4BRRzd2FwTGltaXRTcGVudEluVXNkbgUOYmxja3MyTG10UmVzZXQFCGduc2J0QW10BQ1nbnNidEFtdFRvdGFsAAAFEHVzZG5Td2FwTGltaXRNYXgBaQEdY2FsY1dpdGhkcmF3UmVzdWx0U1lTUkVBRE9OTFkECHN3YXBUeXBlCGluQW1vdW50BXByaWNlB2luQXNzZXQED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwJAJQKAgUDbmlsCQEMY2FsY1dpdGhkcmF3BQUIc3dhcFR5cGUFCGluQW1vdW50BQVwcmljZQUPbmV1dHJpbm9NZXRyaWNzBQdpbkFzc2V0AWkBFHJlcGxhY2VDb21tdW5pdHlOb2RlBApvbGRBZGRyU3RyCm5ld0FkZHJTdHIIZ3JvdXBOdW0NcGVuYWx0eUFtb3VudAQHbW5nUHViUwkBC3ZhbHVlT3JFbHNlAgkAoggBAhwlcyVzX19jZmdfX2xlYXNpbmdNYW5hZ2VyUHViAiw3QVVNWDU0dWtZTVl2UG1tYTd5b0ZmNU5qWmhzNEJ1NW56M0V6OUVWOHN1cgQGbW5nUHViCQDZBAEFB21uZ1B1YlMDCQECIT0CCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBm1uZ1B1YgkAAgECI3JlcGxhY2VDb21tdW5pdHlOb2RlIG5vdCBhdXRob3JpemVkBAhncm91cEtleQkBGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEFCGdyb3VwTnVtBA5ncm91cE5vZGVMaXN0UwkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMFCGdyb3VwS2V5AwkBASEBCQEIY29udGFpbnMCBQ5ncm91cE5vZGVMaXN0UwUKb2xkQWRkclN0cgkAAgEJAKwCAgkArAICCQCsAgICBkdyb3VwIAkApAMBBQhncm91cE51bQIaIGRvZXMgbm90IGNvbnRhaW4gYWRkcmVzcyAFCm9sZEFkZHJTdHIECWRvUmVwbGFjZQkA/AcEBRRub2RlUmVnaXN0cnlDb250cmFjdAITcmVwbGFjZUFwcHJvdmVkTm9kZQkAzAgCBQpvbGRBZGRyU3RyCQDMCAIFCm5ld0FkZHJTdHIJAMwIAgUIZ3JvdXBOdW0JAMwIAgUNcGVuYWx0eUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJZG9SZXBsYWNlBQlkb1JlcGxhY2UEDW9sZExlYXNlSWRLZXkJARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQUKb2xkQWRkclN0cgQOb2xkTGVhc2VBbXRLZXkJARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQEFCm9sZEFkZHJTdHIECGxlYXNlQW10CQERQGV4dHJOYXRpdmUoMTA1NSkBBQ5vbGRMZWFzZUFtdEtleQQNbmV3TGVhc2VJZEtleQkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQpuZXdBZGRyU3RyBA5uZXdMZWFzZUFtdEtleQkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUKbmV3QWRkclN0cgQIbmV3TGVhc2UJAMQIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUKbmV3QWRkclN0cgUIbGVhc2VBbXQEFXVwZGF0ZWRHcm91cE5vZGVMaXN0UwkAuQkCCQC1CQIFDmdyb3VwTm9kZUxpc3RTBQpvbGRBZGRyU3RyBQpuZXdBZGRyU3RyCQCUCgIJAMwIAgkBC0xlYXNlQ2FuY2VsAQkBEUBleHRyTmF0aXZlKDEwNTcpAQUNb2xkTGVhc2VJZEtleQkAzAgCCQELRGVsZXRlRW50cnkBBQ1vbGRMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFDm9sZExlYXNlQW10S2V5CQDMCAIJAQtTdHJpbmdFbnRyeQIFCGdyb3VwS2V5BRV1cGRhdGVkR3JvdXBOb2RlTGlzdFMJAMwIAgUIbmV3TGVhc2UJAMwIAgkBC0JpbmFyeUVudHJ5AgUNbmV3TGVhc2VJZEtleQkBBWxjYWxjAQUIbmV3TGVhc2UJAMwIAgkBDEludGVnZXJFbnRyeQIFDm5ld0xlYXNlQW10S2V5BQhsZWFzZUFtdAUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAQTcHViS2V5QWRtaW5zTGlzdFN0cgkAuQkCCQDMCAICLEV4dEVFSzE5bm1LajltQ3BuV3l2RUVKRllBVExNY1ZFTXZvaGhVSGt5SE5tCQDMCAICLEV2NXB5NUZmQlFYOWNacFlLbmZRclRCNDlCeWY4UW1wWldlRFZSaW00eVY3CQDMCAICLERVdXVMalh1OThuQndaYzdmcXdDVGp0QTNublJ3Z1Ria01TcjVTVTJObURSCQDMCAICLERVdXVMalh1OThuQndaYzdmcXdDVGp0QTNublJ3Z1Ria01TcjVTVTJObURSBQNuaWwFA1NFUAQQcHViS2V5QWRtaW5zTGlzdAkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFD2NvbnRyb2xDb250cmFjdAIMJXNfX211bHRpc2lnBRNwdWJLZXlBZG1pbnNMaXN0U3RyBQNTRVAEBWNvdW50CQBkAgkAZAIJAGQCAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAAABAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwABCQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAABAAEAAAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAIJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAIAAQAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAwkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAwACAAADAwUJaXNCbG9ja2VkCQAAAgkBEUBleHRyTmF0aXZlKDEwNTMpAgUPY29udHJvbENvbnRyYWN0AhFpc19ibG9ja2VkX2NhbGxlcgkApQgBBQtnb3ZDb250cmFjdAcJAQ52YWxpZGF0ZVVwZGF0ZQEFAnR4BAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhVTcG9uc29yRmVlVHJhbnNhY3Rpb24ECXNwb25zb3JUeAUHJG1hdGNoMAMJARtjaGVja0lzVmFsaWRNaW5TcG9uc29yZWRGZWUBBQlzcG9uc29yVHgJAGcCBQVjb3VudAADBwkAZwIFBWNvdW50AAPjRafG", "height": 2471180, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 46ntvNZBvMjcy5ZtsLp8fvkfRprp3jwbzyVAs4CpZcA4 Next: AQJ7Zrp7GS9nYjJoXJfZVRRgRfHBTmufx9EeaeUXLaov 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 LegacyMinNeutrinoSwapAmountKey = "min_neutrino_swap_amount"
206206
207207 let NodeOracleProviderPubKeyKey = "node_oracle_provider"
208208
209209 let NeutrinoOutFeePartKey = "neutrinoOut_swap_feePart"
210210
211211 let WavesOutFeePartKey = "wavesOut_swap_feePart"
212212
213213 func keyNodeRegistry (address) = ("%s__" + address)
214214
215215
216216 let PriceKey = "price"
217217
218218 let PriceIndexKey = "price_index"
219219
220220 let IsBlockedKey = "is_blocked"
221221
222222 func getPriceHistoryKey (block) = ((PriceKey + "_") + toString(block))
223223
224224
225225 func getHeightPriceByIndexKey (index) = ((PriceIndexKey + "_") + toString(index))
226226
227227
228228 func getStakingNodeByIndex (idx) = getStringByKey(makeString(["%s%d%s", "lease", toString(idx), "nodeAddress"], SEP))
229229
230230
231231 func getStakingNodeAddressByIndex (idx) = addressFromStringValue(getStakingNodeByIndex(idx))
232232
233233
234234 func getReservedAmountForSponsorship () = valueOrElse(getInteger(this, makeString(["%s%s", "lease", "sponsorshipWavesReserve"], SEP)), (1000 * MULT8))
235235
236236
237237 func getBalanceUnlockBlockKey (owner) = ("balance_unlock_block_" + owner)
238238
239239
240240 func getLeaseIdKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "id"], SEP)
241241
242242
243243 func getLeaseIdByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "id"], SEP)
244244
245245
246246 func getLeaseAmountKey (nodeIndex) = makeString(["%s%d%s", "lease", toString(nodeIndex), "amount"], SEP)
247247
248248
249249 func getLeaseAmountByAddressKey (nodeAddress) = makeString(["%s%s%s", "leaseByAddress", nodeAddress, "amount"], SEP)
250250
251251
252252 func getLeaseGroupNodeListKey (groupNum) = makeString(["%s%d%s", "leaseGroup", toString(groupNum), "nodeList"], SEP)
253253
254254
255255 func minSwapAmountKEY (swapType) = (("min_" + swapType) + "_swap_amount")
256256
257257
258258 func totalLockedKEY (swapType,assetId) = makeString(["%s%s%s", "balanceLock", swapType, assetId], SEP)
259259
260260
261261 func totalLockedByUserKEY (swapType,owner,assetId) = makeString(["%s%s%s%s", "balanceLock", swapType, owner, assetId], "_")
262262
263263
264264 func balanceLockIntervalKEY (swapType) = if ((swapType == "outMulti"))
265265 then BalanceNeutrinoLockIntervalKey
266266 else BalanceWavesLockIntervalKey
267267
268268
269269 func nodeBalanceLockIntervalKEY () = "balance_node_lock_interval"
270270
271271
272272 func swapsTimeframeKEY () = "swaps_timeframe"
273273
274274
275275 func brProtectedKEY () = "min_BR_protection_level"
276276
277277
278278 func basketAssetsKey () = "%s%s__common__basketAssets"
279279
280280
281281 func basketDKey () = "%s%s__common__basketD"
282282
283283
284284 func basketKKey () = "%s%s__common__basketK"
285285
286286
287287 func basketBKey () = "%s%s__common__basketB"
288288
289289
290290 func basketLogbDeltaKey () = "%s%s__common__basketLogbDelta"
291291
292292
293293 func basketWeightByAssetKey (assetId) = ("%s%s%s__common__weightByAsset__" + assetId)
294294
295295
296296 func keyPriceByAsset (assetId) = ("%s%s%s__common__priceByAsset__" + assetId)
297297
298298
299299 func minSwapAmountREAD (swapType,assetId) = if ((swapType == "outMulti"))
300300 then valueOrElse(getInteger(MinNeutrinoSwapAmountKey), getNumberByKey(LegacyMinNeutrinoSwapAmountKey))
301301 else getNumberByKey(MinTokenSwapAmountKey(assetId))
302302
303303
304304 func swapsTimeframeREAD () = valueOrElse(getInteger(this, swapsTimeframeKEY()), 1440)
305305
306306
307307 func totalLockedREAD (swapType,assetId) = valueOrElse(getInteger(this, totalLockedKEY(swapType, assetId)), 0)
308308
309309
310310 func totalLockedByUserREAD (swapType,owner,assetId) = valueOrElse(getInteger(this, totalLockedByUserKEY(swapType, owner, assetId)), 0)
311311
312312
313313 func balanceLockIntervalREAD (swapType) = valueOrElse(getInteger(this, balanceLockIntervalKEY(swapType)), 1440)
314314
315315
316316 func nodeBalanceLockIntervalREAD () = valueOrElse(getInteger(this, nodeBalanceLockIntervalKEY()), 1)
317317
318318
319319 func keySwapUserSpentInPeriod (userAddress) = makeString(["%s%s", "swapUserSpentInPeriod", userAddress], SEP)
320320
321321
322322 func keyUserLastSwapHeight (userAddress) = makeString(["%s%s", "userLastSwapHeight", userAddress], SEP)
323323
324324
325325 func convertNeutrinoToWaves (amount,price) = fraction(amount, MULT8, price)
326326
327327
328328 func convertTokenToUsd (amount,price) = fraction(amount, price, MULT8)
329329
330330
331331 func convertWavesToNeutrino (amount,price) = fraction(amount, price, MULT8)
332332
333333
334334 func convertWavesToBond (amount,price) = convertTokenToUsd(amount, price)
335335
336336
337337 func convertJsonArrayToList (jsonArray) = split(jsonArray, ",")
338338
339339
340340 func convertBasketItemToNeutrino (inAmount,inAsset,basketInfoStr,neutrinoPrice) = {
341341 let basketInfo = split_4C(basketInfoStr, "_")
342342 func findItem (acc,item) = {
343343 let bItem = split(item, LISTSEP)
344344 if ((bItem[0] == inAsset))
345345 then bItem
346346 else acc
347347 }
348348
349349 let it = {
350350 let $l = basketInfo
351351 let $s = size($l)
352352 let $acc0 = nil
353353 func $f0_1 ($a,$i) = if (($i >= $s))
354354 then $a
355355 else findItem($a, $l[$i])
356356
357357 func $f0_2 ($a,$i) = if (($i >= $s))
358358 then $a
359359 else throw("List size exceeds 10")
360360
361361 $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)
362362 }
363363 let dlog6 = value(getInteger(basketLogbDeltaKey()))
364364 let d6 = value(getInteger(basketDKey()))
365365 let b6 = value(getInteger(basketBKey()))
366366 let w6 = value(getInteger(basketWeightByAssetKey(inAsset)))
367367 let p6 = ((dlog6 - w6) + parseIntValue(it[1]))
368368 let pp6 = pow(b6, 6, p6, 6, 6, HALFUP)
369369 let outAmountGross = fraction(inAmount, parseIntValue(it[2]), if ((neutrinoPrice == 0))
370370 then MULT8
371371 else (neutrinoPrice * 100))
372372 let multiplier = ((MULT6 + d6) - pp6)
373373 let netAmount = fraction(outAmountGross, multiplier, MULT6)
374374 let feeAmount = if ((netAmount >= outAmountGross))
375375 then 0
376376 else (outAmountGross - netAmount)
377377 [outAmountGross, netAmount, feeAmount]
378378 }
379379
380380
381381 func convertNeutrinoToBasket (amount,basketInfoStr,neutrinoSupply) = {
382382 let basketInfo = split_4C(basketInfoStr, "_")
383383 func conv (acc,item) = {
384384 let parts = split(item, LISTSEP)
385385 let assetId = parts[0]
386386 let share = parseIntValue(parts[1])
387387 let price = parseIntValue(parts[2])
388388 let reserv = parseIntValue(parts[3])
389389 if ((neutrinoSupply == 0))
390390 then throw("Attempt to burn neutrino at zero supply")
391391 else {
392392 let outAmount = fraction(amount, reserv, neutrinoSupply)
393393 let wavesTuple = if ((assetId == "WAVES"))
394394 then $Tuple2(outAmount, price)
395395 else $Tuple2(acc._2, acc._3)
396396 $Tuple3((acc._1 :+ $Tuple4(assetId, outAmount, price, share)), wavesTuple._1, wavesTuple._2)
397397 }
398398 }
399399
400400 let $l = basketInfo
401401 let $s = size($l)
402402 let $acc0 = $Tuple3(nil, 0, 0)
403403 func $f0_1 ($a,$i) = if (($i >= $s))
404404 then $a
405405 else conv($a, $l[$i])
406406
407407 func $f0_2 ($a,$i) = if (($i >= $s))
408408 then $a
409409 else throw("List size exceeds 10")
410410
411411 $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)
412412 }
413413
414414
415415 func minSwapAmountFAIL (swapType,minSwapAmount) = throw(((("The specified amount in " + swapType) + " swap is less than the required minimum of ") + toString(minSwapAmount)))
416416
417417
418418 func emergencyShutdownFAIL () = throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
419419
420420
421421 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)))
422422
423423
424424 let neutrinoAssetId = fromBase58String(getStringByKey(NeutrinoAssetIdKey))
425425
426426 let priceIndex = getNumberByAddressAndKey(controlContract, PriceIndexKey)
427427
428428 let isBlocked = getBoolByAddressAndKey(controlContract, IsBlockedKey)
429429
430430 let nodeOracleProviderPubKey = fromBase58String(getStringByKey(NodeOracleProviderPubKeyKey))
431431
432432 let bondAssetId = fromBase58String("F3iaxzruFeKujfVfYSZEkejpjh67wmRfPCRHiNmWKp3Z")
433433
434434 let deprecatedBondAssetId = fromBase58String("975akZBfnMj513U7MZaHKzQrmsEx5aE3wdWKTrHBhbjF")
435435
436436 let neutrinoContract = this
437437
438438 let currentPrice = getNumberByAddressAndKey(controlContract, PriceKey)
439439
440440 func checkIsValidMinSponsoredFee (tx) = {
441441 let MINTRANSFERFEE = 100000
442442 let SponsoredFeeUpperBound = 1000
443443 let realNeutrinoFee = convertTokenToUsd(MINTRANSFERFEE, currentPrice)
444444 let minNeutrinoFee = (realNeutrinoFee * 2)
445445 let maxNeutrinoFee = fraction(realNeutrinoFee, SponsoredFeeUpperBound, 100)
446446 let inputFee = value(tx.minSponsoredAssetFee)
447447 if (if ((inputFee >= minNeutrinoFee))
448448 then (maxNeutrinoFee >= inputFee)
449449 else false)
450450 then (tx.assetId == neutrinoAssetId)
451451 else false
452452 }
453453
454454
455455 func getPriceHistory (block) = getNumberByAddressAndKey(controlContract, getPriceHistoryKey(block))
456456
457457
458458 func getHeightPriceByIndex (index) = getNumberByAddressAndKey(controlContract, getHeightPriceByIndexKey(index))
459459
460460
461461 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", userAddress, "amount"], SEP)
462462
463463
464464 let sIdxSwapType = 1
465465
466466 let sIdxStatus = 2
467467
468468 let sIdxInAmount = 3
469469
470470 let sIdxStartHeight = 7
471471
472472 let sIdxStartTimestamp = 8
473473
474474 let sIdxSelfUnlockHeight = 11
475475
476476 let sIdxMinRand = 15
477477
478478 let sIdxMaxRand = 16
479479
480480 let sIdxInAsset = 20
481481
482482 func swapKEY (userAddress,txId) = makeString(["%s%s", userAddress, txId], SEP)
483483
484484
485485 func strSwapDATA (swapType,status,inAmount,price,outNetAmount,outFeeAmount,startHeight,startTimestamp,endHeight,endTimestamp,selfUnlockHeight,randUnlockHeight,index,withdrawTxId,randMin,randMax,outSurfAmt,br,basketData,inAsset) = makeString_2C(["%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)
486486
487487
488488 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)
489489
490490
491491 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)
492492
493493
494494 func swapDataFailOrREAD (userAddress,swapTxId) = {
495495 let swapKey = swapKEY(userAddress, swapTxId)
496496 split_4C(valueOrErrorMessage(getString(swapKey), ("no swap data for " + swapKey)), SEP)
497497 }
498498
499499
500500 func applyFees (amountOutGross,inAmtToSURF,feePart) = {
501501 let feeAmount = fraction(amountOutGross, feePart, MULT6)
502502 [(amountOutGross - feeAmount), feeAmount]
503503 }
504504
505505
506506 func applyFeesBasket (basketOut) = {
507507 let k6 = value(getInteger(basketKKey()))
508508 let d6 = value(getInteger(basketDKey()))
509509 let feePart = fraction(k6, d6, MULT6)
510510 func feeApplier (acc,item) = {
511511 let feeAmount = fraction(item._2, feePart, MULT6)
512512 (acc :+ makeString([item._1, toString(item._3), toString((item._2 - feeAmount)), toString(feeAmount), toString(item._4)], LISTSEP))
513513 }
514514
515515 let a = {
516516 let $l = basketOut
517517 let $s = size($l)
518518 let $acc0 = nil
519519 func $f0_1 ($a,$i) = if (($i >= $s))
520520 then $a
521521 else feeApplier($a, $l[$i])
522522
523523 func $f0_2 ($a,$i) = if (($i >= $s))
524524 then $a
525525 else throw("List size exceeds 10")
526526
527527 $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)
528528 }
529529 makeString_2C(a, "_")
530530 }
531531
532532
533533 func abs (x) = if ((0 > x))
534534 then -(x)
535535 else x
536536
537537
538538 func selectNode (unleaseAmount) = {
539539 let amountToLease = ((wavesBalance(neutrinoContract).available - unleaseAmount) - getReservedAmountForSponsorship())
540540 let oldLeased0 = getNumberByKey(getLeaseAmountKey(0))
541541 let oldLeased1 = getNumberByKey(getLeaseAmountKey(1))
542542 let newLeased0 = (amountToLease + oldLeased0)
543543 let newLeased1 = (amountToLease + oldLeased1)
544544 if (if ((newLeased0 > 0))
545545 then true
546546 else (newLeased1 > 0))
547547 then {
548548 let delta0 = abs((newLeased0 - oldLeased1))
549549 let delta1 = abs((newLeased1 - oldLeased0))
550550 if ((delta1 >= delta0))
551551 then $Tuple2(0, newLeased0)
552552 else $Tuple2(1, newLeased1)
553553 }
554554 else $Tuple2(-1, 0)
555555 }
556556
557557
558558 func thisOnly (i) = if ((i.caller != this))
559559 then throw("Permission denied: this contract only allowed")
560560 else true
561561
562562
563563 func prepareUnleaseAndLease (unleaseAmount) = {
564564 let nodeTuple = selectNode(unleaseAmount)
565565 let nodeIndex = nodeTuple._1
566566 let newLeaseAmount = nodeTuple._2
567567 if ((newLeaseAmount > 0))
568568 then {
569569 let leaseIdKey = getLeaseIdKey(nodeIndex)
570570 let oldLease = getBinary(this, leaseIdKey)
571571 let unleaseOrEmpty = if (isDefined(oldLease))
572572 then [LeaseCancel(value(oldLease))]
573573 else nil
574574 let leaseAmountKey = getLeaseAmountKey(nodeIndex)
575575 let lease = Lease(getStakingNodeAddressByIndex(nodeIndex), newLeaseAmount)
576576 (unleaseOrEmpty ++ [lease, BinaryEntry(leaseIdKey, lcalc(lease)), IntegerEntry(getLeaseAmountKey(nodeIndex), newLeaseAmount)])
577577 }
578578 else nil
579579 }
580580
581581
582582 func readNodeInfo (nodeIdx) = {
583583 let nodeAddress = getStakingNodeAddressByIndex(nodeIdx)
584584 let leasedAmtKEY = getLeaseAmountKey(nodeIdx)
585585 let leasedAmt = getNumberByKey(leasedAmtKEY)
586586 let leaseIdKEY = getLeaseIdKey(nodeIdx)
587587 let leaseId = value(getBinary(this, leaseIdKEY))
588588 $Tuple5(nodeAddress, leasedAmtKEY, leasedAmt, leaseIdKEY, leaseId)
589589 }
590590
591591
592592 func commonSwap (swapType,pmtAmount,inAsset,userAddressStr,txId58) = {
593593 let swapParamsSTRUCT = asSwapParamsSTRUCT(invoke(this, "swapParamsByUserSYSREADONLY", [userAddressStr, 0], nil))
594594 let tokenSwapLimitUsd = swapParamsSTRUCT._1
595595 let swapLimitSpent = swapParamsSTRUCT._2
596596 let blcks2LmtReset = swapParamsSTRUCT._3
597597 let usdnSwapLimitMax = swapParamsSTRUCT._7
598598 let minSwapAmount = minSwapAmountREAD(swapType, inAsset)
599599 let totalLockedByUser = totalLockedByUserREAD(swapType, userAddressStr, inAsset)
600600 let nodeAddress = getStakingNodeByIndex(0)
601601 let isSwapByNode = (nodeAddress == userAddressStr)
602602 let balanceLockMaxInterval = if (isSwapByNode)
603603 then nodeBalanceLockIntervalREAD()
604604 else balanceLockIntervalREAD(swapType)
605605 let selfUnlockHeight = (height + balanceLockMaxInterval)
606606 let pr = value(getInteger(controlContract, keyPriceByAsset(inAsset)))
607607 let swapUsdnVolume = if ((swapType == "outNeutrino"))
608608 then convertTokenToUsd(pmtAmount, pr)
609609 else pmtAmount
610610 let swapLimitMax = if ((swapType == "outNeutrino"))
611611 then tokenSwapLimitUsd
612612 else usdnSwapLimitMax
613613 if ((minSwapAmount > pmtAmount))
614614 then minSwapAmountFAIL(swapType, minSwapAmount)
615615 else if (if (!(isSwapByNode))
616616 then (swapLimitSpent > 0)
617617 else false)
618618 then throw(("You have exceeded swap limit! Next allowed swap height is " + toString((height + blcks2LmtReset))))
619619 else if (if (!(isSwapByNode))
620620 then (swapUsdnVolume > swapLimitMax)
621621 else false)
622622 then throw(((("You have exceeded your swap limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(swapLimitMax)))
623623 else if (isBlocked)
624624 then emergencyShutdownFAIL()
625625 else {
626626 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
627627 let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
628628 let weightedPrice = asInt(neutrinoMetrics[nMetricWeightedPrice])
629629 let out = convertBasketItemToNeutrino(pmtAmount, inAsset, basketInfo, weightedPrice)
630630 if (if ((swapType == "outNeutrino"))
631631 then (0 >= out[1])
632632 else false)
633633 then throw((((((("Net amount is non-positive, cannot swap. (gross, net, fee) = (" + toString(out[0])) + ", ") + toString(out[1])) + ", ") + toString(out[2])) + ")"))
634634 else {
635635 let leasePart = if (if ((swapType == "outNeutrino"))
636636 then (inAsset == "WAVES")
637637 else false)
638638 then prepareUnleaseAndLease(0)
639639 else nil
640640 $Tuple2(([IntegerEntry(keySwapUserSpentInPeriod(userAddressStr), swapUsdnVolume), IntegerEntry(keyUserLastSwapHeight(userAddressStr), height), IntegerEntry(totalLockedByUserKEY(swapType, userAddressStr, inAsset), (totalLockedByUser + pmtAmount)), IntegerEntry(getBalanceUnlockBlockKey(userAddressStr), selfUnlockHeight), StringEntry(swapKEY(userAddressStr, txId58), pendingSwapDATA(swapType, pmtAmount, selfUnlockHeight, inAsset))] ++ leasePart), unit)
641641 }
642642 }
643643 }
644644
645645
646646 let bFuncIdxSurf = 0
647647
648648 let bFuncIdxWaves = 1
649649
650650 let bFuncIdxUsdn = 2
651651
652652 let bFuncIdxReserveStart = 3
653653
654654 let bFuncIdxSupplyStart = 4
655655
656656 let bFuncIdxBRStart = 5
657657
658658 let bFuncIdxReserveEnd = 6
659659
660660 let bFuncIdxSupplyEnd = 7
661661
662662 let bFuncIdxBREnd = 8
663663
664664 let bFuncIdxRest = 9
665665
666666 let bFuncIdxWavesPrice = 10
667667
668668 func calcWithdrawT2U (inAmount,inAsset,basketInfo,weightedPrice) = {
669669 let outAmt = convertBasketItemToNeutrino(inAmount, inAsset, basketInfo, weightedPrice)
670670 $Tuple12(outAmt[0], neutrinoAssetId, 0, inAsset, 0, weightedPrice, inAmount, 0, 0, 0, nil, [outAmt[1], outAmt[2]])
671671 }
672672
673673
674674 func calcWithdrawU2Basket (usdnIn,basketInfo,neutrinoSupply) = {
675675 let outAmtGross = convertNeutrinoToBasket(usdnIn, basketInfo, neutrinoSupply)
676676 $Tuple12(outAmtGross._2, unit, 0, neutrinoAssetId, outAmtGross._2, outAmtGross._3, usdnIn, neutrinoSupply, usdnIn, 0, outAmtGross._1, nil)
677677 }
678678
679679
680680 func calcWithdraw (swapType,inAmount,price,neutrinoMetrics,inAsset) = {
681681 let neutrinoSupply = asInt(neutrinoMetrics[nMetricIdxUsdnSupply])
682682 let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
683683 let weightedPrice = asInt(neutrinoMetrics[nMetricWeightedPrice])
684684 let outDataTuple = if ((swapType == "outNeutrino"))
685685 then calcWithdrawT2U(inAmount, inAsset, basketInfo, weightedPrice)
686686 else if ((swapType == "outMulti"))
687687 then calcWithdrawU2Basket(inAmount, basketInfo, neutrinoSupply)
688688 else throw(("Unsupported swap type " + swapType))
689689 let outAmtGross = outDataTuple._1
690690 let outAssetId = outDataTuple._2
691691 let inAmtToSurfPart = outDataTuple._3
692692 let inAssetId = outDataTuple._4
693693 let unleaseAmt = outDataTuple._5
694694 let withdrawPrice = outDataTuple._6
695695 let basketData = outDataTuple._11
696696 let netFeeData = outDataTuple._12
697697 let outNetAmt = if ((swapType == "outNeutrino"))
698698 then netFeeData[0]
699699 else 0
700700 let outFeeAmt = if ((swapType == "outNeutrino"))
701701 then netFeeData[1]
702702 else 0
703703 let outSurfAmt = if ((0 >= inAmtToSurfPart))
704704 then 0
705705 else asInt(asAnyList(invoke(mathContract, "surfFunctionREADONLY", [inAmtToSurfPart, inAssetId], nil))[bFuncIdxSurf])
706706 let withdrawBasket = if ((swapType == "outMulti"))
707707 then applyFeesBasket(basketData)
708708 else ""
709709 $Tuple9(outNetAmt, outAssetId, outSurfAmt, inAmtToSurfPart, unleaseAmt, outFeeAmt, outAmtGross, withdrawPrice, withdrawBasket)
710710 }
711711
712712
713713 func keyApplyInProgress () = "%s__applyInProgress"
714714
715715
716716 func keyProposalDataById (proposalId) = ("%s%d__proposalData__" + toString(proposalId))
717717
718718
719719 let govIdxTxIds = 9
720720
721721 func validateUpdate (tx) = match tx {
722722 case o: Order =>
723723 throw("Orders aren't allowed")
724724 case t: DataTransaction|SponsorFeeTransaction|SetScriptTransaction|CreateAliasTransaction|LeaseCancelTransaction|LeaseTransaction|IssueTransaction|InvokeExpressionTransaction|UpdateAssetInfoTransaction|InvokeScriptTransaction|SetAssetScriptTransaction|TransferTransaction|ExchangeTransaction|MassTransferTransaction|BurnTransaction|ReissueTransaction =>
725725 let txId = toBase58String(t.id)
726726 let proposalId = valueOrErrorMessage(getInteger(govContract, keyApplyInProgress()), "Apply is not happening")
727727 let txList = split(split(getStringOrFail(govContract, keyProposalDataById(proposalId)), SEP)[govIdxTxIds], LISTSEP)
728728 if (!(isDefined(indexOf(txList, txId))))
729729 then throw(((("Unknown txId: " + txId) + " for proposalId=") + toString(proposalId)))
730730 else true
731731 case _ =>
732732 throw("Match error")
733733 }
734734
735735
736736 @Callable(i)
737737 func constructorV1 (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,nodeOracleProviderPubKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
738738 let checkCaller = thisOnly(i)
739739 if ((checkCaller == checkCaller))
740740 then if ((size(i.payments) != 0))
741741 then throw("no payments allowed")
742742 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)]
743743 else throw("Strict value is not equal to itself.")
744744 }
745745
746746
747747
748748 @Callable(i)
749749 func constructorV2 (mathContract,nsbtStakingContract,swapsTimeframeBlocks) = {
750750 let checkCaller = thisOnly(i)
751751 if ((checkCaller == checkCaller))
752752 then if ((size(i.payments) != 0))
753753 then throw("no payments allowed")
754754 else [StringEntry(MathContractKey, mathContract), StringEntry(NsbtStakingContractKey, nsbtStakingContract), IntegerEntry(swapsTimeframeKEY(), swapsTimeframeBlocks)]
755755 else throw("Strict value is not equal to itself.")
756756 }
757757
758758
759759
760760 @Callable(i)
761761 func constructorV3 (assetsWeightsMins,dParam,kParam,bParam,deltaParam) = {
762762 let checkCaller = thisOnly(i)
763763 if ((checkCaller == checkCaller))
764764 then if ((size(i.payments) != 0))
765765 then throw("no payments allowed")
766766 else {
767767 func prepare (acc,item) = {
768768 let parts = split(item, "_")
769769 let assetId = parts[0]
770770 let weight = parseIntValue(parts[1])
771771 let minVal = parseIntValue(parts[2])
772772 $Tuple2((acc._1 :+ assetId), ((acc._2 :+ IntegerEntry(basketWeightByAssetKey(assetId), weight)) :+ IntegerEntry(MinTokenSwapAmountKey(assetId), minVal)))
773773 }
774774
775775 let r = {
776776 let $l = assetsWeightsMins
777777 let $s = size($l)
778778 let $acc0 = $Tuple2(nil, nil)
779779 func $f0_1 ($a,$i) = if (($i >= $s))
780780 then $a
781781 else prepare($a, $l[$i])
782782
783783 func $f0_2 ($a,$i) = if (($i >= $s))
784784 then $a
785785 else throw("List size exceeds 10")
786786
787787 $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)
788788 }
789789 (((((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)))
790790 }
791791 else throw("Strict value is not equal to itself.")
792792 }
793793
794794
795795
796796 @Callable(i)
797797 func swapTokenToNeutrino () = if ((size(i.payments) != 1))
798798 then throw("swapTokenToNeutrino require only one payment")
799799 else {
800800 let pmt = value(i.payments[0])
801801 let basketAssets = value(getString(basketAssetsKey()))
802802 let pmtAssetIdStr = toBase58String(valueOrElse(pmt.assetId, WAVESID))
803803 if (!(contains(basketAssets, pmtAssetIdStr)))
804804 then throw(((pmtAssetIdStr + " is not one of basket tokens:") + basketAssets))
805805 else {
806806 let userAddress = toString(i.caller)
807807 let txId58 = toBase58String(i.transactionId)
808808 let totalLocked = totalLockedREAD("outNeutrino", pmtAssetIdStr)
809809 let pmtAmount = pmt.amount
810810 let saveTotalLocked = invoke(this, "internalSaveInteger", [totalLockedKEY("outNeutrino", pmtAssetIdStr), (totalLocked + pmtAmount)], nil)
811811 if ((saveTotalLocked == saveTotalLocked))
812812 then commonSwap("outNeutrino", pmtAmount, pmtAssetIdStr, userAddress, txId58)
813813 else throw("Strict value is not equal to itself.")
814814 }
815815 }
816816
817817
818818
819819 @Callable(i)
820820 func swapNeutrinoToBasket () = if ((size(i.payments) != 1))
821821 then throw("swapNeutrinoToBasket require only one payment")
822822 else {
823823 let pmt = value(i.payments[0])
824824 if ((pmt.assetId != neutrinoAssetId))
825825 then throw("Only appropriate Neutrino tokens are allowed for swapping.")
826826 else {
827827 let userAddress = toString(i.caller)
828828 let txId58 = toBase58String(i.transactionId)
829829 let neutrinoAssetIdStr = toBase58String(neutrinoAssetId)
830830 let totalLocked = totalLockedREAD("outMulti", neutrinoAssetIdStr)
831831 let pmtAmount = pmt.amount
832832 let saveTotalLocked = invoke(this, "internalSaveInteger", [totalLockedKEY("outMulti", neutrinoAssetIdStr), (totalLocked + pmtAmount)], nil)
833833 if ((saveTotalLocked == saveTotalLocked))
834834 then commonSwap("outMulti", pmt.amount, neutrinoAssetIdStr, userAddress, txId58)
835835 else throw("Strict value is not equal to itself.")
836836 }
837837 }
838838
839839
840840
841841 @Callable(i)
842842 func internalSaveInteger (key,amount) = if ((i.caller != this))
843843 then throw("internalSaveInteger is not public method")
844844 else [IntegerEntry(key, amount)]
845845
846846
847847
848848 @Callable(i)
849849 func withdraw (account,index,swapTxId) = {
850850 let txId = toBase58String(i.transactionId)
851851 if ((size(i.payments) != 0))
852852 then throw("no payments allowed")
853853 else {
854854 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
855855 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
856856 let userAddress = addressFromStringValue(account)
857857 let dataArray = swapDataFailOrREAD(account, swapTxId)
858858 let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
859859 let swapType = dataArray[sIdxSwapType]
860860 let inAmount = parseIntValue(dataArray[sIdxInAmount])
861861 let swapStatus = dataArray[sIdxStatus]
862862 let startHeight = parseIntValue(dataArray[sIdxStartHeight])
863863 let inAsset = dataArray[sIdxInAsset]
864864 let totalLocked = totalLockedREAD(swapType, inAsset)
865865 let totalLockedByUser = totalLockedByUserREAD(swapType, account, inAsset)
866866 let unlockHeight = selfUnlockHeight
867867 let indexHeight = getHeightPriceByIndex(index)
868868 let prevIndexHeight = getHeightPriceByIndex((index - 1))
869869 let priceByIndex = getPriceHistory(indexHeight)
870870 if (isBlocked)
871871 then emergencyShutdownFAIL()
872872 else if ((swapStatus != "PENDING"))
873873 then throw("swap has been already processed")
874874 else if ((unlockHeight > height))
875875 then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
876876 else if (if (if ((index > priceIndex))
877877 then true
878878 else (unlockHeight > indexHeight))
879879 then true
880880 else if ((prevIndexHeight != 0))
881881 then (prevIndexHeight >= unlockHeight)
882882 else false)
883883 then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
884884 else {
885885 let withdrawTuple = calcWithdraw(swapType, inAmount, priceByIndex, neutrinoMetrics, inAsset)
886886 let outNetAmount = withdrawTuple._1
887887 let outAssetId = withdrawTuple._2
888888 let outSurfAmt = withdrawTuple._3
889889 let unleaseAmt = withdrawTuple._5
890890 let outFeeAmount = withdrawTuple._6
891891 let outAmtGross = withdrawTuple._7
892892 let withdrawPrice = withdrawTuple._8
893893 let withdrawBasket = withdrawTuple._9
894894 if (if ((swapType == "outNeutrino"))
895895 then (0 >= outAmtGross)
896896 else false)
897897 then throw("balance equals zero")
898898 else {
899899 let surfCondition = if ((outSurfAmt > 0))
900900 then {
901901 let issueResult = invoke(auctionContract, "issueSurf", [outSurfAmt, account], nil)
902902 if ((issueResult == issueResult))
903903 then 0
904904 else throw("Strict value is not equal to itself.")
905905 }
906906 else 0
907907 if ((surfCondition == surfCondition))
908908 then {
909909 let unleaseInvOrEmpty = invoke(this, "internalUnleaseAndLease", [unleaseAmt], nil)
910910 if ((unleaseInvOrEmpty == unleaseInvOrEmpty))
911911 then {
912912 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", ["", 0, 0], nil))
913913 let gnsbtAmtTotal = asInt(gnsbtData[1])
914914 let gnsbtAmtFromSurfTotal = asInt(asAnyList(gnsbtData[3])[3])
915915 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))]
916916 func deposits (surfFees,nsbtFees,surfPayments,nsbtPayments) = {
917917 let surfDeposit = if ((surfFees > 0))
918918 then asInt(invoke(surfStakingContract, "deposit", nil, surfPayments))
919919 else 0
920920 let nsbtDeposit = if ((nsbtFees > 0))
921921 then asInt(invoke(nsbtStakingContract, "deposit", nil, nsbtPayments))
922922 else 0
923923 (surfDeposit + nsbtDeposit)
924924 }
925925
926926 func divideFees (feeAmount) = {
927927 let surfAmt1 = if ((gnsbtAmtTotal != 0))
928928 then fraction(feeAmount, gnsbtAmtFromSurfTotal, gnsbtAmtTotal)
929929 else 0
930930 let surfAmt2 = if ((gnsbtAmtTotal != 0))
931931 then fraction(feeAmount, (MULT6 - BR), MULT6)
932932 else 0
933933 let surfAmt = max([surfAmt1, surfAmt2])
934934 let nsbtAmt = (feeAmount - surfAmt)
935935 [surfAmt, nsbtAmt]
936936 }
937937
938938 let transfers = if ((swapType == "outMulti"))
939939 then {
940940 let basket = split_4C(withdrawBasket, "_")
941941 func looper (acc,item) = {
942942 let it = split(item, LISTSEP)
943943 let tempAssetId = fromBase58String(it[0])
944944 let assetId = if ((tempAssetId == WAVESID))
945945 then unit
946946 else tempAssetId
947947 let netAmount = parseIntValue(it[2])
948948 let feeAmount = parseIntValue(it[3])
949949 let fees = divideFees(feeAmount)
950950 $Tuple5((acc._1 :+ ScriptTransfer(userAddress, netAmount, assetId)), (acc._2 :+ AttachedPayment(assetId, fees[0])), (acc._3 :+ AttachedPayment(assetId, fees[1])), (acc._4 + fees[0]), (acc._5 + fees[1]))
951951 }
952952
953953 let r = {
954954 let $l = basket
955955 let $s = size($l)
956956 let $acc0 = $Tuple5(nil, nil, nil, 0, 0)
957957 func $f0_1 ($a,$i) = if (($i >= $s))
958958 then $a
959959 else looper($a, $l[$i])
960960
961961 func $f0_2 ($a,$i) = if (($i >= $s))
962962 then $a
963963 else throw("List size exceeds 10")
964964
965965 $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)
966966 }
967967 let depoResult = deposits(r._4, r._5, r._2, r._3)
968968 $Tuple2(r._1, depoResult)
969969 }
970970 else {
971971 let fees = divideFees(outFeeAmount)
972972 let depoResult = deposits(fees[0], fees[1], [AttachedPayment(outAssetId, fees[0])], [AttachedPayment(outAssetId, fees[1])])
973973 $Tuple2([ScriptTransfer(userAddress, outNetAmount, outAssetId)], depoResult)
974974 }
975975 $Tuple2((commonActions ++ transfers._1), transfers._2)
976976 }
977977 else throw("Strict value is not equal to itself.")
978978 }
979979 else throw("Strict value is not equal to itself.")
980980 }
981981 }
982982 }
983983 }
984984
985985
986986
987987 @Callable(i)
988988 func internalUnleaseAndLease (unleaseAmount) = if ((i.caller != this))
989989 then throw("internalUnleaseAndLease is not public method")
990990 else prepareUnleaseAndLease(unleaseAmount)
991991
992992
993993
994994 @Callable(i)
995995 func transferUsdnToUser (amount,addr) = if ((i.caller != auctionContract))
996996 then throw("Only auction contract is authorized")
997997 else [ScriptTransfer(addressFromStringValue(addr), amount, neutrinoAssetId)]
998998
999999
10001000
10011001 @Callable(i)
10021002 func acceptWaves () = if (if ((i.caller != auctionContract))
10031003 then (i.caller != govContract)
10041004 else false)
10051005 then throw("Currently only auction and governance contracts are allowed to call")
10061006 else $Tuple2(prepareUnleaseAndLease(0), "success")
10071007
10081008
10091009
10101010 @Callable(i)
10111011 func approveLeasings (nListS,groupNum,lAmt) = {
10121012 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
10131013 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
10141014 let mngPub = fromBase58String(mngPubS)
10151015 let nodeRegAddrStr = valueOrElse(getString("%s%s__cfg__nodesRegistryAddress"), "3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE")
10161016 let nodeRegAddr = addressFromStringValue(nodeRegAddrStr)
10171017 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
10181018 let lGrNodeOpt = getString(this, lGroupNodeListKEY)
10191019 if (isDefined(lGrNodeOpt))
10201020 then throw((("group " + toString(groupNum)) + " already initialized"))
10211021 else {
10221022 let nList = split(nListS, SEP)
10231023 let expCount = size(nIdxs)
10241024 if ((i.callerPublicKey != mngPub))
10251025 then throw("approveLeasings not authorized")
10261026 else {
10271027 let $t04442544487 = readNodeInfo(0)
10281028 let nAddr0 = $t04442544487._1
10291029 let lAmtKEY0 = $t04442544487._2
10301030 let lAmt0 = $t04442544487._3
10311031 let lIdKEY0 = $t04442544487._4
10321032 let lId0 = $t04442544487._5
10331033 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
10341034 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
10351035 if ((validation == validation))
10361036 then {
10371037 func forEachNodeValidateAndGenerateLease (a,i) = {
10381038 let node = nList[i]
10391039 let la = Lease(addressFromStringValue(node), lAmt)
10401040 (a ++ [la, BinaryEntry(getLeaseIdByAddressKey(node), lcalc(la)), IntegerEntry(getLeaseAmountByAddressKey(node), lAmt)])
10411041 }
10421042
10431043 ([StringEntry(lGroupNodeListKEY, nListS), BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0] ++ {
10441044 let $l = nIdxs
10451045 let $s = size($l)
10461046 let $acc0 = nil
10471047 func $f0_1 ($a,$i) = if (($i >= $s))
10481048 then $a
10491049 else forEachNodeValidateAndGenerateLease($a, $l[$i])
10501050
10511051 func $f0_2 ($a,$i) = if (($i >= $s))
10521052 then $a
10531053 else throw("List size exceeds 8")
10541054
10551055 $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)
10561056 })
10571057 }
10581058 else throw("Strict value is not equal to itself.")
10591059 }
10601060 }
10611061 }
10621062
10631063
10641064
10651065 @Callable(i)
10661066 func rebalanceLeasings (amount,groupNum) = {
10671067 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
10681068 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
10691069 let mngPub = fromBase58String(mngPubS)
10701070 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
10711071 let nListS = getStringOrFail(this, lGroupNodeListKEY)
10721072 let nList = split(nListS, SEP)
10731073 if ((i.callerPublicKey != mngPub))
10741074 then throw("rebalanceLeasings not authorized")
10751075 else {
10761076 let unleaseAmt = ((amount / size(nList)) + 1)
10771077 let $t04572745789 = readNodeInfo(0)
10781078 let nAddr0 = $t04572745789._1
10791079 let lAmtKEY0 = $t04572745789._2
10801080 let lAmt0 = $t04572745789._3
10811081 let lIdKEY0 = $t04572745789._4
10821082 let lId0 = $t04572745789._5
10831083 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
10841084 func forEachNodeDoUnlease (a,i) = {
10851085 let node = nList[i]
10861086 let lIdKEY = getLeaseIdByAddressKey(node)
10871087 let lId = getBinaryValue(this, lIdKEY)
10881088 let lAmtKEY = getLeaseAmountByAddressKey(node)
10891089 let lAmt = getIntegerValue(this, lAmtKEY)
10901090 let ula = LeaseCancel(value(lId))
10911091 let la = Lease(addressFromStringValue(node), (lAmt - unleaseAmt))
10921092 (a ++ [LeaseCancel(value(lId)), la, BinaryEntry(lIdKEY, lcalc(la)), IntegerEntry(lAmtKEY, la.amount)])
10931093 }
10941094
10951095 ({
10961096 let $l = nIdxs
10971097 let $s = size($l)
10981098 let $acc0 = nil
10991099 func $f0_1 ($a,$i) = if (($i >= $s))
11001100 then $a
11011101 else forEachNodeDoUnlease($a, $l[$i])
11021102
11031103 func $f0_2 ($a,$i) = if (($i >= $s))
11041104 then $a
11051105 else throw("List size exceeds 8")
11061106
11071107 $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)
11081108 } ++ [BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0])
11091109 }
11101110 }
11111111
11121112
11131113
11141114 @Callable(i)
11151115 func swapParamsByUserSYSREADONLY (userAddressStr,gnsbtDiff) = {
11161116 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStr, 0, 0], nil))
11171117 let gnsbtAmt = (asInt(gnsbtData[0]) + gnsbtDiff)
11181118 let gnsbtAmtTotal = (asInt(gnsbtData[1]) + gnsbtDiff)
11191119 let swapLimitData = asAnyList(invoke(mathContract, "calcSwapLimitREADONLY", [gnsbtAmt], nil))
11201120 let tokenSwapLimitInUsdMax = asInt(swapLimitData[0])
11211121 let usdnSwapLimitMax = asInt(swapLimitData[2])
11221122 let lastSwapHeight = valueOrElse(getInteger(this, keyUserLastSwapHeight(userAddressStr)), 0)
11231123 let swapLimitTimelifeBlocks = swapsTimeframeREAD()
11241124 let passedBlocksAfterLastSwap = (height - lastSwapHeight)
11251125 let isSwapTimelifeNew = (passedBlocksAfterLastSwap >= swapLimitTimelifeBlocks)
11261126 let swapLimitSpentInUsdn = if (isSwapTimelifeNew)
11271127 then 0
11281128 else valueOrElse(getInteger(this, keySwapUserSpentInPeriod(userAddressStr)), 0)
11291129 let blcks2LmtReset = if (isSwapTimelifeNew)
11301130 then 0
11311131 else (swapLimitTimelifeBlocks - passedBlocksAfterLastSwap)
11321132 $Tuple2(nil, $Tuple7(tokenSwapLimitInUsdMax, swapLimitSpentInUsdn, blcks2LmtReset, gnsbtAmt, gnsbtAmtTotal, 0, usdnSwapLimitMax))
11331133 }
11341134
11351135
11361136
11371137 @Callable(i)
11381138 func calcWithdrawResultSYSREADONLY (swapType,inAmount,price,inAsset) = {
11391139 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
11401140 $Tuple2(nil, calcWithdraw(swapType, inAmount, price, neutrinoMetrics, inAsset))
11411141 }
11421142
11431143
11441144
11451145 @Callable(i)
11461146 func replaceCommunityNode (oldAddrStr,newAddrStr,groupNum,penaltyAmount) = {
11471147 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
11481148 let mngPub = fromBase58String(mngPubS)
11491149 if ((i.callerPublicKey != mngPub))
11501150 then throw("replaceCommunityNode not authorized")
11511151 else {
11521152 let groupKey = getLeaseGroupNodeListKey(groupNum)
11531153 let groupNodeListS = getStringOrFail(this, groupKey)
11541154 if (!(contains(groupNodeListS, oldAddrStr)))
11551155 then throw(((("Group " + toString(groupNum)) + " does not contain address ") + oldAddrStr))
11561156 else {
11571157 let doReplace = invoke(nodeRegistryContract, "replaceApprovedNode", [oldAddrStr, newAddrStr, groupNum, penaltyAmount], nil)
11581158 if ((doReplace == doReplace))
11591159 then {
11601160 let oldLeaseIdKey = getLeaseIdByAddressKey(oldAddrStr)
11611161 let oldLeaseAmtKey = getLeaseAmountByAddressKey(oldAddrStr)
11621162 let leaseAmt = getIntegerValue(oldLeaseAmtKey)
11631163 let newLeaseIdKey = getLeaseIdByAddressKey(newAddrStr)
11641164 let newLeaseAmtKey = getLeaseAmountByAddressKey(newAddrStr)
11651165 let newLease = Lease(addressFromStringValue(newAddrStr), leaseAmt)
11661166 let updatedGroupNodeListS = makeString(split(groupNodeListS, oldAddrStr), newAddrStr)
11671167 $Tuple2([LeaseCancel(getBinaryValue(oldLeaseIdKey)), DeleteEntry(oldLeaseIdKey), DeleteEntry(oldLeaseAmtKey), StringEntry(groupKey, updatedGroupNodeListS), newLease, BinaryEntry(newLeaseIdKey, lcalc(newLease)), IntegerEntry(newLeaseAmtKey, leaseAmt)], unit)
11681168 }
11691169 else throw("Strict value is not equal to itself.")
11701170 }
11711171 }
11721172 }
11731173
11741174
11751175 @Verifier(tx)
11761176 func verify () = {
11771177 let pubKeyAdminsListStr = makeString(["ExtEEK19nmKj9mCpnWyvEEJFYATLMcVEMvohhUHkyHNm", "Ev5py5FfBQX9cZpYKnfQrTB49Byf8QmpZWeDVRim4yV7", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR"], SEP)
11781178 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
11791179 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
11801180 then 1
11811181 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
11821182 then 1
11831183 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
11841184 then 1
11851185 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
11861186 then 2
11871187 else 0))
11881188 if (if (isBlocked)
11891189 then (getStringValue(controlContract, "is_blocked_caller") == toString(govContract))
11901190 else false)
11911191 then validateUpdate(tx)
11921192 else match tx {
11931193 case sponsorTx: SponsorFeeTransaction =>
11941194 if (checkIsValidMinSponsoredFee(sponsorTx))
11951195 then (count >= 3)
11961196 else false
11971197 case _ =>
11981198 (count >= 3)
11991199 }
12001200 }
12011201

github/deemru/w8io/3ef1775 
124.86 ms