tx · 8TCFfKQLAwGuzxGWqdhH7ve1vNPzHnQQARZakHCEmBAe

3N9be2mwrA52WJho6DiesZkk4351GvpnWuj:  -0.04100000 Waves

2023.03.01 16:44 [2471076] smart account 3N9be2mwrA52WJho6DiesZkk4351GvpnWuj > SELF 0.00000000 Waves

{ "type": 13, "id": "8TCFfKQLAwGuzxGWqdhH7ve1vNPzHnQQARZakHCEmBAe", "fee": 4100000, "feeAssetId": null, "timestamp": 1677678250211, "version": 2, "chainId": 84, "sender": "3N9be2mwrA52WJho6DiesZkk4351GvpnWuj", "senderPublicKey": "6mzmbCza9iqbzxMEELcEA4Xc9NeF4CYpbTtz1zMK3C7x", "proofs": [ "2zwnjrB3JHNzS4cwrxEywLLkMCnYzLsWWGj3bb888dMP57esvvxsEJ1X4fEaSNrRvu7rRaT9wYQVqwFMuoPUS3ua", "63Ja3dNWAJ2iv3kLwxbuxHzCadHDTs7KVQKMfi2DCYahUCDGj6hv3u7kwUjrQXTvtLBWgPuQJMNavYnr5MNRGHft", "3jjbzvP6QJoGtm3Vo3wFKjckU2hYgndXTZpUmNQSrWeEaMJ4sGCZFDpwdgaewekvbHdaAJp2NM2iLYcQSZgpAgHu" ], "script": "base64:BgJjCAISDgoMCAgICAgIAQEBAQEBEgUKAwgIARIHCgUYAQEBARIAEgASBAoCCAESBQoDCAEIEgMKAQESBAoCAQgSABIFCgMIAQESBAoCAQESBAoCCAESBgoECAEBCBIGCgQICAEBswEBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUHYWRkcmVzcwkAzAgCAgEuCQDMCAIFA2tleQkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQVsY2FsYwEBbAkAuQgBBQFsAQ5nZXROdW1iZXJCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQ5nZXRTdHJpbmdCeUtleQEDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQIAAQxnZXRCb29sQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQNrZXkHARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFB2FkZHJlc3MFA2tleQAAARhnZXRTdHJpbmdCeUFkZHJlc3NBbmRLZXkCB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB2FkZHJlc3MFA2tleQIAARZnZXRCb29sQnlBZGRyZXNzQW5kS2V5AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAmwgCBQdhZGRyZXNzBQNrZXkHAQlhc0FueUxpc3QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAFsBQckbWF0Y2gwBQFsCQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBBWFzSW50AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACA0ludAQBaQUHJG1hdGNoMAUBaQkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEHYXNCeXRlcwEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQHdmFsQnl0ZQUHJG1hdGNoMAUHdmFsQnl0ZQkAAgECHGZhaWwgdG8gY2FzdCBpbnRvIEJ5dGVWZWN0b3IBCWFzUGF5bWVudAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAg9BdHRhY2hlZFBheW1lbnQEAXAFByRtYXRjaDAFAXAJAAIBAiFmYWlsIHRvIGNhc3QgaW50byBBdHRhY2hlZFBheW1lbnQBEmFzU3dhcFBhcmFtc1NUUlVDVAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAiMoSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50KQQGc3RydWN0BQckbWF0Y2gwBQZzdHJ1Y3QJAAIBAh1mYWlsIHRvIGNhc3QgaW50byBUdXBsZTUgaW50cwADU0VQAgJfXwAHTElTVFNFUAIBOgAFTVVMVDgAgMLXLwAFTVVMVDYAwIQ9AA5ERUZBVUxUU1dBUEZFRQCgnAEAC0JSUFJPVEVDVEVEAKCNBgAHV0FWRVNJRAEEE6vZMwAPbk1ldHJpY0lkeFByaWNlAAAAG25NZXRyaWNJZHhVc2RuTG9ja2VkQmFsYW5jZQABABxuTWV0cmljSWR4V2F2ZXNMb2NrZWRCYWxhbmNlAAIAEW5NZXRyaWNJZHhSZXNlcnZlAAMAF25NZXRyaWNJZHhSZXNlcnZlSW5Vc2RuAAQAFG5NZXRyaWNJZHhVc2RuU3VwcGx5AAUAEW5NZXRyaWNJZHhTdXJwbHVzAAYAGG5NZXRyaWNJZHhTdXJwbHVzUGVyY2VudAAHAAxuTWV0cmljSWR4QlIACAAUbk1ldHJpY0lkeE5zYnRTdXBwbHkACQAXbk1ldHJpY0lkeE1heE5zYnRTdXBwbHkACgAUbk1ldHJpY0lkeFN1cmZTdXBwbHkACwASbk1ldHJpY1VzZG5Vc2R0UGVnAAwAFm5NZXRyaWNDdXJyZW50UHJpY2VBZGoADQARbk1ldHJpY0Jhc2tldEluZm8ADgAUbk1ldHJpY1dlaWdodGVkUHJpY2UADwAXbk1ldHJpY1RvdGFsUmVzZXJ2ZXNVc2QAEAAZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAABABhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAAgAUSWR4Q29udHJvbENmZ1JwZERhcHAAAwAVSWR4Q29udHJvbENmZ01hdGhEYXBwAAQAHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAABQAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAYAHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAcAHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAACAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAJABxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwAAoAIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAAsAF0lkeENvbnRyb2xDZmdSZXN0VjJEYXBwAAwAG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAANARFrZXlDb250cm9sQWRkcmVzcwACHCVzJXNfX2NvbmZpZ19fY29udHJvbEFkZHJlc3MBDWtleUNvbnRyb2xDZmcAAhElc19fY29udHJvbENvbmZpZwEUcmVhZENvbnRyb2xDZmdPckZhaWwBB2NvbnRyb2wJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFB2NvbnRyb2wJAQ1rZXlDb250cm9sQ2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCCmNvbnRyb2xDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpjb250cm9sQ2ZnBQNpZHgJAKwCAgItQ29udHJvbCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAPY29udHJvbENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJARFrZXlDb250cm9sQWRkcmVzcwACIzNONE5TN2Q0Sm85YTZGMTRMaUZVS0tZVmRVa2tmMmVQNFp4AApjb250cm9sQ2ZnCQEUcmVhZENvbnRyb2xDZmdPckZhaWwBBQ9jb250cm9sQ29udHJhY3QADG1hdGhDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFFUlkeENvbnRyb2xDZmdNYXRoRGFwcAATbnNidFN0YWtpbmdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAAE3N1cmZTdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwABdnbnNidENvbnRyb2xsZXJDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAA9hdWN0aW9uQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAFG5vZGVSZWdpc3RyeUNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUdSWR4Q29udHJvbENmZ05vZGVSZWdpc3RyeURhcHAAC2dvdkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUbSWR4Q29udHJvbENmZ0dvdmVybmFuY2VEYXBwABJOZXV0cmlub0Fzc2V0SWRLZXkCEW5ldXRyaW5vX2Fzc2V0X2lkAA5Cb25kQXNzZXRJZEtleQINYm9uZF9hc3NldF9pZAASQXVjdGlvbkNvbnRyYWN0S2V5AhBhdWN0aW9uX2NvbnRyYWN0ABZOc2J0U3Rha2luZ0NvbnRyYWN0S2V5AhNuc2J0U3Rha2luZ0NvbnRyYWN0ABZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5AhRsaXF1aWRhdGlvbl9jb250cmFjdAAOUlBEQ29udHJhY3RLZXkCDHJwZF9jb250cmFjdAARQ29udG9sQ29udHJhY3RLZXkCEGNvbnRyb2xfY29udHJhY3QAD01hdGhDb250cmFjdEtleQINbWF0aF9jb250cmFjdAAbQmFsYW5jZVdhdmVzTG9ja0ludGVydmFsS2V5AhtiYWxhbmNlX3dhdmVzX2xvY2tfaW50ZXJ2YWwAHkJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbEtleQIeYmFsYW5jZV9uZXV0cmlub19sb2NrX2ludGVydmFsARVNaW5Ub2tlblN3YXBBbW91bnRLZXkBB2Fzc2V0SWQJAKwCAgIcbWluX291dE5ldXRyaW5vX3N3YXBfYW1vdW50XwUHYXNzZXRJZAAYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5AhhtaW5fb3V0TXVsdGlfc3dhcF9hbW91bnQAHkxlZ2FjeU1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQIYbWluX25ldXRyaW5vX3N3YXBfYW1vdW50ABtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkCFG5vZGVfb3JhY2xlX3Byb3ZpZGVyABVOZXV0cmlub091dEZlZVBhcnRLZXkCGG5ldXRyaW5vT3V0X3N3YXBfZmVlUGFydAASV2F2ZXNPdXRGZWVQYXJ0S2V5AhV3YXZlc091dF9zd2FwX2ZlZVBhcnQBD2tleU5vZGVSZWdpc3RyeQEHYWRkcmVzcwkArAICAgQlc19fBQdhZGRyZXNzAAhQcmljZUtleQIFcHJpY2UADVByaWNlSW5kZXhLZXkCC3ByaWNlX2luZGV4AAxJc0Jsb2NrZWRLZXkCCmlzX2Jsb2NrZWQBEmdldFByaWNlSGlzdG9yeUtleQEFYmxvY2sJAKwCAgkArAICBQhQcmljZUtleQIBXwkApAMBBQVibG9jawEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQVpbmRleAkArAICCQCsAgIFDVByaWNlSW5kZXhLZXkCAV8JAKQDAQUFaW5kZXgBFWdldFN0YWtpbmdOb2RlQnlJbmRleAEDaWR4CQEOZ2V0U3RyaW5nQnlLZXkBCQC5CQIJAMwIAgIGJXMlZCVzCQDMCAICBWxlYXNlCQDMCAIJAKQDAQUDaWR4CQDMCAICC25vZGVBZGRyZXNzBQNuaWwFA1NFUAEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEDaWR4CQERQGV4dHJOYXRpdmUoMTA2MikBCQEVZ2V0U3Rha2luZ05vZGVCeUluZGV4AQUDaWR4AR9nZXRSZXNlcnZlZEFtb3VudEZvclNwb25zb3JzaGlwAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVsZWFzZQkAzAgCAhdzcG9uc29yc2hpcFdhdmVzUmVzZXJ2ZQUDbmlsBQNTRVAJAGgCAOgHBQVNVUxUOAEYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AQVvd25lcgkArAICAhViYWxhbmNlX3VubG9ja19ibG9ja18FBW93bmVyAQ1nZXRMZWFzZUlkS2V5AQlub2RlSW5kZXgJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIFbGVhc2UJAMwIAgkApAMBBQlub2RlSW5kZXgJAMwIAgICaWQFA25pbAUDU0VQARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQtub2RlQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAg5sZWFzZUJ5QWRkcmVzcwkAzAgCBQtub2RlQWRkcmVzcwkAzAgCAgJpZAUDbmlsBQNTRVABEWdldExlYXNlQW1vdW50S2V5AQlub2RlSW5kZXgJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIFbGVhc2UJAMwIAgkApAMBBQlub2RlSW5kZXgJAMwIAgIGYW1vdW50BQNuaWwFA1NFUAEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBC25vZGVBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICDmxlYXNlQnlBZGRyZXNzCQDMCAIFC25vZGVBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQNTRVABGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEIZ3JvdXBOdW0JALkJAgkAzAgCAgYlcyVkJXMJAMwIAgIKbGVhc2VHcm91cAkAzAgCCQCkAwEFCGdyb3VwTnVtCQDMCAICCG5vZGVMaXN0BQNuaWwFA1NFUAEQbWluU3dhcEFtb3VudEtFWQEIc3dhcFR5cGUJAKwCAgkArAICAgRtaW5fBQhzd2FwVHlwZQIMX3N3YXBfYW1vdW50AQ50b3RhbExvY2tlZEtFWQIIc3dhcFR5cGUHYXNzZXRJZAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtiYWxhbmNlTG9jawkAzAgCBQhzd2FwVHlwZQkAzAgCBQdhc3NldElkBQNuaWwFA1NFUAEUdG90YWxMb2NrZWRCeVVzZXJLRVkDCHN3YXBUeXBlBW93bmVyB2Fzc2V0SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCAgtiYWxhbmNlTG9jawkAzAgCBQhzd2FwVHlwZQkAzAgCBQVvd25lcgkAzAgCBQdhc3NldElkBQNuaWwCAV8BFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBCHN3YXBUeXBlAwkAAAIFCHN3YXBUeXBlAghvdXRNdWx0aQUeQmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsS2V5BRtCYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxLZXkBGm5vZGVCYWxhbmNlTG9ja0ludGVydmFsS0VZAAIaYmFsYW5jZV9ub2RlX2xvY2tfaW50ZXJ2YWwBEXN3YXBzVGltZWZyYW1lS0VZAAIPc3dhcHNfdGltZWZyYW1lAQ5iclByb3RlY3RlZEtFWQACF21pbl9CUl9wcm90ZWN0aW9uX2xldmVsAQ9iYXNrZXRBc3NldHNLZXkAAholcyVzX19jb21tb25fX2Jhc2tldEFzc2V0cwEKYmFza2V0REtleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0RAEKYmFza2V0S0tleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0SwEKYmFza2V0QktleQACFSVzJXNfX2NvbW1vbl9fYmFza2V0QgESYmFza2V0TG9nYkRlbHRhS2V5AAIdJXMlc19fY29tbW9uX19iYXNrZXRMb2diRGVsdGEBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBB2Fzc2V0SWQJAKwCAgIfJXMlcyVzX19jb21tb25fX3dlaWdodEJ5QXNzZXRfXwUHYXNzZXRJZAEPa2V5UHJpY2VCeUFzc2V0AQdhc3NldElkCQCsAgICHiVzJXMlc19fY29tbW9uX19wcmljZUJ5QXNzZXRfXwUHYXNzZXRJZAERbWluU3dhcEFtb3VudFJFQUQCCHN3YXBUeXBlB2Fzc2V0SWQDCQAAAgUIc3dhcFR5cGUCCG91dE11bHRpCQELdmFsdWVPckVsc2UCCQCfCAEFGE1pbk5ldXRyaW5vU3dhcEFtb3VudEtleQkBDmdldE51bWJlckJ5S2V5AQUeTGVnYWN5TWluTmV1dHJpbm9Td2FwQW1vdW50S2V5CQEOZ2V0TnVtYmVyQnlLZXkBCQEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQUHYXNzZXRJZAESc3dhcHNUaW1lZnJhbWVSRUFEAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQERc3dhcHNUaW1lZnJhbWVLRVkAAKALAQ90b3RhbExvY2tlZFJFQUQCCHN3YXBUeXBlB2Fzc2V0SWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDnRvdGFsTG9ja2VkS0VZAgUIc3dhcFR5cGUFB2Fzc2V0SWQAAAEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAwhzd2FwVHlwZQVvd25lcgdhc3NldElkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARR0b3RhbExvY2tlZEJ5VXNlcktFWQMFCHN3YXBUeXBlBQVvd25lcgUHYXNzZXRJZAAAARdiYWxhbmNlTG9ja0ludGVydmFsUkVBRAEIc3dhcFR5cGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFmJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkBBQhzd2FwVHlwZQCgCwEbbm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxSRUFEAAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEabm9kZUJhbGFuY2VMb2NrSW50ZXJ2YWxLRVkAAAEBGGtleVN3YXBVc2VyU3BlbnRJblBlcmlvZAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAICFXN3YXBVc2VyU3BlbnRJblBlcmlvZAkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQNTRVABFWtleVVzZXJMYXN0U3dhcEhlaWdodAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAICEnVzZXJMYXN0U3dhcEhlaWdodAkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQNTRVABFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMCBmFtb3VudAVwcmljZQkAawMFBmFtb3VudAUFTVVMVDgFBXByaWNlARFjb252ZXJ0VG9rZW5Ub1VzZAIGYW1vdW50BXByaWNlCQBrAwUGYW1vdW50BQVwcmljZQUFTVVMVDgBFmNvbnZlcnRXYXZlc1RvTmV1dHJpbm8CBmFtb3VudAVwcmljZQkAawMFBmFtb3VudAUFcHJpY2UFBU1VTFQ4ARJjb252ZXJ0V2F2ZXNUb0JvbmQCBmFtb3VudAVwcmljZQkBEWNvbnZlcnRUb2tlblRvVXNkAgUGYW1vdW50BQVwcmljZQEWY29udmVydEpzb25BcnJheVRvTGlzdAEJanNvbkFycmF5CQC1CQIFCWpzb25BcnJheQIBLAEbY29udmVydEJhc2tldEl0ZW1Ub05ldXRyaW5vBAhpbkFtb3VudAdpbkFzc2V0DWJhc2tldEluZm9TdHINbmV1dHJpbm9QcmljZQQKYmFza2V0SW5mbwkAvAkCBQ1iYXNrZXRJbmZvU3RyAgFfCgEIZmluZEl0ZW0CA2FjYwRpdGVtBAViSXRlbQkAtQkCBQRpdGVtBQdMSVNUU0VQAwkAAAIJAJEDAgUFYkl0ZW0AAAUHaW5Bc3NldAUFYkl0ZW0FA2FjYwQCaXQKAAIkbAUKYmFza2V0SW5mbwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIZmluZEl0ZW0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEBWRsb2c2CQEFdmFsdWUBCQCfCAEJARJiYXNrZXRMb2diRGVsdGFLZXkABAJkNgkBBXZhbHVlAQkAnwgBCQEKYmFza2V0REtleQAEAmI2CQEFdmFsdWUBCQCfCAEJAQpiYXNrZXRCS2V5AAQCdzYJAQV2YWx1ZQEJAJ8IAQkBFmJhc2tldFdlaWdodEJ5QXNzZXRLZXkBBQdpbkFzc2V0BAJwNgkAZAIJAGUCBQVkbG9nNgUCdzYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJpdAABBANwcDYJAGwGBQJiNgAGBQJwNgAGAAYFBkhBTEZVUAQOb3V0QW1vdW50R3Jvc3MJAGsDBQhpbkFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAml0AAIDCQAAAgUNbmV1dHJpbm9QcmljZQAABQVNVUxUOAkAaAIFDW5ldXRyaW5vUHJpY2UAZAQKbXVsdGlwbGllcgkAZQIJAGQCBQVNVUxUNgUCZDYFA3BwNgQJbmV0QW1vdW50CQBrAwUOb3V0QW1vdW50R3Jvc3MFCm11bHRpcGxpZXIFBU1VTFQ2BAlmZWVBbW91bnQDCQBnAgUJbmV0QW1vdW50BQ5vdXRBbW91bnRHcm9zcwAACQBlAgUOb3V0QW1vdW50R3Jvc3MFCW5ldEFtb3VudAkAzAgCBQ5vdXRBbW91bnRHcm9zcwkAzAgCBQluZXRBbW91bnQJAMwIAgUJZmVlQW1vdW50BQNuaWwBF2NvbnZlcnROZXV0cmlub1RvQmFza2V0AwZhbW91bnQNYmFza2V0SW5mb1N0cg5uZXV0cmlub1N1cHBseQQKYmFza2V0SW5mbwkAvAkCBQ1iYXNrZXRJbmZvU3RyAgFfCgEEY29udgIDYWNjBGl0ZW0EBXBhcnRzCQC1CQIFBGl0ZW0FB0xJU1RTRVAEB2Fzc2V0SWQJAJEDAgUFcGFydHMAAAQFc2hhcmUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwYXJ0cwABBAVwcmljZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAIEBnJlc2VydgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAMDCQAAAgUObmV1dHJpbm9TdXBwbHkAAAkAAgECJ0F0dGVtcHQgdG8gYnVybiBuZXV0cmlubyBhdCB6ZXJvIHN1cHBseQQJb3V0QW1vdW50CQBrAwUGYW1vdW50BQZyZXNlcnYFDm5ldXRyaW5vU3VwcGx5BAp3YXZlc1R1cGxlAwkAAAIFB2Fzc2V0SWQCBVdBVkVTCQCUCgIFCW91dEFtb3VudAUFcHJpY2UJAJQKAggFA2FjYwJfMggFA2FjYwJfMwkAlQoDCQDNCAIIBQNhY2MCXzEJAJYKBAUHYXNzZXRJZAUJb3V0QW1vdW50BQVwcmljZQUFc2hhcmUIBQp3YXZlc1R1cGxlAl8xCAUKd2F2ZXNUdXBsZQJfMgoAAiRsBQpiYXNrZXRJbmZvCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlQoDBQNuaWwAAAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQRjb252AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARFtaW5Td2FwQW1vdW50RkFJTAIIc3dhcFR5cGUNbWluU3dhcEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICGFRoZSBzcGVjaWZpZWQgYW1vdW50IGluIAUIc3dhcFR5cGUCKyBzd2FwIGlzIGxlc3MgdGhhbiB0aGUgcmVxdWlyZWQgbWluaW11bSBvZiAJAKQDAQUNbWluU3dhcEFtb3VudAEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAkAAgECWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwEOcHJpY2VJbmRleEZBSUwFBWluZGV4CnByaWNlSW5kZXgLaW5kZXhIZWlnaHQMdW5sb2NrSGVpZ2h0D3ByZXZJbmRleEhlaWdodAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICI2ludmFsaWQgcHJpY2UgaGlzdG9yeSBpbmRleDogaW5kZXg9CQCkAwEFBWluZGV4AgwgcHJpY2VJbmRleD0JAKQDAQUKcHJpY2VJbmRleAINIGluZGV4SGVpZ2h0PQkApAMBBQtpbmRleEhlaWdodAIOIHVubG9ja0hlaWdodD0JAKQDAQUMdW5sb2NrSGVpZ2h0AhEgcHJldkluZGV4SGVpZ2h0PQkApAMBBQ9wcmV2SW5kZXhIZWlnaHQAD25ldXRyaW5vQXNzZXRJZAkA2QQBCQEOZ2V0U3RyaW5nQnlLZXkBBRJOZXV0cmlub0Fzc2V0SWRLZXkACnByaWNlSW5kZXgJARhnZXROdW1iZXJCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDVByaWNlSW5kZXhLZXkACWlzQmxvY2tlZAkBFmdldEJvb2xCeUFkZHJlc3NBbmRLZXkCBQ9jb250cm9sQ29udHJhY3QFDElzQmxvY2tlZEtleQAYbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5CQDZBAEJAQ5nZXRTdHJpbmdCeUtleQEFG05vZGVPcmFjbGVQcm92aWRlclB1YktleUtleQALYm9uZEFzc2V0SWQJANkEAQIsRjNpYXh6cnVGZUt1amZWZllTWkVrZWpwamg2N3dtUmZQQ1JIaU5tV0twM1oAFWRlcHJlY2F0ZWRCb25kQXNzZXRJZAkA2QQBAiw5NzVha1pCZm5NajUxM1U3TVphSEt6UXJtc0V4NWFFM3dkV0tUckhCaGJqRgAQbmV1dHJpbm9Db250cmFjdAUEdGhpcwAMY3VycmVudFByaWNlCQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0BQhQcmljZUtleQEbY2hlY2tJc1ZhbGlkTWluU3BvbnNvcmVkRmVlAQJ0eAQOTUlOVFJBTlNGRVJGRUUAoI0GBBZTcG9uc29yZWRGZWVVcHBlckJvdW5kAOgHBA9yZWFsTmV1dHJpbm9GZWUJARFjb252ZXJ0VG9rZW5Ub1VzZAIFDk1JTlRSQU5TRkVSRkVFBQxjdXJyZW50UHJpY2UEDm1pbk5ldXRyaW5vRmVlCQBoAgUPcmVhbE5ldXRyaW5vRmVlAAIEDm1heE5ldXRyaW5vRmVlCQBrAwUPcmVhbE5ldXRyaW5vRmVlBRZTcG9uc29yZWRGZWVVcHBlckJvdW5kAGQECGlucHV0RmVlCQEFdmFsdWUBCAUCdHgUbWluU3BvbnNvcmVkQXNzZXRGZWUDAwkAZwIFCGlucHV0RmVlBQ5taW5OZXV0cmlub0ZlZQkAZwIFDm1heE5ldXRyaW5vRmVlBQhpbnB1dEZlZQcJAAACCAUCdHgHYXNzZXRJZAUPbmV1dHJpbm9Bc3NldElkBwEPZ2V0UHJpY2VIaXN0b3J5AQVibG9jawkBGGdldE51bWJlckJ5QWRkcmVzc0FuZEtleQIFD2NvbnRyb2xDb250cmFjdAkBEmdldFByaWNlSGlzdG9yeUtleQEFBWJsb2NrARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBBWluZGV4CQEYZ2V0TnVtYmVyQnlBZGRyZXNzQW5kS2V5AgUPY29udHJvbENvbnRyYWN0CQEYZ2V0SGVpZ2h0UHJpY2VCeUluZGV4S2V5AQUFaW5kZXgBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQNTRVAADHNJZHhTd2FwVHlwZQABAApzSWR4U3RhdHVzAAIADHNJZHhJbkFtb3VudAADAA9zSWR4U3RhcnRIZWlnaHQABwASc0lkeFN0YXJ0VGltZXN0YW1wAAgAFHNJZHhTZWxmVW5sb2NrSGVpZ2h0AAsAC3NJZHhNaW5SYW5kAA8AC3NJZHhNYXhSYW5kABAAC3NJZHhJbkFzc2V0ABQBB3N3YXBLRVkCC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFBHR4SWQFA25pbAUDU0VQAQtzdHJTd2FwREFUQRQIc3dhcFR5cGUGc3RhdHVzCGluQW1vdW50BXByaWNlDG91dE5ldEFtb3VudAxvdXRGZWVBbW91bnQLc3RhcnRIZWlnaHQOc3RhcnRUaW1lc3RhbXAJZW5kSGVpZ2h0DGVuZFRpbWVzdGFtcBBzZWxmVW5sb2NrSGVpZ2h0EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkB3JhbmRNaW4HcmFuZE1heApvdXRTdXJmQW10AmJyCmJhc2tldERhdGEHaW5Bc3NldAkAugkCCQDMCAICKCVzJXMlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJXMlZCVkJWQlZCVzJXMJAMwIAgUIc3dhcFR5cGUJAMwIAgUGc3RhdHVzCQDMCAIFCGluQW1vdW50CQDMCAIFBXByaWNlCQDMCAIFDG91dE5ldEFtb3VudAkAzAgCBQxvdXRGZWVBbW91bnQJAMwIAgULc3RhcnRIZWlnaHQJAMwIAgUOc3RhcnRUaW1lc3RhbXAJAMwIAgUJZW5kSGVpZ2h0CQDMCAIFDGVuZFRpbWVzdGFtcAkAzAgCBRBzZWxmVW5sb2NrSGVpZ2h0CQDMCAIFEHJhbmRVbmxvY2tIZWlnaHQJAMwIAgUFaW5kZXgJAMwIAgUMd2l0aGRyYXdUeElkCQDMCAIFB3JhbmRNaW4JAMwIAgUHcmFuZE1heAkAzAgCBQpvdXRTdXJmQW10CQDMCAIFAmJyCQDMCAIFCmJhc2tldERhdGEJAMwIAgUHaW5Bc3NldAUDbmlsBQNTRVABD3BlbmRpbmdTd2FwREFUQQQIc3dhcFR5cGUNaW5Bc3NldEFtb3VudBBzZWxmVW5sb2NrSGVpZ2h0B2luQXNzZXQJAQtzdHJTd2FwREFUQRQFCHN3YXBUeXBlAgdQRU5ESU5HCQCkAwEFDWluQXNzZXRBbW91bnQCATACATACATAJAKQDAQUGaGVpZ2h0CQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wAgEwAgEwCQCkAwEFEHNlbGZVbmxvY2tIZWlnaHQCATACATACBE5VTEwCATACATACATACATACAAUHaW5Bc3NldAEOZmluaXNoU3dhcERBVEELCWRhdGFBcnJheQVwcmljZQxvdXROZXRBbW91bnQMb3V0RmVlQW1vdW50EHJhbmRVbmxvY2tIZWlnaHQFaW5kZXgMd2l0aGRyYXdUeElkCm91dFN1cmZBbXQCYnIKYmFza2V0RGF0YQdpbkFzc2V0CQELc3RyU3dhcERBVEEUCQCRAwIFCWRhdGFBcnJheQUMc0lkeFN3YXBUeXBlAghGSU5JU0hFRAkAkQMCBQlkYXRhQXJyYXkFDHNJZHhJbkFtb3VudAkApAMBBQVwcmljZQkApAMBBQxvdXROZXRBbW91bnQJAKQDAQUMb3V0RmVlQW1vdW50CQCRAwIFCWRhdGFBcnJheQUPc0lkeFN0YXJ0SGVpZ2h0CQCRAwIFCWRhdGFBcnJheQUSc0lkeFN0YXJ0VGltZXN0YW1wCQCkAwEFBmhlaWdodAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAkQMCBQlkYXRhQXJyYXkFFHNJZHhTZWxmVW5sb2NrSGVpZ2h0CQCkAwEFEHJhbmRVbmxvY2tIZWlnaHQJAKQDAQUFaW5kZXgFDHdpdGhkcmF3VHhJZAkAkQMCBQlkYXRhQXJyYXkFC3NJZHhNaW5SYW5kCQCRAwIFCWRhdGFBcnJheQULc0lkeE1heFJhbmQJAKQDAQUKb3V0U3VyZkFtdAkApAMBBQJicgUKYmFza2V0RGF0YQUHaW5Bc3NldAESc3dhcERhdGFGYWlsT3JSRUFEAgt1c2VyQWRkcmVzcwhzd2FwVHhJZAQHc3dhcEtleQkBB3N3YXBLRVkCBQt1c2VyQWRkcmVzcwUIc3dhcFR4SWQJALwJAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEFB3N3YXBLZXkJAKwCAgIRbm8gc3dhcCBkYXRhIGZvciAFB3N3YXBLZXkFA1NFUAEJYXBwbHlGZWVzAw5hbW91bnRPdXRHcm9zcwtpbkFtdFRvU1VSRgdmZWVQYXJ0BAlmZWVBbW91bnQJAGsDBQ5hbW91bnRPdXRHcm9zcwUHZmVlUGFydAUFTVVMVDYJAMwIAgkAZQIFDmFtb3VudE91dEdyb3NzBQlmZWVBbW91bnQJAMwIAgUJZmVlQW1vdW50BQNuaWwBD2FwcGx5RmVlc0Jhc2tldAEJYmFza2V0T3V0BAJrNgkBBXZhbHVlAQkAnwgBCQEKYmFza2V0S0tleQAEAmQ2CQEFdmFsdWUBCQCfCAEJAQpiYXNrZXRES2V5AAQHZmVlUGFydAkAawMFAms2BQJkNgUFTVVMVDYKAQpmZWVBcHBsaWVyAgNhY2MEaXRlbQQJZmVlQW1vdW50CQBrAwgFBGl0ZW0CXzIFB2ZlZVBhcnQFBU1VTFQ2CQDNCAIFA2FjYwkAuQkCCQDMCAIIBQRpdGVtAl8xCQDMCAIJAKQDAQgFBGl0ZW0CXzMJAMwIAgkApAMBCQBlAggFBGl0ZW0CXzIFCWZlZUFtb3VudAkAzAgCCQCkAwEFCWZlZUFtb3VudAkAzAgCCQCkAwEIBQRpdGVtAl80BQNuaWwFB0xJU1RTRVAEAWEKAAIkbAUJYmFza2V0T3V0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpmZWVBcHBsaWVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQC6CQIFAWECAV8BA2FicwEBeAMJAGYCAAAFAXgJAQEtAQUBeAUBeAEKc2VsZWN0Tm9kZQENdW5sZWFzZUFtb3VudAQNYW1vdW50VG9MZWFzZQkAZQIJAGUCCAkA7wcBBRBuZXV0cmlub0NvbnRyYWN0CWF2YWlsYWJsZQUNdW5sZWFzZUFtb3VudAkBH2dldFJlc2VydmVkQW1vdW50Rm9yU3BvbnNvcnNoaXAABApvbGRMZWFzZWQwCQEOZ2V0TnVtYmVyQnlLZXkBCQERZ2V0TGVhc2VBbW91bnRLZXkBAAAECm9sZExlYXNlZDEJAQ5nZXROdW1iZXJCeUtleQEJARFnZXRMZWFzZUFtb3VudEtleQEAAQQKbmV3TGVhc2VkMAkAZAIFDWFtb3VudFRvTGVhc2UFCm9sZExlYXNlZDAECm5ld0xlYXNlZDEJAGQCBQ1hbW91bnRUb0xlYXNlBQpvbGRMZWFzZWQxAwMJAGYCBQpuZXdMZWFzZWQwAAAGCQBmAgUKbmV3TGVhc2VkMQAABAZkZWx0YTAJAQNhYnMBCQBlAgUKbmV3TGVhc2VkMAUKb2xkTGVhc2VkMQQGZGVsdGExCQEDYWJzAQkAZQIFCm5ld0xlYXNlZDEFCm9sZExlYXNlZDADCQBnAgUGZGVsdGExBQZkZWx0YTAJAJQKAgAABQpuZXdMZWFzZWQwCQCUCgIAAQUKbmV3TGVhc2VkMQkAlAoCAP///////////wEAAAEIdGhpc09ubHkBAWkDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAi1QZXJtaXNzaW9uIGRlbmllZDogdGhpcyBjb250cmFjdCBvbmx5IGFsbG93ZWQGARZwcmVwYXJlVW5sZWFzZUFuZExlYXNlAQ11bmxlYXNlQW1vdW50BAlub2RlVHVwbGUJAQpzZWxlY3ROb2RlAQUNdW5sZWFzZUFtb3VudAQJbm9kZUluZGV4CAUJbm9kZVR1cGxlAl8xBA5uZXdMZWFzZUFtb3VudAgFCW5vZGVUdXBsZQJfMgMJAGYCBQ5uZXdMZWFzZUFtb3VudAAABApsZWFzZUlkS2V5CQENZ2V0TGVhc2VJZEtleQEFCW5vZGVJbmRleAQIb2xkTGVhc2UJAJwIAgUEdGhpcwUKbGVhc2VJZEtleQQOdW5sZWFzZU9yRW1wdHkDCQEJaXNEZWZpbmVkAQUIb2xkTGVhc2UJAMwIAgkBC0xlYXNlQ2FuY2VsAQkBBXZhbHVlAQUIb2xkTGVhc2UFA25pbAUDbmlsBA5sZWFzZUFtb3VudEtleQkBEWdldExlYXNlQW1vdW50S2V5AQUJbm9kZUluZGV4BAVsZWFzZQkAxAgCCQEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEFCW5vZGVJbmRleAUObmV3TGVhc2VBbW91bnQJAM4IAgUOdW5sZWFzZU9yRW1wdHkJAMwIAgUFbGVhc2UJAMwIAgkBC0JpbmFyeUVudHJ5AgUKbGVhc2VJZEtleQkBBWxjYWxjAQUFbGVhc2UJAMwIAgkBDEludGVnZXJFbnRyeQIJARFnZXRMZWFzZUFtb3VudEtleQEFCW5vZGVJbmRleAUObmV3TGVhc2VBbW91bnQFA25pbAUDbmlsAQxyZWFkTm9kZUluZm8BB25vZGVJZHgEC25vZGVBZGRyZXNzCQEcZ2V0U3Rha2luZ05vZGVBZGRyZXNzQnlJbmRleAEFB25vZGVJZHgEDGxlYXNlZEFtdEtFWQkBEWdldExlYXNlQW1vdW50S2V5AQUHbm9kZUlkeAQJbGVhc2VkQW10CQEOZ2V0TnVtYmVyQnlLZXkBBQxsZWFzZWRBbXRLRVkECmxlYXNlSWRLRVkJAQ1nZXRMZWFzZUlkS2V5AQUHbm9kZUlkeAQHbGVhc2VJZAkBBXZhbHVlAQkAnAgCBQR0aGlzBQpsZWFzZUlkS0VZCQCXCgUFC25vZGVBZGRyZXNzBQxsZWFzZWRBbXRLRVkFCWxlYXNlZEFtdAUKbGVhc2VJZEtFWQUHbGVhc2VJZAEKY29tbW9uU3dhcAUIc3dhcFR5cGUJcG10QW1vdW50B2luQXNzZXQOdXNlckFkZHJlc3NTdHIGdHhJZDU4BBBzd2FwUGFyYW1zU1RSVUNUCQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/AcEBQR0aGlzAhtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgAABQNuaWwFA25pbAQRdG9rZW5Td2FwTGltaXRVc2QIBRBzd2FwUGFyYW1zU1RSVUNUAl8xBA5zd2FwTGltaXRTcGVudAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzIEDmJsY2tzMkxtdFJlc2V0CAUQc3dhcFBhcmFtc1NUUlVDVAJfMwQQdXNkblN3YXBMaW1pdE1heAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzcEDW1pblN3YXBBbW91bnQJARFtaW5Td2FwQW1vdW50UkVBRAIFCHN3YXBUeXBlBQdpbkFzc2V0BBF0b3RhbExvY2tlZEJ5VXNlcgkBFXRvdGFsTG9ja2VkQnlVc2VyUkVBRAMFCHN3YXBUeXBlBQ51c2VyQWRkcmVzc1N0cgUHaW5Bc3NldAQLbm9kZUFkZHJlc3MJARVnZXRTdGFraW5nTm9kZUJ5SW5kZXgBAAAEDGlzU3dhcEJ5Tm9kZQkAAAIFC25vZGVBZGRyZXNzBQ51c2VyQWRkcmVzc1N0cgQWYmFsYW5jZUxvY2tNYXhJbnRlcnZhbAMFDGlzU3dhcEJ5Tm9kZQkBG25vZGVCYWxhbmNlTG9ja0ludGVydmFsUkVBRAAJARdiYWxhbmNlTG9ja0ludGVydmFsUkVBRAEFCHN3YXBUeXBlBBBzZWxmVW5sb2NrSGVpZ2h0CQBkAgUGaGVpZ2h0BRZiYWxhbmNlTG9ja01heEludGVydmFsBAJwcgkBBXZhbHVlAQkAmggCBQ9jb250cm9sQ29udHJhY3QJAQ9rZXlQcmljZUJ5QXNzZXQBBQdpbkFzc2V0BA5zd2FwVXNkblZvbHVtZQMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8JARFjb252ZXJ0VG9rZW5Ub1VzZAIFCXBtdEFtb3VudAUCcHIFCXBtdEFtb3VudAQMc3dhcExpbWl0TWF4AwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwURdG9rZW5Td2FwTGltaXRVc2QFEHVzZG5Td2FwTGltaXRNYXgDCQBmAgUNbWluU3dhcEFtb3VudAUJcG10QW1vdW50CQERbWluU3dhcEFtb3VudEZBSUwCBQhzd2FwVHlwZQUNbWluU3dhcEFtb3VudAMDCQEBIQEFDGlzU3dhcEJ5Tm9kZQkAZgIFDnN3YXBMaW1pdFNwZW50AAAHCQACAQkArAICAjpZb3UgaGF2ZSBleGNlZWRlZCBzd2FwIGxpbWl0ISBOZXh0IGFsbG93ZWQgc3dhcCBoZWlnaHQgaXMgCQCkAwEJAGQCBQZoZWlnaHQFDmJsY2tzMkxtdFJlc2V0AwMJAQEhAQUMaXNTd2FwQnlOb2RlCQBmAgUOc3dhcFVzZG5Wb2x1bWUFDHN3YXBMaW1pdE1heAcJAAIBCQCsAgIJAKwCAgkArAICAi5Zb3UgaGF2ZSBleGNlZWRlZCB5b3VyIHN3YXAgbGltaXQhIFJlcXVlc3RlZDogCQCkAwEFDnN3YXBVc2RuVm9sdW1lAg0sIGF2YWlsYWJsZTogCQCkAwEFDHN3YXBMaW1pdE1heAMFCWlzQmxvY2tlZAkBFWVtZXJnZW5jeVNodXRkb3duRkFJTAAED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwECmJhc2tldEluZm8JAQhhc1N0cmluZwEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBRFuTWV0cmljQmFza2V0SW5mbwQNd2VpZ2h0ZWRQcmljZQkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFFG5NZXRyaWNXZWlnaHRlZFByaWNlBANvdXQJARtjb252ZXJ0QmFza2V0SXRlbVRvTmV1dHJpbm8EBQlwbXRBbW91bnQFB2luQXNzZXQFCmJhc2tldEluZm8FDXdlaWdodGVkUHJpY2UDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAZwIAAAkAkQMCBQNvdXQAAQcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAj5OZXQgYW1vdW50IGlzIG5vbi1wb3NpdGl2ZSwgY2Fubm90IHN3YXAuIChncm9zcywgbmV0LCBmZWUpID0gKAkApAMBCQCRAwIFA291dAAAAgIsIAkApAMBCQCRAwIFA291dAABAgIsIAkApAMBCQCRAwIFA291dAACAgEpBAlsZWFzZVBhcnQDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAAAIFB2luQXNzZXQCBVdBVkVTBwkBFnByZXBhcmVVbmxlYXNlQW5kTGVhc2UBAAAFA25pbAkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARhrZXlTd2FwVXNlclNwZW50SW5QZXJpb2QBBQ51c2VyQWRkcmVzc1N0cgUOc3dhcFVzZG5Wb2x1bWUJAMwIAgkBDEludGVnZXJFbnRyeQIJARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBBQ51c2VyQWRkcmVzc1N0cgUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUdG90YWxMb2NrZWRCeVVzZXJLRVkDBQhzd2FwVHlwZQUOdXNlckFkZHJlc3NTdHIFB2luQXNzZXQJAGQCBRF0b3RhbExvY2tlZEJ5VXNlcgUJcG10QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYZ2V0QmFsYW5jZVVubG9ja0Jsb2NrS2V5AQUOdXNlckFkZHJlc3NTdHIFEHNlbGZVbmxvY2tIZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB3N3YXBLRVkCBQ51c2VyQWRkcmVzc1N0cgUGdHhJZDU4CQEPcGVuZGluZ1N3YXBEQVRBBAUIc3dhcFR5cGUFCXBtdEFtb3VudAUQc2VsZlVubG9ja0hlaWdodAUHaW5Bc3NldAUDbmlsBQlsZWFzZVBhcnQFBHVuaXQADGJGdW5jSWR4U3VyZgAAAA1iRnVuY0lkeFdhdmVzAAEADGJGdW5jSWR4VXNkbgACABRiRnVuY0lkeFJlc2VydmVTdGFydAADABNiRnVuY0lkeFN1cHBseVN0YXJ0AAQAD2JGdW5jSWR4QlJTdGFydAAFABJiRnVuY0lkeFJlc2VydmVFbmQABgARYkZ1bmNJZHhTdXBwbHlFbmQABwANYkZ1bmNJZHhCUkVuZAAIAAxiRnVuY0lkeFJlc3QACQASYkZ1bmNJZHhXYXZlc1ByaWNlAAoBD2NhbGNXaXRoZHJhd1QyVQQIaW5BbW91bnQHaW5Bc3NldApiYXNrZXRJbmZvDXdlaWdodGVkUHJpY2UEBm91dEFtdAkBG2NvbnZlcnRCYXNrZXRJdGVtVG9OZXV0cmlubwQFCGluQW1vdW50BQdpbkFzc2V0BQpiYXNrZXRJbmZvBQ13ZWlnaHRlZFByaWNlCQCeCgwJAJEDAgUGb3V0QW10AAAFD25ldXRyaW5vQXNzZXRJZAAABQdpbkFzc2V0AAAFDXdlaWdodGVkUHJpY2UFCGluQW1vdW50AAAAAAAABQNuaWwJAMwIAgkAkQMCBQZvdXRBbXQAAQkAzAgCCQCRAwIFBm91dEFtdAACBQNuaWwBFGNhbGNXaXRoZHJhd1UyQmFza2V0AwZ1c2RuSW4KYmFza2V0SW5mbw5uZXV0cmlub1N1cHBseQQLb3V0QW10R3Jvc3MJARdjb252ZXJ0TmV1dHJpbm9Ub0Jhc2tldAMFBnVzZG5JbgUKYmFza2V0SW5mbwUObmV1dHJpbm9TdXBwbHkJAJ4KDAgFC291dEFtdEdyb3NzAl8yBQR1bml0AAAFD25ldXRyaW5vQXNzZXRJZAgFC291dEFtdEdyb3NzAl8yCAULb3V0QW10R3Jvc3MCXzMFBnVzZG5JbgUObmV1dHJpbm9TdXBwbHkFBnVzZG5JbgAACAULb3V0QW10R3Jvc3MCXzEFA25pbAEMY2FsY1dpdGhkcmF3BQhzd2FwVHlwZQhpbkFtb3VudAVwcmljZQ9uZXV0cmlub01ldHJpY3MHaW5Bc3NldAQObmV1dHJpbm9TdXBwbHkJAQVhc0ludAEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBRRuTWV0cmljSWR4VXNkblN1cHBseQQKYmFza2V0SW5mbwkBCGFzU3RyaW5nAQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFEW5NZXRyaWNCYXNrZXRJbmZvBA13ZWlnaHRlZFByaWNlCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUUbk1ldHJpY1dlaWdodGVkUHJpY2UEDG91dERhdGFUdXBsZQMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8JAQ9jYWxjV2l0aGRyYXdUMlUEBQhpbkFtb3VudAUHaW5Bc3NldAUKYmFza2V0SW5mbwUNd2VpZ2h0ZWRQcmljZQMJAAACBQhzd2FwVHlwZQIIb3V0TXVsdGkJARRjYWxjV2l0aGRyYXdVMkJhc2tldAMFCGluQW1vdW50BQpiYXNrZXRJbmZvBQ5uZXV0cmlub1N1cHBseQkAAgEJAKwCAgIWVW5zdXBwb3J0ZWQgc3dhcCB0eXBlIAUIc3dhcFR5cGUEC291dEFtdEdyb3NzCAUMb3V0RGF0YVR1cGxlAl8xBApvdXRBc3NldElkCAUMb3V0RGF0YVR1cGxlAl8yBA9pbkFtdFRvU3VyZlBhcnQIBQxvdXREYXRhVHVwbGUCXzMECWluQXNzZXRJZAgFDG91dERhdGFUdXBsZQJfNAQKdW5sZWFzZUFtdAgFDG91dERhdGFUdXBsZQJfNQQNd2l0aGRyYXdQcmljZQgFDG91dERhdGFUdXBsZQJfNgQKYmFza2V0RGF0YQgFDG91dERhdGFUdXBsZQNfMTEECm5ldEZlZURhdGEIBQxvdXREYXRhVHVwbGUDXzEyBAlvdXROZXRBbXQDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQCRAwIFCm5ldEZlZURhdGEAAAAABAlvdXRGZWVBbXQDCQAAAgUIc3dhcFR5cGUCC291dE5ldXRyaW5vCQCRAwIFCm5ldEZlZURhdGEAAQAABApvdXRTdXJmQW10AwkAZwIAAAUPaW5BbXRUb1N1cmZQYXJ0AAAJAQVhc0ludAEJAJEDAgkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhRzdXJmRnVuY3Rpb25SRUFET05MWQkAzAgCBQ9pbkFtdFRvU3VyZlBhcnQJAMwIAgUJaW5Bc3NldElkBQNuaWwFA25pbAUMYkZ1bmNJZHhTdXJmBA53aXRoZHJhd0Jhc2tldAMJAAACBQhzd2FwVHlwZQIIb3V0TXVsdGkJAQ9hcHBseUZlZXNCYXNrZXQBBQpiYXNrZXREYXRhAgAJAJsKCQUJb3V0TmV0QW10BQpvdXRBc3NldElkBQpvdXRTdXJmQW10BQ9pbkFtdFRvU3VyZlBhcnQFCnVubGVhc2VBbXQFCW91dEZlZUFtdAULb3V0QW10R3Jvc3MFDXdpdGhkcmF3UHJpY2UFDndpdGhkcmF3QmFza2V0ARJrZXlBcHBseUluUHJvZ3Jlc3MAAhMlc19fYXBwbHlJblByb2dyZXNzARNrZXlQcm9wb3NhbERhdGFCeUlkAQpwcm9wb3NhbElkCQCsAgICFCVzJWRfX3Byb3Bvc2FsRGF0YV9fCQCkAwEFCnByb3Bvc2FsSWQAC2dvdklkeFR4SWRzAAkBDnZhbGlkYXRlVXBkYXRlAQJ0eAQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIFT3JkZXIEAW8FByRtYXRjaDAJAAIBAhVPcmRlcnMgYXJlbid0IGFsbG93ZWQDAwkAAQIFByRtYXRjaDACD0RhdGFUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIVU3BvbnNvckZlZVRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhRTZXRTY3JpcHRUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIWQ3JlYXRlQWxpYXNUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIWTGVhc2VDYW5jZWxUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIQTGVhc2VUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIQSXNzdWVUcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIbSW52b2tlRXhwcmVzc2lvblRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAhpVcGRhdGVBc3NldEluZm9UcmFuc2FjdGlvbgYDCQABAgUHJG1hdGNoMAIXSW52b2tlU2NyaXB0VHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACGVNldEFzc2V0U2NyaXB0VHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACE1RyYW5zZmVyVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACE0V4Y2hhbmdlVHJhbnNhY3Rpb24GAwkAAQIFByRtYXRjaDACF01hc3NUcmFuc2ZlclRyYW5zYWN0aW9uBgMJAAECBQckbWF0Y2gwAg9CdXJuVHJhbnNhY3Rpb24GCQABAgUHJG1hdGNoMAISUmVpc3N1ZVRyYW5zYWN0aW9uBAF0BQckbWF0Y2gwBAR0eElkCQDYBAEIBQF0AmlkBApwcm9wb3NhbElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgULZ292Q29udHJhY3QJARJrZXlBcHBseUluUHJvZ3Jlc3MAAhZBcHBseSBpcyBub3QgaGFwcGVuaW5nBAZ0eExpc3QJALUJAgkAkQMCCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQtnb3ZDb250cmFjdAkBE2tleVByb3Bvc2FsRGF0YUJ5SWQBBQpwcm9wb3NhbElkBQNTRVAFC2dvdklkeFR4SWRzBQdMSVNUU0VQAwkBASEBCQEJaXNEZWZpbmVkAQkAzwgCBQZ0eExpc3QFBHR4SWQJAAIBCQCsAgIJAKwCAgkArAICAg5Vbmtub3duIHR4SWQ6IAUEdHhJZAIQIGZvciBwcm9wb3NhbElkPQkApAMBBQpwcm9wb3NhbElkBgkAAgECC01hdGNoIGVycm9yDwFpAQ1jb25zdHJ1Y3RvclYxDBJuZXV0cmlub0Fzc2V0SWRQcm0OYm9uZEFzc2V0SWRQcm0SYXVjdGlvbkNvbnRyYWN0UHJtFmxpcXVpZGF0aW9uQ29udHJhY3RQcm0OcnBkQ29udHJhY3RQcm0bbm9kZU9yYWNsZVByb3ZpZGVyUHViS2V5UHJtG2JhbGFuY2VXYXZlc0xvY2tJbnRlcnZhbFBybR5iYWxhbmNlTmV1dHJpbm9Mb2NrSW50ZXJ2YWxQcm0VbWluV2F2ZXNTd2FwQW1vdW50UHJtGG1pbk5ldXRyaW5vU3dhcEFtb3VudFBybRVuZXV0cmlub091dEZlZVBhcnRQcm0Sd2F2ZXNPdXRGZWVQYXJ0UHJtBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCQDMCAIJAQtTdHJpbmdFbnRyeQIFEk5ldXRyaW5vQXNzZXRJZEtleQUSbmV1dHJpbm9Bc3NldElkUHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFDkJvbmRBc3NldElkS2V5BQ5ib25kQXNzZXRJZFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRJBdWN0aW9uQ29udHJhY3RLZXkFEmF1Y3Rpb25Db250cmFjdFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRZMaXF1aWRhdGlvbkNvbnRyYWN0S2V5BRZsaXF1aWRhdGlvbkNvbnRyYWN0UHJtCQDMCAIJAQtTdHJpbmdFbnRyeQIFDlJQRENvbnRyYWN0S2V5BQ5ycGRDb250cmFjdFBybQkAzAgCCQELU3RyaW5nRW50cnkCBRtOb2RlT3JhY2xlUHJvdmlkZXJQdWJLZXlLZXkFG25vZGVPcmFjbGVQcm92aWRlclB1YktleVBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUbQmFsYW5jZVdhdmVzTG9ja0ludGVydmFsS2V5BRtiYWxhbmNlV2F2ZXNMb2NrSW50ZXJ2YWxQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFHkJhbGFuY2VOZXV0cmlub0xvY2tJbnRlcnZhbEtleQUeYmFsYW5jZU5ldXRyaW5vTG9ja0ludGVydmFsUHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVTWluVG9rZW5Td2FwQW1vdW50S2V5AQIFV0FWRVMFFW1pbldhdmVzU3dhcEFtb3VudFBybQkAzAgCCQEMSW50ZWdlckVudHJ5AgUYTWluTmV1dHJpbm9Td2FwQW1vdW50S2V5BRhtaW5OZXV0cmlub1N3YXBBbW91bnRQcm0JAMwIAgkBDEludGVnZXJFbnRyeQIFFU5ldXRyaW5vT3V0RmVlUGFydEtleQUVbmV1dHJpbm9PdXRGZWVQYXJ0UHJtCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJXYXZlc091dEZlZVBhcnRLZXkFEndhdmVzT3V0RmVlUGFydFBybQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDWNvbnN0cnVjdG9yVjIDDG1hdGhDb250cmFjdBNuc2J0U3Rha2luZ0NvbnRyYWN0FHN3YXBzVGltZWZyYW1lQmxvY2tzBAtjaGVja0NhbGxlcgkBCHRoaXNPbmx5AQUBaQMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkCQDMCAIJAQtTdHJpbmdFbnRyeQIFD01hdGhDb250cmFjdEtleQUMbWF0aENvbnRyYWN0CQDMCAIJAQtTdHJpbmdFbnRyeQIFFk5zYnRTdGFraW5nQ29udHJhY3RLZXkFE25zYnRTdGFraW5nQ29udHJhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIJARFzd2Fwc1RpbWVmcmFtZUtFWQAFFHN3YXBzVGltZWZyYW1lQmxvY2tzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY29uc3RydWN0b3JWMwURYXNzZXRzV2VpZ2h0c01pbnMGZFBhcmFtBmtQYXJhbQZiUGFyYW0KZGVsdGFQYXJhbQQLY2hlY2tDYWxsZXIJAQh0aGlzT25seQEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQITbm8gcGF5bWVudHMgYWxsb3dlZAoBB3ByZXBhcmUCA2FjYwRpdGVtBAVwYXJ0cwkAtQkCBQRpdGVtAgFfBAdhc3NldElkCQCRAwIFBXBhcnRzAAAEBndlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAEEBm1pblZhbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAIJAJQKAgkAzQgCCAUDYWNjAl8xBQdhc3NldElkCQDNCAIJAM0IAggFA2FjYwJfMgkBDEludGVnZXJFbnRyeQIJARZiYXNrZXRXZWlnaHRCeUFzc2V0S2V5AQUHYXNzZXRJZAUGd2VpZ2h0CQEMSW50ZWdlckVudHJ5AgkBFU1pblRva2VuU3dhcEFtb3VudEtleQEFB2Fzc2V0SWQFBm1pblZhbAQBcgoAAiRsBRFhc3NldHNXZWlnaHRzTWlucwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3ByZXBhcmUCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAUBcgJfMgkBDEludGVnZXJFbnRyeQIJAQpiYXNrZXRES2V5AAUGZFBhcmFtCQEMSW50ZWdlckVudHJ5AgkBCmJhc2tldEtLZXkABQZrUGFyYW0JAQxJbnRlZ2VyRW50cnkCCQEKYmFza2V0QktleQAFBmJQYXJhbQkBDEludGVnZXJFbnRyeQIJARJiYXNrZXRMb2diRGVsdGFLZXkACQBtBgUKZGVsdGFQYXJhbQAGBQZiUGFyYW0ABgAGBQZIQUxGVVAJAQtTdHJpbmdFbnRyeQIJAQ9iYXNrZXRBc3NldHNLZXkACQC5CQIIBQFyAl8xBQNTRVAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETc3dhcFRva2VuVG9OZXV0cmlubwADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAixzd2FwVG9rZW5Ub05ldXRyaW5vIHJlcXVpcmUgb25seSBvbmUgcGF5bWVudAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEDGJhc2tldEFzc2V0cwkBBXZhbHVlAQkAoggBCQEPYmFza2V0QXNzZXRzS2V5AAQNcG10QXNzZXRJZFN0cgkA2AQBCQELdmFsdWVPckVsc2UCCAUDcG10B2Fzc2V0SWQFB1dBVkVTSUQDCQEBIQEJAQhjb250YWlucwIFDGJhc2tldEFzc2V0cwUNcG10QXNzZXRJZFN0cgkAAgEJAKwCAgkArAICBQ1wbXRBc3NldElkU3RyAh0gaXMgbm90IG9uZSBvZiBiYXNrZXQgdG9rZW5zOgUMYmFza2V0QXNzZXRzBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBAt0b3RhbExvY2tlZAkBD3RvdGFsTG9ja2VkUkVBRAICC291dE5ldXRyaW5vBQ1wbXRBc3NldElkU3RyBAlwbXRBbW91bnQIBQNwbXQGYW1vdW50BA9zYXZlVG90YWxMb2NrZWQJAPwHBAUEdGhpcwITaW50ZXJuYWxTYXZlSW50ZWdlcgkAzAgCCQEOdG90YWxMb2NrZWRLRVkCAgtvdXROZXV0cmlubwUNcG10QXNzZXRJZFN0cgkAzAgCCQBkAgULdG90YWxMb2NrZWQFCXBtdEFtb3VudAUDbmlsBQNuaWwDCQAAAgUPc2F2ZVRvdGFsTG9ja2VkBQ9zYXZlVG90YWxMb2NrZWQJAQpjb21tb25Td2FwBQILb3V0TmV1dHJpbm8FCXBtdEFtb3VudAUNcG10QXNzZXRJZFN0cgULdXNlckFkZHJlc3MFBnR4SWQ1OAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARRzd2FwTmV1dHJpbm9Ub0Jhc2tldAADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAi1zd2FwTmV1dHJpbm9Ub0Jhc2tldCByZXF1aXJlIG9ubHkgb25lIHBheW1lbnQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQJAAIBAjpPbmx5IGFwcHJvcHJpYXRlIE5ldXRyaW5vIHRva2VucyBhcmUgYWxsb3dlZCBmb3Igc3dhcHBpbmcuBAt1c2VyQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnR4SWQ1OAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBBJuZXV0cmlub0Fzc2V0SWRTdHIJANgEAQUPbmV1dHJpbm9Bc3NldElkBAt0b3RhbExvY2tlZAkBD3RvdGFsTG9ja2VkUkVBRAICCG91dE11bHRpBRJuZXV0cmlub0Fzc2V0SWRTdHIECXBtdEFtb3VudAgFA3BtdAZhbW91bnQED3NhdmVUb3RhbExvY2tlZAkA/AcEBQR0aGlzAhNpbnRlcm5hbFNhdmVJbnRlZ2VyCQDMCAIJAQ50b3RhbExvY2tlZEtFWQICCG91dE11bHRpBRJuZXV0cmlub0Fzc2V0SWRTdHIJAMwIAgkAZAIFC3RvdGFsTG9ja2VkBQlwbXRBbW91bnQFA25pbAUDbmlsAwkAAAIFD3NhdmVUb3RhbExvY2tlZAUPc2F2ZVRvdGFsTG9ja2VkCQEKY29tbW9uU3dhcAUCCG91dE11bHRpCAUDcG10BmFtb3VudAUSbmV1dHJpbm9Bc3NldElkU3RyBQt1c2VyQWRkcmVzcwUGdHhJZDU4CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBE2ludGVybmFsU2F2ZUludGVnZXICA2tleQZhbW91bnQDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAihpbnRlcm5hbFNhdmVJbnRlZ2VyIGlzIG5vdCBwdWJsaWMgbWV0aG9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQNrZXkFBmFtb3VudAUDbmlsAWkBCHdpdGhkcmF3AwdhY2NvdW50BWluZGV4CHN3YXBUeElkBAR0eElkCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNubyBwYXltZW50cyBhbGxvd2VkBA9uZXV0cmlub01ldHJpY3MJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIaY2FsY05ldXRpbm9NZXRyaWNzUkVBRE9OTFkFA25pbAUDbmlsBAJCUgkBBWFzSW50AQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFDG5NZXRyaWNJZHhCUgQLdXNlckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB2FjY291bnQECWRhdGFBcnJheQkBEnN3YXBEYXRhRmFpbE9yUkVBRAIFB2FjY291bnQFCHN3YXBUeElkBBBzZWxmVW5sb2NrSGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGF0YUFycmF5BRRzSWR4U2VsZlVubG9ja0hlaWdodAQIc3dhcFR5cGUJAJEDAgUJZGF0YUFycmF5BQxzSWR4U3dhcFR5cGUECGluQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGF0YUFycmF5BQxzSWR4SW5BbW91bnQECnN3YXBTdGF0dXMJAJEDAgUJZGF0YUFycmF5BQpzSWR4U3RhdHVzBAtzdGFydEhlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRhdGFBcnJheQUPc0lkeFN0YXJ0SGVpZ2h0BAdpbkFzc2V0CQCRAwIFCWRhdGFBcnJheQULc0lkeEluQXNzZXQEC3RvdGFsTG9ja2VkCQEPdG90YWxMb2NrZWRSRUFEAgUIc3dhcFR5cGUFB2luQXNzZXQEEXRvdGFsTG9ja2VkQnlVc2VyCQEVdG90YWxMb2NrZWRCeVVzZXJSRUFEAwUIc3dhcFR5cGUFB2FjY291bnQFB2luQXNzZXQEDHVubG9ja0hlaWdodAUQc2VsZlVubG9ja0hlaWdodAQLaW5kZXhIZWlnaHQJARVnZXRIZWlnaHRQcmljZUJ5SW5kZXgBBQVpbmRleAQPcHJldkluZGV4SGVpZ2h0CQEVZ2V0SGVpZ2h0UHJpY2VCeUluZGV4AQkAZQIFBWluZGV4AAEEDHByaWNlQnlJbmRleAkBD2dldFByaWNlSGlzdG9yeQEFC2luZGV4SGVpZ2h0AwUJaXNCbG9ja2VkCQEVZW1lcmdlbmN5U2h1dGRvd25GQUlMAAMJAQIhPQIFCnN3YXBTdGF0dXMCB1BFTkRJTkcJAAIBAh9zd2FwIGhhcyBiZWVuIGFscmVhZHkgcHJvY2Vzc2VkAwkAZgIFDHVubG9ja0hlaWdodAUGaGVpZ2h0CQACAQkArAICCQCsAgICEXBsZWFzZSB3YWl0IGZvcjogCQCkAwEFDHVubG9ja0hlaWdodAIfIGJsb2NrIGhlaWdodCB0byB3aXRoZHJhdyBmdW5kcwMDAwkAZgIFBWluZGV4BQpwcmljZUluZGV4BgkAZgIFDHVubG9ja0hlaWdodAULaW5kZXhIZWlnaHQGAwkBAiE9AgUPcHJldkluZGV4SGVpZ2h0AAAJAGcCBQ9wcmV2SW5kZXhIZWlnaHQFDHVubG9ja0hlaWdodAcJAQ5wcmljZUluZGV4RkFJTAUFBWluZGV4BQpwcmljZUluZGV4BQtpbmRleEhlaWdodAUMdW5sb2NrSGVpZ2h0BQ9wcmV2SW5kZXhIZWlnaHQEDXdpdGhkcmF3VHVwbGUJAQxjYWxjV2l0aGRyYXcFBQhzd2FwVHlwZQUIaW5BbW91bnQFDHByaWNlQnlJbmRleAUPbmV1dHJpbm9NZXRyaWNzBQdpbkFzc2V0BAxvdXROZXRBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl8xBApvdXRBc3NldElkCAUNd2l0aGRyYXdUdXBsZQJfMgQKb3V0U3VyZkFtdAgFDXdpdGhkcmF3VHVwbGUCXzMECnVubGVhc2VBbXQIBQ13aXRoZHJhd1R1cGxlAl81BAxvdXRGZWVBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl82BAtvdXRBbXRHcm9zcwgFDXdpdGhkcmF3VHVwbGUCXzcEDXdpdGhkcmF3UHJpY2UIBQ13aXRoZHJhd1R1cGxlAl84BA53aXRoZHJhd0Jhc2tldAgFDXdpdGhkcmF3VHVwbGUCXzkDAwkAAAIFCHN3YXBUeXBlAgtvdXROZXV0cmlubwkAZwIAAAULb3V0QW10R3Jvc3MHCQACAQITYmFsYW5jZSBlcXVhbHMgemVybwQNc3VyZkNvbmRpdGlvbgMJAGYCBQpvdXRTdXJmQW10AAAEC2lzc3VlUmVzdWx0CQD8BwQFD2F1Y3Rpb25Db250cmFjdAIJaXNzdWVTdXJmCQDMCAIFCm91dFN1cmZBbXQJAMwIAgUHYWNjb3VudAUDbmlsBQNuaWwDCQAAAgULaXNzdWVSZXN1bHQFC2lzc3VlUmVzdWx0AAAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAMJAAACBQ1zdXJmQ29uZGl0aW9uBQ1zdXJmQ29uZGl0aW9uBBF1bmxlYXNlSW52T3JFbXB0eQkA/AcEBQR0aGlzAhdpbnRlcm5hbFVubGVhc2VBbmRMZWFzZQkAzAgCBQp1bmxlYXNlQW10BQNuaWwFA25pbAMJAAACBRF1bmxlYXNlSW52T3JFbXB0eQURdW5sZWFzZUludk9yRW1wdHkECWduc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUXZ25zYnRDb250cm9sbGVyQ29udHJhY3QCFGduc2J0SW5mb1NZU1JFQURPTkxZCQDMCAICAAkAzAgCAAAJAMwIAgAABQNuaWwFA25pbAQNZ25zYnRBbXRUb3RhbAkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEAAQQVZ25zYnRBbXRGcm9tU3VyZlRvdGFsCQEFYXNJbnQBCQCRAwIJAQlhc0FueUxpc3QBCQCRAwIFCWduc2J0RGF0YQADAAMEDWNvbW1vbkFjdGlvbnMJAMwIAgkBDEludGVnZXJFbnRyeQIJARR0b3RhbExvY2tlZEJ5VXNlcktFWQMFCHN3YXBUeXBlBQdhY2NvdW50BQdpbkFzc2V0CQBlAgURdG90YWxMb2NrZWRCeVVzZXIFCGluQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG90YWxMb2NrZWRLRVkCBQhzd2FwVHlwZQUHaW5Bc3NldAkAZQIFC3RvdGFsTG9ja2VkBQhpbkFtb3VudAkAzAgCCQELU3RyaW5nRW50cnkCCQEHc3dhcEtFWQIFB2FjY291bnQFCHN3YXBUeElkCQEOZmluaXNoU3dhcERBVEELBQlkYXRhQXJyYXkFDXdpdGhkcmF3UHJpY2UFDG91dE5ldEFtb3VudAUMb3V0RmVlQW1vdW50BQx1bmxvY2tIZWlnaHQFBWluZGV4BQR0eElkBQpvdXRTdXJmQW10BQJCUgUOd2l0aGRyYXdCYXNrZXQFB2luQXNzZXQFA25pbAoBCGRlcG9zaXRzBAhzdXJmRmVlcwhuc2J0RmVlcwxzdXJmUGF5bWVudHMMbnNidFBheW1lbnRzBAtzdXJmRGVwb3NpdAMJAGYCBQhzdXJmRmVlcwAACQEFYXNJbnQBCQD8BwQFE3N1cmZTdGFraW5nQ29udHJhY3QCB2RlcG9zaXQFA25pbAUMc3VyZlBheW1lbnRzAAAEC25zYnREZXBvc2l0AwkAZgIFCG5zYnRGZWVzAAAJAQVhc0ludAEJAPwHBAUTbnNidFN0YWtpbmdDb250cmFjdAIHZGVwb3NpdAUDbmlsBQxuc2J0UGF5bWVudHMAAAkAZAIFC3N1cmZEZXBvc2l0BQtuc2J0RGVwb3NpdAoBCmRpdmlkZUZlZXMBCWZlZUFtb3VudAQIc3VyZkFtdDEDCQECIT0CBQ1nbnNidEFtdFRvdGFsAAAJAGsDBQlmZWVBbW91bnQFFWduc2J0QW10RnJvbVN1cmZUb3RhbAUNZ25zYnRBbXRUb3RhbAAABAhzdXJmQW10MgMJAQIhPQIFDWduc2J0QW10VG90YWwAAAkAawMFCWZlZUFtb3VudAkAZQIFBU1VTFQ2BQJCUgUFTVVMVDYAAAQHc3VyZkFtdAkAlgMBCQDMCAIFCHN1cmZBbXQxCQDMCAIFCHN1cmZBbXQyBQNuaWwEB25zYnRBbXQJAGUCBQlmZWVBbW91bnQFB3N1cmZBbXQJAMwIAgUHc3VyZkFtdAkAzAgCBQduc2J0QW10BQNuaWwECXRyYW5zZmVycwMJAAACBQhzd2FwVHlwZQIIb3V0TXVsdGkEBmJhc2tldAkAvAkCBQ53aXRoZHJhd0Jhc2tldAIBXwoBBmxvb3BlcgIDYWNjBGl0ZW0EAml0CQC1CQIFBGl0ZW0FB0xJU1RTRVAEC3RlbXBBc3NldElkCQDZBAEJAJEDAgUCaXQAAAQHYXNzZXRJZAMJAAACBQt0ZW1wQXNzZXRJZAUHV0FWRVNJRAUEdW5pdAULdGVtcEFzc2V0SWQECW5ldEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAml0AAIECWZlZUFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAml0AAMEBGZlZXMJAQpkaXZpZGVGZWVzAQUJZmVlQW1vdW50CQCXCgUJAM0IAggFA2FjYwJfMQkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFCW5ldEFtb3VudAUHYXNzZXRJZAkAzQgCCAUDYWNjAl8yCQEPQXR0YWNoZWRQYXltZW50AgUHYXNzZXRJZAkAkQMCBQRmZWVzAAAJAM0IAggFA2FjYwJfMwkBD0F0dGFjaGVkUGF5bWVudAIFB2Fzc2V0SWQJAJEDAgUEZmVlcwABCQBkAggFA2FjYwJfNAkAkQMCBQRmZWVzAAAJAGQCCAUDYWNjAl81CQCRAwIFBGZlZXMAAQQBcgoAAiRsBQZiYXNrZXQKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCXCgUFA25pbAUDbmlsBQNuaWwAAAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQZsb29wZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoECmRlcG9SZXN1bHQJAQhkZXBvc2l0cwQIBQFyAl80CAUBcgJfNQgFAXICXzIIBQFyAl8zCQCUCgIIBQFyAl8xBQpkZXBvUmVzdWx0BARmZWVzCQEKZGl2aWRlRmVlcwEFDG91dEZlZUFtb3VudAQKZGVwb1Jlc3VsdAkBCGRlcG9zaXRzBAkAkQMCBQRmZWVzAAAJAJEDAgUEZmVlcwABCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQpvdXRBc3NldElkCQCRAwIFBGZlZXMAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQpvdXRBc3NldElkCQCRAwIFBGZlZXMAAQUDbmlsCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFDG91dE5ldEFtb3VudAUKb3V0QXNzZXRJZAUDbmlsBQpkZXBvUmVzdWx0CQCUCgIJAM4IAgUNY29tbW9uQWN0aW9ucwgFCXRyYW5zZmVycwJfMQgFCXRyYW5zZmVycwJfMgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARdpbnRlcm5hbFVubGVhc2VBbmRMZWFzZQENdW5sZWFzZUFtb3VudAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECLGludGVybmFsVW5sZWFzZUFuZExlYXNlIGlzIG5vdCBwdWJsaWMgbWV0aG9kCQEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQEFDXVubGVhc2VBbW91bnQBaQESdHJhbnNmZXJVc2RuVG9Vc2VyAgZhbW91bnQEYWRkcgMJAQIhPQIIBQFpBmNhbGxlcgUPYXVjdGlvbkNvbnRyYWN0CQACAQIjT25seSBhdWN0aW9uIGNvbnRyYWN0IGlzIGF1dGhvcml6ZWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUEYWRkcgUGYW1vdW50BQ9uZXV0cmlub0Fzc2V0SWQFA25pbAFpAQthY2NlcHRXYXZlcwADAwkBAiE9AggFAWkGY2FsbGVyBQ9hdWN0aW9uQ29udHJhY3QJAQIhPQIIBQFpBmNhbGxlcgULZ292Q29udHJhY3QHCQACAQJDQ3VycmVudGx5IG9ubHkgYXVjdGlvbiBhbmQgZ292ZXJuYW5jZSBjb250cmFjdHMgYXJlIGFsbG93ZWQgdG8gY2FsbAkAlAoCCQEWcHJlcGFyZVVubGVhc2VBbmRMZWFzZQEAAAIHc3VjY2VzcwFpAQ9hcHByb3ZlTGVhc2luZ3MDBm5MaXN0Uwhncm91cE51bQRsQW10BAVuSWR4cwkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHBQNuaWwEB21uZ1B1YlMJAQt2YWx1ZU9yRWxzZQIJAKIIAQIcJXMlc19fY2ZnX19sZWFzaW5nTWFuYWdlclB1YgIsN0FVTVg1NHVrWU1ZdlBtbWE3eW9GZjVOalpoczRCdTVuejNFejlFVjhzdXIEBm1uZ1B1YgkA2QQBBQdtbmdQdWJTBA5ub2RlUmVnQWRkclN0cgkBC3ZhbHVlT3JFbHNlAgkAoggBAh8lcyVzX19jZmdfX25vZGVzUmVnaXN0cnlBZGRyZXNzAiMzUDl2S3FRS2pVZG1wWEFmaVdhdThrclJFWUFZMVhyNjlwRQQLbm9kZVJlZ0FkZHIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDm5vZGVSZWdBZGRyU3RyBBFsR3JvdXBOb2RlTGlzdEtFWQkBGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEFCGdyb3VwTnVtBApsR3JOb2RlT3B0CQCdCAIFBHRoaXMFEWxHcm91cE5vZGVMaXN0S0VZAwkBCWlzRGVmaW5lZAEFCmxHck5vZGVPcHQJAAIBCQCsAgIJAKwCAgIGZ3JvdXAgCQCkAwEFCGdyb3VwTnVtAhQgYWxyZWFkeSBpbml0aWFsaXplZAQFbkxpc3QJALUJAgUGbkxpc3RTBQNTRVAECGV4cENvdW50CQCQAwEFBW5JZHhzAwkBAiE9AggFAWkPY2FsbGVyUHVibGljS2V5BQZtbmdQdWIJAAIBAh5hcHByb3ZlTGVhc2luZ3Mgbm90IGF1dGhvcml6ZWQEDSR0MDQ0NDI1NDQ0ODcJAQxyZWFkTm9kZUluZm8BAAAEBm5BZGRyMAgFDSR0MDQ0NDI1NDQ0ODcCXzEECGxBbXRLRVkwCAUNJHQwNDQ0MjU0NDQ4NwJfMgQFbEFtdDAIBQ0kdDA0NDQyNTQ0NDg3Al8zBAdsSWRLRVkwCAUNJHQwNDQ0MjU0NDQ4NwJfNAQEbElkMAgFDSR0MDQ0NDI1NDQ0ODcCXzUEBW5ld0wwCQDECAIFBm5BZGRyMAkAZQIFBWxBbXQwCQBoAgUEbEFtdAUIZXhwQ291bnQECnZhbGlkYXRpb24JAPwHBAULbm9kZVJlZ0FkZHICGnZhbGlkYXRlQW5kQXBwcm92ZUxlYXNpbmdzCQDMCAIFBm5MaXN0UwUDbmlsBQNuaWwDCQAAAgUKdmFsaWRhdGlvbgUKdmFsaWRhdGlvbgoBI2ZvckVhY2hOb2RlVmFsaWRhdGVBbmRHZW5lcmF0ZUxlYXNlAgFhAWkEBG5vZGUJAJEDAgUFbkxpc3QFAWkEAmxhCQDECAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBG5vZGUFBGxBbXQJAM4IAgUBYQkAzAgCBQJsYQkAzAgCCQELQmluYXJ5RW50cnkCCQEWZ2V0TGVhc2VJZEJ5QWRkcmVzc0tleQEFBG5vZGUJAQVsY2FsYwEFAmxhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEaZ2V0TGVhc2VBbW91bnRCeUFkZHJlc3NLZXkBBQRub2RlBQRsQW10BQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBRFsR3JvdXBOb2RlTGlzdEtFWQUGbkxpc3RTCQDMCAIJAQtCaW5hcnlFbnRyeQIFB2xJZEtFWTAJAQVsY2FsYwEFBW5ld0wwCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhsQW10S0VZMAgFBW5ld0wwBmFtb3VudAkAzAgCCQELTGVhc2VDYW5jZWwBBQRsSWQwCQDMCAIFBW5ld0wwBQNuaWwKAAIkbAUFbklkeHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBI2ZvckVhY2hOb2RlVmFsaWRhdGVBbmRHZW5lcmF0ZUxlYXNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA4CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARFyZWJhbGFuY2VMZWFzaW5ncwIGYW1vdW50CGdyb3VwTnVtBAVuSWR4cwkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHBQNuaWwEB21uZ1B1YlMJAQt2YWx1ZU9yRWxzZQIJAKIIAQIcJXMlc19fY2ZnX19sZWFzaW5nTWFuYWdlclB1YgIsN0FVTVg1NHVrWU1ZdlBtbWE3eW9GZjVOalpoczRCdTVuejNFejlFVjhzdXIEBm1uZ1B1YgkA2QQBBQdtbmdQdWJTBBFsR3JvdXBOb2RlTGlzdEtFWQkBGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEFCGdyb3VwTnVtBAZuTGlzdFMJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzBRFsR3JvdXBOb2RlTGlzdEtFWQQFbkxpc3QJALUJAgUGbkxpc3RTBQNTRVADCQECIT0CCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBm1uZ1B1YgkAAgECIHJlYmFsYW5jZUxlYXNpbmdzIG5vdCBhdXRob3JpemVkBAp1bmxlYXNlQW10CQBkAgkAaQIFBmFtb3VudAkAkAMBBQVuTGlzdAABBA0kdDA0NTcyNzQ1Nzg5CQEMcmVhZE5vZGVJbmZvAQAABAZuQWRkcjAIBQ0kdDA0NTcyNzQ1Nzg5Al8xBAhsQW10S0VZMAgFDSR0MDQ1NzI3NDU3ODkCXzIEBWxBbXQwCAUNJHQwNDU3Mjc0NTc4OQJfMwQHbElkS0VZMAgFDSR0MDQ1NzI3NDU3ODkCXzQEBGxJZDAIBQ0kdDA0NTcyNzQ1Nzg5Al81BAVuZXdMMAkAxAgCBQZuQWRkcjAJAGQCBQVsQW10MAkAaAIFCnVubGVhc2VBbXQJAJADAQUFbkxpc3QKARRmb3JFYWNoTm9kZURvVW5sZWFzZQIBYQFpBARub2RlCQCRAwIFBW5MaXN0BQFpBAZsSWRLRVkJARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQUEbm9kZQQDbElkCQERQGV4dHJOYXRpdmUoMTA1MikCBQR0aGlzBQZsSWRLRVkEB2xBbXRLRVkJARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQEFBG5vZGUEBGxBbXQJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMFB2xBbXRLRVkEA3VsYQkBC0xlYXNlQ2FuY2VsAQkBBXZhbHVlAQUDbElkBAJsYQkAxAgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQRub2RlCQBlAgUEbEFtdAUKdW5sZWFzZUFtdAkAzggCBQFhCQDMCAIJAQtMZWFzZUNhbmNlbAEJAQV2YWx1ZQEFA2xJZAkAzAgCBQJsYQkAzAgCCQELQmluYXJ5RW50cnkCBQZsSWRLRVkJAQVsY2FsYwEFAmxhCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQdsQW10S0VZCAUCbGEGYW1vdW50BQNuaWwJAM4IAgoAAiRsBQVuSWR4cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEUZm9yRWFjaE5vZGVEb1VubGVhc2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAICQDMCAIJAQtCaW5hcnlFbnRyeQIFB2xJZEtFWTAJAQVsY2FsYwEFBW5ld0wwCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhsQW10S0VZMAgFBW5ld0wwBmFtb3VudAkAzAgCCQELTGVhc2VDYW5jZWwBBQRsSWQwCQDMCAIFBW5ld0wwBQNuaWwBaQEbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZAg51c2VyQWRkcmVzc1N0cglnbnNidERpZmYECWduc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUXZ25zYnRDb250cm9sbGVyQ29udHJhY3QCFGduc2J0SW5mb1NZU1JFQURPTkxZCQDMCAIFDnVzZXJBZGRyZXNzU3RyCQDMCAIAAAkAzAgCAAAFA25pbAUDbmlsBAhnbnNidEFtdAkAZAIJAQVhc0ludAEJAJEDAgUJZ25zYnREYXRhAAAFCWduc2J0RGlmZgQNZ25zYnRBbXRUb3RhbAkAZAIJAQVhc0ludAEJAJEDAgUJZ25zYnREYXRhAAEFCWduc2J0RGlmZgQNc3dhcExpbWl0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhVjYWxjU3dhcExpbWl0UkVBRE9OTFkJAMwIAgUIZ25zYnRBbXQFA25pbAUDbmlsBBZ0b2tlblN3YXBMaW1pdEluVXNkTWF4CQEFYXNJbnQBCQCRAwIFDXN3YXBMaW1pdERhdGEAAAQQdXNkblN3YXBMaW1pdE1heAkBBWFzSW50AQkAkQMCBQ1zd2FwTGltaXREYXRhAAIEDmxhc3RTd2FwSGVpZ2h0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARVrZXlVc2VyTGFzdFN3YXBIZWlnaHQBBQ51c2VyQWRkcmVzc1N0cgAABBdzd2FwTGltaXRUaW1lbGlmZUJsb2NrcwkBEnN3YXBzVGltZWZyYW1lUkVBRAAEGXBhc3NlZEJsb2Nrc0FmdGVyTGFzdFN3YXAJAGUCBQZoZWlnaHQFDmxhc3RTd2FwSGVpZ2h0BBFpc1N3YXBUaW1lbGlmZU5ldwkAZwIFGXBhc3NlZEJsb2Nrc0FmdGVyTGFzdFN3YXAFF3N3YXBMaW1pdFRpbWVsaWZlQmxvY2tzBBRzd2FwTGltaXRTcGVudEluVXNkbgMFEWlzU3dhcFRpbWVsaWZlTmV3AAAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBGGtleVN3YXBVc2VyU3BlbnRJblBlcmlvZAEFDnVzZXJBZGRyZXNzU3RyAAAEDmJsY2tzMkxtdFJlc2V0AwURaXNTd2FwVGltZWxpZmVOZXcAAAkAZQIFF3N3YXBMaW1pdFRpbWVsaWZlQmxvY2tzBRlwYXNzZWRCbG9ja3NBZnRlckxhc3RTd2FwCQCUCgIFA25pbAkAmQoHBRZ0b2tlblN3YXBMaW1pdEluVXNkTWF4BRRzd2FwTGltaXRTcGVudEluVXNkbgUOYmxja3MyTG10UmVzZXQFCGduc2J0QW10BQ1nbnNidEFtdFRvdGFsAAAFEHVzZG5Td2FwTGltaXRNYXgBaQEdY2FsY1dpdGhkcmF3UmVzdWx0U1lTUkVBRE9OTFkECHN3YXBUeXBlCGluQW1vdW50BXByaWNlB2luQXNzZXQED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwJAJQKAgUDbmlsCQEMY2FsY1dpdGhkcmF3BQUIc3dhcFR5cGUFCGluQW1vdW50BQVwcmljZQUPbmV1dHJpbm9NZXRyaWNzBQdpbkFzc2V0AWkBFHJlcGxhY2VDb21tdW5pdHlOb2RlBApvbGRBZGRyU3RyCm5ld0FkZHJTdHIIZ3JvdXBOdW0NcGVuYWx0eUFtb3VudAQHbW5nUHViUwkBC3ZhbHVlT3JFbHNlAgkAoggBAhwlcyVzX19jZmdfX2xlYXNpbmdNYW5hZ2VyUHViAiw3QVVNWDU0dWtZTVl2UG1tYTd5b0ZmNU5qWmhzNEJ1NW56M0V6OUVWOHN1cgQGbW5nUHViCQDZBAEFB21uZ1B1YlMDCQECIT0CCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBm1uZ1B1YgkAAgECI3JlcGxhY2VDb21tdW5pdHlOb2RlIG5vdCBhdXRob3JpemVkBAhncm91cEtleQkBGGdldExlYXNlR3JvdXBOb2RlTGlzdEtleQEFCGdyb3VwTnVtBA5ncm91cE5vZGVMaXN0UwkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMFCGdyb3VwS2V5AwkBASEBCQEIY29udGFpbnMCBQ5ncm91cE5vZGVMaXN0UwUKb2xkQWRkclN0cgkAAgEJAKwCAgkArAICCQCsAgICBkdyb3VwIAkApAMBBQhncm91cE51bQIaIGRvZXMgbm90IGNvbnRhaW4gYWRkcmVzcyAFCm9sZEFkZHJTdHIECWRvUmVwbGFjZQkA/AcEBRRub2RlUmVnaXN0cnlDb250cmFjdAITcmVwbGFjZUFwcHJvdmVkTm9kZQkAzAgCBQpvbGRBZGRyU3RyCQDMCAIFCm5ld0FkZHJTdHIJAMwIAgUIZ3JvdXBOdW0JAMwIAgUNcGVuYWx0eUFtb3VudAUDbmlsBQNuaWwDCQAAAgUJZG9SZXBsYWNlBQlkb1JlcGxhY2UEDW9sZExlYXNlSWRLZXkJARZnZXRMZWFzZUlkQnlBZGRyZXNzS2V5AQUKb2xkQWRkclN0cgQOb2xkTGVhc2VBbXRLZXkJARpnZXRMZWFzZUFtb3VudEJ5QWRkcmVzc0tleQEFCm9sZEFkZHJTdHIECGxlYXNlQW10CQERQGV4dHJOYXRpdmUoMTA1NSkBBQ5vbGRMZWFzZUFtdEtleQQNbmV3TGVhc2VJZEtleQkBFmdldExlYXNlSWRCeUFkZHJlc3NLZXkBBQpuZXdBZGRyU3RyBA5uZXdMZWFzZUFtdEtleQkBGmdldExlYXNlQW1vdW50QnlBZGRyZXNzS2V5AQUKbmV3QWRkclN0cgQIbmV3TGVhc2UJAMQIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUKbmV3QWRkclN0cgUIbGVhc2VBbXQEFXVwZGF0ZWRHcm91cE5vZGVMaXN0UwkAuQkCCQC1CQIFDmdyb3VwTm9kZUxpc3RTBQpvbGRBZGRyU3RyBQpuZXdBZGRyU3RyCQCUCgIJAMwIAgkBC0xlYXNlQ2FuY2VsAQkBEUBleHRyTmF0aXZlKDEwNTcpAQUNb2xkTGVhc2VJZEtleQkAzAgCCQELRGVsZXRlRW50cnkBBQ1vbGRMZWFzZUlkS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFDm9sZExlYXNlQW10S2V5CQDMCAIJAQtTdHJpbmdFbnRyeQIFCGdyb3VwS2V5BRV1cGRhdGVkR3JvdXBOb2RlTGlzdFMJAMwIAgUIbmV3TGVhc2UJAMwIAgkBC0JpbmFyeUVudHJ5AgUNbmV3TGVhc2VJZEtleQkBBWxjYWxjAQUIbmV3TGVhc2UJAMwIAgkBDEludGVnZXJFbnRyeQIFDm5ld0xlYXNlQW10S2V5BQhsZWFzZUFtdAUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAQTcHViS2V5QWRtaW5zTGlzdFN0cgkAuQkCCQDMCAICLEV4dEVFSzE5bm1LajltQ3BuV3l2RUVKRllBVExNY1ZFTXZvaGhVSGt5SE5tCQDMCAICLEV2NXB5NUZmQlFYOWNacFlLbmZRclRCNDlCeWY4UW1wWldlRFZSaW00eVY3CQDMCAICLERVdXVMalh1OThuQndaYzdmcXdDVGp0QTNublJ3Z1Ria01TcjVTVTJObURSCQDMCAICLERVdXVMalh1OThuQndaYzdmcXdDVGp0QTNublJ3Z1Ria01TcjVTVTJObURSBQNuaWwFA1NFUAQQcHViS2V5QWRtaW5zTGlzdAkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFD2NvbnRyb2xDb250cmFjdAIMJXNfX211bHRpc2lnBRNwdWJLZXlBZG1pbnNMaXN0U3RyBQNTRVAEBWNvdW50CQBkAgkAZAIJAGQCAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAAABAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwABCQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAABAAEAAAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAIJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAIAAQAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAwkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAwACAAADAwUJaXNCbG9ja2VkCQAAAgkBEUBleHRyTmF0aXZlKDEwNTMpAgUPY29udHJvbENvbnRyYWN0AhFpc19ibG9ja2VkX2NhbGxlcgkApQgBBQtnb3ZDb250cmFjdAcJAQ52YWxpZGF0ZVVwZGF0ZQEFAnR4BAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhVTcG9uc29yRmVlVHJhbnNhY3Rpb24ECXNwb25zb3JUeAUHJG1hdGNoMAMJARtjaGVja0lzVmFsaWRNaW5TcG9uc29yZWRGZWUBBQlzcG9uc29yVHgJAGcCBQVjb3VudAADBwkAZwIFBWNvdW50AAPjRafG", "height": 2471076, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: BXAAZ2zTLk6if5hjvoGMwRyXyVkcMi4ioKcvok957Yqy Next: EBgZWGytK72wKvEPqzpkp6om5531cv2UcZYCUkUeQbLC Diff:
OldNewDifferences
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 }
363- let dlog6 = valueOrElse(getInteger(basketLogbDeltaKey()), -18820642)
364- let d6 = valueOrElse(getInteger(basketDKey()), 50000)
365- let b6 = valueOrElse(getInteger(basketBKey()), 1250000)
366- let w6 = valueOrElse(getInteger(basketWeightByAssetKey(inAsset)), 166666)
363+ let dlog6 = value(getInteger(basketLogbDeltaKey()))
364+ let d6 = value(getInteger(basketDKey()))
365+ let b6 = value(getInteger(basketBKey()))
366+ 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))
504504
505505
506506 func applyFeesBasket (basketOut) = {
507- let k6 = valueOrElse(getInteger(basketKKey()), MULT6)
508- let d6 = valueOrElse(getInteger(basketDKey()), 50000)
507+ let k6 = value(getInteger(basketKKey()))
508+ 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)
596596 let blcks2LmtReset = swapParamsSTRUCT._3
597597 let usdnSwapLimitMax = swapParamsSTRUCT._7
598598 let minSwapAmount = minSwapAmountREAD(swapType, inAsset)
599- let totalLocked = totalLockedREAD(swapType, inAsset)
600599 let totalLockedByUser = totalLockedByUserREAD(swapType, userAddressStr, inAsset)
601600 let nodeAddress = getStakingNodeByIndex(0)
602601 let isSwapByNode = (nodeAddress == userAddressStr)
604603 then nodeBalanceLockIntervalREAD()
605604 else balanceLockIntervalREAD(swapType)
606605 let selfUnlockHeight = (height + balanceLockMaxInterval)
607- let pr = valueOrElse(getInteger(controlContract, keyPriceByAsset(inAsset)), MULT6)
606+ let pr = value(getInteger(controlContract, keyPriceByAsset(inAsset)))
608607 let swapUsdnVolume = if ((swapType == "outNeutrino"))
609608 then convertTokenToUsd(pmtAmount, pr)
610609 else pmtAmount
638637 else false)
639638 then prepareUnleaseAndLease(0)
640639 else nil
641- $Tuple2(([IntegerEntry(keySwapUserSpentInPeriod(userAddressStr), swapUsdnVolume), IntegerEntry(keyUserLastSwapHeight(userAddressStr), height), IntegerEntry(totalLockedByUserKEY(swapType, userAddressStr, inAsset), (totalLockedByUser + pmtAmount)), IntegerEntry(getBalanceUnlockBlockKey(userAddressStr), selfUnlockHeight), IntegerEntry(totalLockedKEY(swapType, inAsset), (totalLocked + pmtAmount)), StringEntry(swapKEY(userAddressStr, txId58), pendingSwapDATA(swapType, pmtAmount, selfUnlockHeight, inAsset))] ++ leasePart), unit)
640+ $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)
642641 }
643642 }
644643 }
799798 then throw("swapTokenToNeutrino require only one payment")
800799 else {
801800 let pmt = value(i.payments[0])
802- let basketAssets = valueOrElse(getString(basketAssetsKey()), "WAVES")
801+ let basketAssets = value(getString(basketAssetsKey()))
803802 let pmtAssetIdStr = toBase58String(valueOrElse(pmt.assetId, WAVESID))
804803 if (!(contains(basketAssets, pmtAssetIdStr)))
805804 then throw(((pmtAssetIdStr + " is not one of basket tokens:") + basketAssets))
806805 else {
807806 let userAddress = toString(i.caller)
808807 let txId58 = toBase58String(i.transactionId)
809- commonSwap("outNeutrino", pmt.amount, pmtAssetIdStr, userAddress, txId58)
808+ let totalLocked = totalLockedREAD("outNeutrino", pmtAssetIdStr)
809+ let pmtAmount = pmt.amount
810+ let saveTotalLocked = invoke(this, "internalSaveInteger", [totalLockedKEY("outNeutrino", pmtAssetIdStr), (totalLocked + pmtAmount)], nil)
811+ if ((saveTotalLocked == saveTotalLocked))
812+ then commonSwap("outNeutrino", pmtAmount, pmtAssetIdStr, userAddress, txId58)
813+ else throw("Strict value is not equal to itself.")
810814 }
811815 }
812816
822826 else {
823827 let userAddress = toString(i.caller)
824828 let txId58 = toBase58String(i.transactionId)
825- commonSwap("outMulti", pmt.amount, toBase58String(neutrinoAssetId), userAddress, txId58)
829+ let neutrinoAssetIdStr = toBase58String(neutrinoAssetId)
830+ let totalLocked = totalLockedREAD("outMulti", neutrinoAssetIdStr)
831+ let pmtAmount = pmt.amount
832+ let saveTotalLocked = invoke(this, "internalSaveInteger", [totalLockedKEY("outMulti", neutrinoAssetIdStr), (totalLocked + pmtAmount)], nil)
833+ if ((saveTotalLocked == saveTotalLocked))
834+ then commonSwap("outMulti", pmt.amount, neutrinoAssetIdStr, userAddress, txId58)
835+ else throw("Strict value is not equal to itself.")
826836 }
827837 }
838+
839+
840+
841+@Callable(i)
842+func internalSaveInteger (key,amount) = if ((i.caller != this))
843+ then throw("internalSaveInteger is not public method")
844+ else [IntegerEntry(key, amount)]
828845
829846
830847
10071024 if ((i.callerPublicKey != mngPub))
10081025 then throw("approveLeasings not authorized")
10091026 else {
1010- let $t04371943781 = readNodeInfo(0)
1011- let nAddr0 = $t04371943781._1
1012- let lAmtKEY0 = $t04371943781._2
1013- let lAmt0 = $t04371943781._3
1014- let lIdKEY0 = $t04371943781._4
1015- let lId0 = $t04371943781._5
1027+ let $t04442544487 = readNodeInfo(0)
1028+ let nAddr0 = $t04442544487._1
1029+ let lAmtKEY0 = $t04442544487._2
1030+ let lAmt0 = $t04442544487._3
1031+ let lIdKEY0 = $t04442544487._4
1032+ let lId0 = $t04442544487._5
10161033 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
10171034 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
10181035 if ((validation == validation))
10571074 then throw("rebalanceLeasings not authorized")
10581075 else {
10591076 let unleaseAmt = ((amount / size(nList)) + 1)
1060- let $t04502145083 = readNodeInfo(0)
1061- let nAddr0 = $t04502145083._1
1062- let lAmtKEY0 = $t04502145083._2
1063- let lAmt0 = $t04502145083._3
1064- let lIdKEY0 = $t04502145083._4
1065- let lId0 = $t04502145083._5
1077+ let $t04572745789 = readNodeInfo(0)
1078+ let nAddr0 = $t04572745789._1
1079+ let lAmtKEY0 = $t04572745789._2
1080+ let lAmt0 = $t04572745789._3
1081+ let lIdKEY0 = $t04572745789._4
1082+ let lId0 = $t04572745789._5
10661083 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
10671084 func forEachNodeDoUnlease (a,i) = {
10681085 let node = nList[i]
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
55
66
77 func lcalc (l) = calculateLeaseId(l)
88
99
1010 func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0)
1111
1212
1313 func getStringByKey (key) = valueOrElse(getString(this, key), "")
1414
1515
1616 func getBoolByKey (key) = valueOrElse(getBoolean(this, key), false)
1717
1818
1919 func getNumberByAddressAndKey (address,key) = valueOrElse(getInteger(address, key), 0)
2020
2121
2222 func getStringByAddressAndKey (address,key) = valueOrElse(getString(addressFromStringValue(address), key), "")
2323
2424
2525 func getBoolByAddressAndKey (address,key) = valueOrElse(getBoolean(address, key), false)
2626
2727
2828 func asAnyList (v) = match v {
2929 case l: List[Any] =>
3030 l
3131 case _ =>
3232 throw("fail to cast into List[Any]")
3333 }
3434
3535
3636 func asString (v) = match v {
3737 case s: String =>
3838 s
3939 case _ =>
4040 throw("fail to cast into String")
4141 }
4242
4343
4444 func asInt (v) = match v {
4545 case i: Int =>
4646 i
4747 case _ =>
4848 throw("fail to cast into Int")
4949 }
5050
5151
5252 func asBytes (val) = match val {
5353 case valByte: ByteVector =>
5454 valByte
5555 case _ =>
5656 throw("fail to cast into ByteVector")
5757 }
5858
5959
6060 func asPayment (v) = match v {
6161 case p: AttachedPayment =>
6262 p
6363 case _ =>
6464 throw("fail to cast into AttachedPayment")
6565 }
6666
6767
6868 func asSwapParamsSTRUCT (v) = match v {
6969 case struct: (Int, Int, Int, Int, Int, Int, Int) =>
7070 struct
7171 case _ =>
7272 throw("fail to cast into Tuple5 ints")
7373 }
7474
7575
7676 let SEP = "__"
7777
7878 let LISTSEP = ":"
7979
8080 let MULT8 = 100000000
8181
8282 let MULT6 = 1000000
8383
8484 let DEFAULTSWAPFEE = 20000
8585
8686 let BRPROTECTED = 100000
8787
8888 let WAVESID = base58'WAVES'
8989
9090 let nMetricIdxPrice = 0
9191
9292 let nMetricIdxUsdnLockedBalance = 1
9393
9494 let nMetricIdxWavesLockedBalance = 2
9595
9696 let nMetricIdxReserve = 3
9797
9898 let nMetricIdxReserveInUsdn = 4
9999
100100 let nMetricIdxUsdnSupply = 5
101101
102102 let nMetricIdxSurplus = 6
103103
104104 let nMetricIdxSurplusPercent = 7
105105
106106 let nMetricIdxBR = 8
107107
108108 let nMetricIdxNsbtSupply = 9
109109
110110 let nMetricIdxMaxNsbtSupply = 10
111111
112112 let nMetricIdxSurfSupply = 11
113113
114114 let nMetricUsdnUsdtPeg = 12
115115
116116 let nMetricCurrentPriceAdj = 13
117117
118118 let nMetricBasketInfo = 14
119119
120120 let nMetricWeightedPrice = 15
121121
122122 let nMetricTotalReservesUsd = 16
123123
124124 let IdxControlCfgNeutrinoDapp = 1
125125
126126 let IdxControlCfgAuctionDapp = 2
127127
128128 let IdxControlCfgRpdDapp = 3
129129
130130 let IdxControlCfgMathDapp = 4
131131
132132 let IdxControlCfgLiquidationDapp = 5
133133
134134 let IdxControlCfgRestDapp = 6
135135
136136 let IdxControlCfgNodeRegistryDapp = 7
137137
138138 let IdxControlCfgNsbtStakingDapp = 8
139139
140140 let IdxControlCfgMediatorDapp = 9
141141
142142 let IdxControlCfgSurfStakingDapp = 10
143143
144144 let IdxControlCfgGnsbtControllerDapp = 11
145145
146146 let IdxControlCfgRestV2Dapp = 12
147147
148148 let IdxControlCfgGovernanceDapp = 13
149149
150150 func keyControlAddress () = "%s%s__config__controlAddress"
151151
152152
153153 func keyControlCfg () = "%s__controlConfig"
154154
155155
156156 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
157157
158158
159159 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
160160
161161
162162 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3N4NS7d4Jo9a6F14LiFUKKYVdUkkf2eP4Zx"))
163163
164164 let controlCfg = readControlCfgOrFail(controlContract)
165165
166166 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
167167
168168 let nsbtStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgNsbtStakingDapp)
169169
170170 let surfStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgSurfStakingDapp)
171171
172172 let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
173173
174174 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
175175
176176 let nodeRegistryContract = getContractAddressOrFail(controlCfg, IdxControlCfgNodeRegistryDapp)
177177
178178 let govContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
179179
180180 let NeutrinoAssetIdKey = "neutrino_asset_id"
181181
182182 let BondAssetIdKey = "bond_asset_id"
183183
184184 let AuctionContractKey = "auction_contract"
185185
186186 let NsbtStakingContractKey = "nsbtStakingContract"
187187
188188 let LiquidationContractKey = "liquidation_contract"
189189
190190 let RPDContractKey = "rpd_contract"
191191
192192 let ContolContractKey = "control_contract"
193193
194194 let MathContractKey = "math_contract"
195195
196196 let BalanceWavesLockIntervalKey = "balance_waves_lock_interval"
197197
198198 let BalanceNeutrinoLockIntervalKey = "balance_neutrino_lock_interval"
199199
200200 func MinTokenSwapAmountKey (assetId) = ("min_outNeutrino_swap_amount_" + assetId)
201201
202202
203203 let MinNeutrinoSwapAmountKey = "min_outMulti_swap_amount"
204204
205205 let 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 }
363- let dlog6 = valueOrElse(getInteger(basketLogbDeltaKey()), -18820642)
364- let d6 = valueOrElse(getInteger(basketDKey()), 50000)
365- let b6 = valueOrElse(getInteger(basketBKey()), 1250000)
366- let w6 = valueOrElse(getInteger(basketWeightByAssetKey(inAsset)), 166666)
363+ let dlog6 = value(getInteger(basketLogbDeltaKey()))
364+ let d6 = value(getInteger(basketDKey()))
365+ let b6 = value(getInteger(basketBKey()))
366+ 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) = {
507- let k6 = valueOrElse(getInteger(basketKKey()), MULT6)
508- let d6 = valueOrElse(getInteger(basketDKey()), 50000)
507+ let k6 = value(getInteger(basketKKey()))
508+ 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)
599- let totalLocked = totalLockedREAD(swapType, inAsset)
600599 let totalLockedByUser = totalLockedByUserREAD(swapType, userAddressStr, inAsset)
601600 let nodeAddress = getStakingNodeByIndex(0)
602601 let isSwapByNode = (nodeAddress == userAddressStr)
603602 let balanceLockMaxInterval = if (isSwapByNode)
604603 then nodeBalanceLockIntervalREAD()
605604 else balanceLockIntervalREAD(swapType)
606605 let selfUnlockHeight = (height + balanceLockMaxInterval)
607- let pr = valueOrElse(getInteger(controlContract, keyPriceByAsset(inAsset)), MULT6)
606+ let pr = value(getInteger(controlContract, keyPriceByAsset(inAsset)))
608607 let swapUsdnVolume = if ((swapType == "outNeutrino"))
609608 then convertTokenToUsd(pmtAmount, pr)
610609 else pmtAmount
611610 let swapLimitMax = if ((swapType == "outNeutrino"))
612611 then tokenSwapLimitUsd
613612 else usdnSwapLimitMax
614613 if ((minSwapAmount > pmtAmount))
615614 then minSwapAmountFAIL(swapType, minSwapAmount)
616615 else if (if (!(isSwapByNode))
617616 then (swapLimitSpent > 0)
618617 else false)
619618 then throw(("You have exceeded swap limit! Next allowed swap height is " + toString((height + blcks2LmtReset))))
620619 else if (if (!(isSwapByNode))
621620 then (swapUsdnVolume > swapLimitMax)
622621 else false)
623622 then throw(((("You have exceeded your swap limit! Requested: " + toString(swapUsdnVolume)) + ", available: ") + toString(swapLimitMax)))
624623 else if (isBlocked)
625624 then emergencyShutdownFAIL()
626625 else {
627626 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
628627 let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
629628 let weightedPrice = asInt(neutrinoMetrics[nMetricWeightedPrice])
630629 let out = convertBasketItemToNeutrino(pmtAmount, inAsset, basketInfo, weightedPrice)
631630 if (if ((swapType == "outNeutrino"))
632631 then (0 >= out[1])
633632 else false)
634633 then throw((((((("Net amount is non-positive, cannot swap. (gross, net, fee) = (" + toString(out[0])) + ", ") + toString(out[1])) + ", ") + toString(out[2])) + ")"))
635634 else {
636635 let leasePart = if (if ((swapType == "outNeutrino"))
637636 then (inAsset == "WAVES")
638637 else false)
639638 then prepareUnleaseAndLease(0)
640639 else nil
641- $Tuple2(([IntegerEntry(keySwapUserSpentInPeriod(userAddressStr), swapUsdnVolume), IntegerEntry(keyUserLastSwapHeight(userAddressStr), height), IntegerEntry(totalLockedByUserKEY(swapType, userAddressStr, inAsset), (totalLockedByUser + pmtAmount)), IntegerEntry(getBalanceUnlockBlockKey(userAddressStr), selfUnlockHeight), IntegerEntry(totalLockedKEY(swapType, inAsset), (totalLocked + pmtAmount)), StringEntry(swapKEY(userAddressStr, txId58), pendingSwapDATA(swapType, pmtAmount, selfUnlockHeight, inAsset))] ++ leasePart), unit)
640+ $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)
642641 }
643642 }
644643 }
645644
646645
647646 let bFuncIdxSurf = 0
648647
649648 let bFuncIdxWaves = 1
650649
651650 let bFuncIdxUsdn = 2
652651
653652 let bFuncIdxReserveStart = 3
654653
655654 let bFuncIdxSupplyStart = 4
656655
657656 let bFuncIdxBRStart = 5
658657
659658 let bFuncIdxReserveEnd = 6
660659
661660 let bFuncIdxSupplyEnd = 7
662661
663662 let bFuncIdxBREnd = 8
664663
665664 let bFuncIdxRest = 9
666665
667666 let bFuncIdxWavesPrice = 10
668667
669668 func calcWithdrawT2U (inAmount,inAsset,basketInfo,weightedPrice) = {
670669 let outAmt = convertBasketItemToNeutrino(inAmount, inAsset, basketInfo, weightedPrice)
671670 $Tuple12(outAmt[0], neutrinoAssetId, 0, inAsset, 0, weightedPrice, inAmount, 0, 0, 0, nil, [outAmt[1], outAmt[2]])
672671 }
673672
674673
675674 func calcWithdrawU2Basket (usdnIn,basketInfo,neutrinoSupply) = {
676675 let outAmtGross = convertNeutrinoToBasket(usdnIn, basketInfo, neutrinoSupply)
677676 $Tuple12(outAmtGross._2, unit, 0, neutrinoAssetId, outAmtGross._2, outAmtGross._3, usdnIn, neutrinoSupply, usdnIn, 0, outAmtGross._1, nil)
678677 }
679678
680679
681680 func calcWithdraw (swapType,inAmount,price,neutrinoMetrics,inAsset) = {
682681 let neutrinoSupply = asInt(neutrinoMetrics[nMetricIdxUsdnSupply])
683682 let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
684683 let weightedPrice = asInt(neutrinoMetrics[nMetricWeightedPrice])
685684 let outDataTuple = if ((swapType == "outNeutrino"))
686685 then calcWithdrawT2U(inAmount, inAsset, basketInfo, weightedPrice)
687686 else if ((swapType == "outMulti"))
688687 then calcWithdrawU2Basket(inAmount, basketInfo, neutrinoSupply)
689688 else throw(("Unsupported swap type " + swapType))
690689 let outAmtGross = outDataTuple._1
691690 let outAssetId = outDataTuple._2
692691 let inAmtToSurfPart = outDataTuple._3
693692 let inAssetId = outDataTuple._4
694693 let unleaseAmt = outDataTuple._5
695694 let withdrawPrice = outDataTuple._6
696695 let basketData = outDataTuple._11
697696 let netFeeData = outDataTuple._12
698697 let outNetAmt = if ((swapType == "outNeutrino"))
699698 then netFeeData[0]
700699 else 0
701700 let outFeeAmt = if ((swapType == "outNeutrino"))
702701 then netFeeData[1]
703702 else 0
704703 let outSurfAmt = if ((0 >= inAmtToSurfPart))
705704 then 0
706705 else asInt(asAnyList(invoke(mathContract, "surfFunctionREADONLY", [inAmtToSurfPart, inAssetId], nil))[bFuncIdxSurf])
707706 let withdrawBasket = if ((swapType == "outMulti"))
708707 then applyFeesBasket(basketData)
709708 else ""
710709 $Tuple9(outNetAmt, outAssetId, outSurfAmt, inAmtToSurfPart, unleaseAmt, outFeeAmt, outAmtGross, withdrawPrice, withdrawBasket)
711710 }
712711
713712
714713 func keyApplyInProgress () = "%s__applyInProgress"
715714
716715
717716 func keyProposalDataById (proposalId) = ("%s%d__proposalData__" + toString(proposalId))
718717
719718
720719 let govIdxTxIds = 9
721720
722721 func validateUpdate (tx) = match tx {
723722 case o: Order =>
724723 throw("Orders aren't allowed")
725724 case t: DataTransaction|SponsorFeeTransaction|SetScriptTransaction|CreateAliasTransaction|LeaseCancelTransaction|LeaseTransaction|IssueTransaction|InvokeExpressionTransaction|UpdateAssetInfoTransaction|InvokeScriptTransaction|SetAssetScriptTransaction|TransferTransaction|ExchangeTransaction|MassTransferTransaction|BurnTransaction|ReissueTransaction =>
726725 let txId = toBase58String(t.id)
727726 let proposalId = valueOrErrorMessage(getInteger(govContract, keyApplyInProgress()), "Apply is not happening")
728727 let txList = split(split(getStringOrFail(govContract, keyProposalDataById(proposalId)), SEP)[govIdxTxIds], LISTSEP)
729728 if (!(isDefined(indexOf(txList, txId))))
730729 then throw(((("Unknown txId: " + txId) + " for proposalId=") + toString(proposalId)))
731730 else true
732731 case _ =>
733732 throw("Match error")
734733 }
735734
736735
737736 @Callable(i)
738737 func constructorV1 (neutrinoAssetIdPrm,bondAssetIdPrm,auctionContractPrm,liquidationContractPrm,rpdContractPrm,nodeOracleProviderPubKeyPrm,balanceWavesLockIntervalPrm,balanceNeutrinoLockIntervalPrm,minWavesSwapAmountPrm,minNeutrinoSwapAmountPrm,neutrinoOutFeePartPrm,wavesOutFeePartPrm) = {
739738 let checkCaller = thisOnly(i)
740739 if ((checkCaller == checkCaller))
741740 then if ((size(i.payments) != 0))
742741 then throw("no payments allowed")
743742 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)]
744743 else throw("Strict value is not equal to itself.")
745744 }
746745
747746
748747
749748 @Callable(i)
750749 func constructorV2 (mathContract,nsbtStakingContract,swapsTimeframeBlocks) = {
751750 let checkCaller = thisOnly(i)
752751 if ((checkCaller == checkCaller))
753752 then if ((size(i.payments) != 0))
754753 then throw("no payments allowed")
755754 else [StringEntry(MathContractKey, mathContract), StringEntry(NsbtStakingContractKey, nsbtStakingContract), IntegerEntry(swapsTimeframeKEY(), swapsTimeframeBlocks)]
756755 else throw("Strict value is not equal to itself.")
757756 }
758757
759758
760759
761760 @Callable(i)
762761 func constructorV3 (assetsWeightsMins,dParam,kParam,bParam,deltaParam) = {
763762 let checkCaller = thisOnly(i)
764763 if ((checkCaller == checkCaller))
765764 then if ((size(i.payments) != 0))
766765 then throw("no payments allowed")
767766 else {
768767 func prepare (acc,item) = {
769768 let parts = split(item, "_")
770769 let assetId = parts[0]
771770 let weight = parseIntValue(parts[1])
772771 let minVal = parseIntValue(parts[2])
773772 $Tuple2((acc._1 :+ assetId), ((acc._2 :+ IntegerEntry(basketWeightByAssetKey(assetId), weight)) :+ IntegerEntry(MinTokenSwapAmountKey(assetId), minVal)))
774773 }
775774
776775 let r = {
777776 let $l = assetsWeightsMins
778777 let $s = size($l)
779778 let $acc0 = $Tuple2(nil, nil)
780779 func $f0_1 ($a,$i) = if (($i >= $s))
781780 then $a
782781 else prepare($a, $l[$i])
783782
784783 func $f0_2 ($a,$i) = if (($i >= $s))
785784 then $a
786785 else throw("List size exceeds 10")
787786
788787 $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)
789788 }
790789 (((((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)))
791790 }
792791 else throw("Strict value is not equal to itself.")
793792 }
794793
795794
796795
797796 @Callable(i)
798797 func swapTokenToNeutrino () = if ((size(i.payments) != 1))
799798 then throw("swapTokenToNeutrino require only one payment")
800799 else {
801800 let pmt = value(i.payments[0])
802- let basketAssets = valueOrElse(getString(basketAssetsKey()), "WAVES")
801+ let basketAssets = value(getString(basketAssetsKey()))
803802 let pmtAssetIdStr = toBase58String(valueOrElse(pmt.assetId, WAVESID))
804803 if (!(contains(basketAssets, pmtAssetIdStr)))
805804 then throw(((pmtAssetIdStr + " is not one of basket tokens:") + basketAssets))
806805 else {
807806 let userAddress = toString(i.caller)
808807 let txId58 = toBase58String(i.transactionId)
809- commonSwap("outNeutrino", pmt.amount, pmtAssetIdStr, userAddress, txId58)
808+ let totalLocked = totalLockedREAD("outNeutrino", pmtAssetIdStr)
809+ let pmtAmount = pmt.amount
810+ let saveTotalLocked = invoke(this, "internalSaveInteger", [totalLockedKEY("outNeutrino", pmtAssetIdStr), (totalLocked + pmtAmount)], nil)
811+ if ((saveTotalLocked == saveTotalLocked))
812+ then commonSwap("outNeutrino", pmtAmount, pmtAssetIdStr, userAddress, txId58)
813+ else throw("Strict value is not equal to itself.")
810814 }
811815 }
812816
813817
814818
815819 @Callable(i)
816820 func swapNeutrinoToBasket () = if ((size(i.payments) != 1))
817821 then throw("swapNeutrinoToBasket require only one payment")
818822 else {
819823 let pmt = value(i.payments[0])
820824 if ((pmt.assetId != neutrinoAssetId))
821825 then throw("Only appropriate Neutrino tokens are allowed for swapping.")
822826 else {
823827 let userAddress = toString(i.caller)
824828 let txId58 = toBase58String(i.transactionId)
825- commonSwap("outMulti", pmt.amount, toBase58String(neutrinoAssetId), userAddress, txId58)
829+ let neutrinoAssetIdStr = toBase58String(neutrinoAssetId)
830+ let totalLocked = totalLockedREAD("outMulti", neutrinoAssetIdStr)
831+ let pmtAmount = pmt.amount
832+ let saveTotalLocked = invoke(this, "internalSaveInteger", [totalLockedKEY("outMulti", neutrinoAssetIdStr), (totalLocked + pmtAmount)], nil)
833+ if ((saveTotalLocked == saveTotalLocked))
834+ then commonSwap("outMulti", pmt.amount, neutrinoAssetIdStr, userAddress, txId58)
835+ else throw("Strict value is not equal to itself.")
826836 }
827837 }
838+
839+
840+
841+@Callable(i)
842+func internalSaveInteger (key,amount) = if ((i.caller != this))
843+ then throw("internalSaveInteger is not public method")
844+ else [IntegerEntry(key, amount)]
828845
829846
830847
831848 @Callable(i)
832849 func withdraw (account,index,swapTxId) = {
833850 let txId = toBase58String(i.transactionId)
834851 if ((size(i.payments) != 0))
835852 then throw("no payments allowed")
836853 else {
837854 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
838855 let BR = asInt(neutrinoMetrics[nMetricIdxBR])
839856 let userAddress = addressFromStringValue(account)
840857 let dataArray = swapDataFailOrREAD(account, swapTxId)
841858 let selfUnlockHeight = parseIntValue(dataArray[sIdxSelfUnlockHeight])
842859 let swapType = dataArray[sIdxSwapType]
843860 let inAmount = parseIntValue(dataArray[sIdxInAmount])
844861 let swapStatus = dataArray[sIdxStatus]
845862 let startHeight = parseIntValue(dataArray[sIdxStartHeight])
846863 let inAsset = dataArray[sIdxInAsset]
847864 let totalLocked = totalLockedREAD(swapType, inAsset)
848865 let totalLockedByUser = totalLockedByUserREAD(swapType, account, inAsset)
849866 let unlockHeight = selfUnlockHeight
850867 let indexHeight = getHeightPriceByIndex(index)
851868 let prevIndexHeight = getHeightPriceByIndex((index - 1))
852869 let priceByIndex = getPriceHistory(indexHeight)
853870 if (isBlocked)
854871 then emergencyShutdownFAIL()
855872 else if ((swapStatus != "PENDING"))
856873 then throw("swap has been already processed")
857874 else if ((unlockHeight > height))
858875 then throw((("please wait for: " + toString(unlockHeight)) + " block height to withdraw funds"))
859876 else if (if (if ((index > priceIndex))
860877 then true
861878 else (unlockHeight > indexHeight))
862879 then true
863880 else if ((prevIndexHeight != 0))
864881 then (prevIndexHeight >= unlockHeight)
865882 else false)
866883 then priceIndexFAIL(index, priceIndex, indexHeight, unlockHeight, prevIndexHeight)
867884 else {
868885 let withdrawTuple = calcWithdraw(swapType, inAmount, priceByIndex, neutrinoMetrics, inAsset)
869886 let outNetAmount = withdrawTuple._1
870887 let outAssetId = withdrawTuple._2
871888 let outSurfAmt = withdrawTuple._3
872889 let unleaseAmt = withdrawTuple._5
873890 let outFeeAmount = withdrawTuple._6
874891 let outAmtGross = withdrawTuple._7
875892 let withdrawPrice = withdrawTuple._8
876893 let withdrawBasket = withdrawTuple._9
877894 if (if ((swapType == "outNeutrino"))
878895 then (0 >= outAmtGross)
879896 else false)
880897 then throw("balance equals zero")
881898 else {
882899 let surfCondition = if ((outSurfAmt > 0))
883900 then {
884901 let issueResult = invoke(auctionContract, "issueSurf", [outSurfAmt, account], nil)
885902 if ((issueResult == issueResult))
886903 then 0
887904 else throw("Strict value is not equal to itself.")
888905 }
889906 else 0
890907 if ((surfCondition == surfCondition))
891908 then {
892909 let unleaseInvOrEmpty = invoke(this, "internalUnleaseAndLease", [unleaseAmt], nil)
893910 if ((unleaseInvOrEmpty == unleaseInvOrEmpty))
894911 then {
895912 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", ["", 0, 0], nil))
896913 let gnsbtAmtTotal = asInt(gnsbtData[1])
897914 let gnsbtAmtFromSurfTotal = asInt(asAnyList(gnsbtData[3])[3])
898915 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))]
899916 func deposits (surfFees,nsbtFees,surfPayments,nsbtPayments) = {
900917 let surfDeposit = if ((surfFees > 0))
901918 then asInt(invoke(surfStakingContract, "deposit", nil, surfPayments))
902919 else 0
903920 let nsbtDeposit = if ((nsbtFees > 0))
904921 then asInt(invoke(nsbtStakingContract, "deposit", nil, nsbtPayments))
905922 else 0
906923 (surfDeposit + nsbtDeposit)
907924 }
908925
909926 func divideFees (feeAmount) = {
910927 let surfAmt1 = if ((gnsbtAmtTotal != 0))
911928 then fraction(feeAmount, gnsbtAmtFromSurfTotal, gnsbtAmtTotal)
912929 else 0
913930 let surfAmt2 = if ((gnsbtAmtTotal != 0))
914931 then fraction(feeAmount, (MULT6 - BR), MULT6)
915932 else 0
916933 let surfAmt = max([surfAmt1, surfAmt2])
917934 let nsbtAmt = (feeAmount - surfAmt)
918935 [surfAmt, nsbtAmt]
919936 }
920937
921938 let transfers = if ((swapType == "outMulti"))
922939 then {
923940 let basket = split_4C(withdrawBasket, "_")
924941 func looper (acc,item) = {
925942 let it = split(item, LISTSEP)
926943 let tempAssetId = fromBase58String(it[0])
927944 let assetId = if ((tempAssetId == WAVESID))
928945 then unit
929946 else tempAssetId
930947 let netAmount = parseIntValue(it[2])
931948 let feeAmount = parseIntValue(it[3])
932949 let fees = divideFees(feeAmount)
933950 $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]))
934951 }
935952
936953 let r = {
937954 let $l = basket
938955 let $s = size($l)
939956 let $acc0 = $Tuple5(nil, nil, nil, 0, 0)
940957 func $f0_1 ($a,$i) = if (($i >= $s))
941958 then $a
942959 else looper($a, $l[$i])
943960
944961 func $f0_2 ($a,$i) = if (($i >= $s))
945962 then $a
946963 else throw("List size exceeds 10")
947964
948965 $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)
949966 }
950967 let depoResult = deposits(r._4, r._5, r._2, r._3)
951968 $Tuple2(r._1, depoResult)
952969 }
953970 else {
954971 let fees = divideFees(outFeeAmount)
955972 let depoResult = deposits(fees[0], fees[1], [AttachedPayment(outAssetId, fees[0])], [AttachedPayment(outAssetId, fees[1])])
956973 $Tuple2([ScriptTransfer(userAddress, outNetAmount, outAssetId)], depoResult)
957974 }
958975 $Tuple2((commonActions ++ transfers._1), transfers._2)
959976 }
960977 else throw("Strict value is not equal to itself.")
961978 }
962979 else throw("Strict value is not equal to itself.")
963980 }
964981 }
965982 }
966983 }
967984
968985
969986
970987 @Callable(i)
971988 func internalUnleaseAndLease (unleaseAmount) = if ((i.caller != this))
972989 then throw("internalUnleaseAndLease is not public method")
973990 else prepareUnleaseAndLease(unleaseAmount)
974991
975992
976993
977994 @Callable(i)
978995 func transferUsdnToUser (amount,addr) = if ((i.caller != auctionContract))
979996 then throw("Only auction contract is authorized")
980997 else [ScriptTransfer(addressFromStringValue(addr), amount, neutrinoAssetId)]
981998
982999
9831000
9841001 @Callable(i)
9851002 func acceptWaves () = if (if ((i.caller != auctionContract))
9861003 then (i.caller != govContract)
9871004 else false)
9881005 then throw("Currently only auction and governance contracts are allowed to call")
9891006 else $Tuple2(prepareUnleaseAndLease(0), "success")
9901007
9911008
9921009
9931010 @Callable(i)
9941011 func approveLeasings (nListS,groupNum,lAmt) = {
9951012 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
9961013 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
9971014 let mngPub = fromBase58String(mngPubS)
9981015 let nodeRegAddrStr = valueOrElse(getString("%s%s__cfg__nodesRegistryAddress"), "3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE")
9991016 let nodeRegAddr = addressFromStringValue(nodeRegAddrStr)
10001017 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
10011018 let lGrNodeOpt = getString(this, lGroupNodeListKEY)
10021019 if (isDefined(lGrNodeOpt))
10031020 then throw((("group " + toString(groupNum)) + " already initialized"))
10041021 else {
10051022 let nList = split(nListS, SEP)
10061023 let expCount = size(nIdxs)
10071024 if ((i.callerPublicKey != mngPub))
10081025 then throw("approveLeasings not authorized")
10091026 else {
1010- let $t04371943781 = readNodeInfo(0)
1011- let nAddr0 = $t04371943781._1
1012- let lAmtKEY0 = $t04371943781._2
1013- let lAmt0 = $t04371943781._3
1014- let lIdKEY0 = $t04371943781._4
1015- let lId0 = $t04371943781._5
1027+ let $t04442544487 = readNodeInfo(0)
1028+ let nAddr0 = $t04442544487._1
1029+ let lAmtKEY0 = $t04442544487._2
1030+ let lAmt0 = $t04442544487._3
1031+ let lIdKEY0 = $t04442544487._4
1032+ let lId0 = $t04442544487._5
10161033 let newL0 = Lease(nAddr0, (lAmt0 - (lAmt * expCount)))
10171034 let validation = invoke(nodeRegAddr, "validateAndApproveLeasings", [nListS], nil)
10181035 if ((validation == validation))
10191036 then {
10201037 func forEachNodeValidateAndGenerateLease (a,i) = {
10211038 let node = nList[i]
10221039 let la = Lease(addressFromStringValue(node), lAmt)
10231040 (a ++ [la, BinaryEntry(getLeaseIdByAddressKey(node), lcalc(la)), IntegerEntry(getLeaseAmountByAddressKey(node), lAmt)])
10241041 }
10251042
10261043 ([StringEntry(lGroupNodeListKEY, nListS), BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0] ++ {
10271044 let $l = nIdxs
10281045 let $s = size($l)
10291046 let $acc0 = nil
10301047 func $f0_1 ($a,$i) = if (($i >= $s))
10311048 then $a
10321049 else forEachNodeValidateAndGenerateLease($a, $l[$i])
10331050
10341051 func $f0_2 ($a,$i) = if (($i >= $s))
10351052 then $a
10361053 else throw("List size exceeds 8")
10371054
10381055 $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)
10391056 })
10401057 }
10411058 else throw("Strict value is not equal to itself.")
10421059 }
10431060 }
10441061 }
10451062
10461063
10471064
10481065 @Callable(i)
10491066 func rebalanceLeasings (amount,groupNum) = {
10501067 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
10511068 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
10521069 let mngPub = fromBase58String(mngPubS)
10531070 let lGroupNodeListKEY = getLeaseGroupNodeListKey(groupNum)
10541071 let nListS = getStringOrFail(this, lGroupNodeListKEY)
10551072 let nList = split(nListS, SEP)
10561073 if ((i.callerPublicKey != mngPub))
10571074 then throw("rebalanceLeasings not authorized")
10581075 else {
10591076 let unleaseAmt = ((amount / size(nList)) + 1)
1060- let $t04502145083 = readNodeInfo(0)
1061- let nAddr0 = $t04502145083._1
1062- let lAmtKEY0 = $t04502145083._2
1063- let lAmt0 = $t04502145083._3
1064- let lIdKEY0 = $t04502145083._4
1065- let lId0 = $t04502145083._5
1077+ let $t04572745789 = readNodeInfo(0)
1078+ let nAddr0 = $t04572745789._1
1079+ let lAmtKEY0 = $t04572745789._2
1080+ let lAmt0 = $t04572745789._3
1081+ let lIdKEY0 = $t04572745789._4
1082+ let lId0 = $t04572745789._5
10661083 let newL0 = Lease(nAddr0, (lAmt0 + (unleaseAmt * size(nList))))
10671084 func forEachNodeDoUnlease (a,i) = {
10681085 let node = nList[i]
10691086 let lIdKEY = getLeaseIdByAddressKey(node)
10701087 let lId = getBinaryValue(this, lIdKEY)
10711088 let lAmtKEY = getLeaseAmountByAddressKey(node)
10721089 let lAmt = getIntegerValue(this, lAmtKEY)
10731090 let ula = LeaseCancel(value(lId))
10741091 let la = Lease(addressFromStringValue(node), (lAmt - unleaseAmt))
10751092 (a ++ [LeaseCancel(value(lId)), la, BinaryEntry(lIdKEY, lcalc(la)), IntegerEntry(lAmtKEY, la.amount)])
10761093 }
10771094
10781095 ({
10791096 let $l = nIdxs
10801097 let $s = size($l)
10811098 let $acc0 = nil
10821099 func $f0_1 ($a,$i) = if (($i >= $s))
10831100 then $a
10841101 else forEachNodeDoUnlease($a, $l[$i])
10851102
10861103 func $f0_2 ($a,$i) = if (($i >= $s))
10871104 then $a
10881105 else throw("List size exceeds 8")
10891106
10901107 $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)
10911108 } ++ [BinaryEntry(lIdKEY0, lcalc(newL0)), IntegerEntry(lAmtKEY0, newL0.amount), LeaseCancel(lId0), newL0])
10921109 }
10931110 }
10941111
10951112
10961113
10971114 @Callable(i)
10981115 func swapParamsByUserSYSREADONLY (userAddressStr,gnsbtDiff) = {
10991116 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStr, 0, 0], nil))
11001117 let gnsbtAmt = (asInt(gnsbtData[0]) + gnsbtDiff)
11011118 let gnsbtAmtTotal = (asInt(gnsbtData[1]) + gnsbtDiff)
11021119 let swapLimitData = asAnyList(invoke(mathContract, "calcSwapLimitREADONLY", [gnsbtAmt], nil))
11031120 let tokenSwapLimitInUsdMax = asInt(swapLimitData[0])
11041121 let usdnSwapLimitMax = asInt(swapLimitData[2])
11051122 let lastSwapHeight = valueOrElse(getInteger(this, keyUserLastSwapHeight(userAddressStr)), 0)
11061123 let swapLimitTimelifeBlocks = swapsTimeframeREAD()
11071124 let passedBlocksAfterLastSwap = (height - lastSwapHeight)
11081125 let isSwapTimelifeNew = (passedBlocksAfterLastSwap >= swapLimitTimelifeBlocks)
11091126 let swapLimitSpentInUsdn = if (isSwapTimelifeNew)
11101127 then 0
11111128 else valueOrElse(getInteger(this, keySwapUserSpentInPeriod(userAddressStr)), 0)
11121129 let blcks2LmtReset = if (isSwapTimelifeNew)
11131130 then 0
11141131 else (swapLimitTimelifeBlocks - passedBlocksAfterLastSwap)
11151132 $Tuple2(nil, $Tuple7(tokenSwapLimitInUsdMax, swapLimitSpentInUsdn, blcks2LmtReset, gnsbtAmt, gnsbtAmtTotal, 0, usdnSwapLimitMax))
11161133 }
11171134
11181135
11191136
11201137 @Callable(i)
11211138 func calcWithdrawResultSYSREADONLY (swapType,inAmount,price,inAsset) = {
11221139 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
11231140 $Tuple2(nil, calcWithdraw(swapType, inAmount, price, neutrinoMetrics, inAsset))
11241141 }
11251142
11261143
11271144
11281145 @Callable(i)
11291146 func replaceCommunityNode (oldAddrStr,newAddrStr,groupNum,penaltyAmount) = {
11301147 let mngPubS = valueOrElse(getString("%s%s__cfg__leasingManagerPub"), "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur")
11311148 let mngPub = fromBase58String(mngPubS)
11321149 if ((i.callerPublicKey != mngPub))
11331150 then throw("replaceCommunityNode not authorized")
11341151 else {
11351152 let groupKey = getLeaseGroupNodeListKey(groupNum)
11361153 let groupNodeListS = getStringOrFail(this, groupKey)
11371154 if (!(contains(groupNodeListS, oldAddrStr)))
11381155 then throw(((("Group " + toString(groupNum)) + " does not contain address ") + oldAddrStr))
11391156 else {
11401157 let doReplace = invoke(nodeRegistryContract, "replaceApprovedNode", [oldAddrStr, newAddrStr, groupNum, penaltyAmount], nil)
11411158 if ((doReplace == doReplace))
11421159 then {
11431160 let oldLeaseIdKey = getLeaseIdByAddressKey(oldAddrStr)
11441161 let oldLeaseAmtKey = getLeaseAmountByAddressKey(oldAddrStr)
11451162 let leaseAmt = getIntegerValue(oldLeaseAmtKey)
11461163 let newLeaseIdKey = getLeaseIdByAddressKey(newAddrStr)
11471164 let newLeaseAmtKey = getLeaseAmountByAddressKey(newAddrStr)
11481165 let newLease = Lease(addressFromStringValue(newAddrStr), leaseAmt)
11491166 let updatedGroupNodeListS = makeString(split(groupNodeListS, oldAddrStr), newAddrStr)
11501167 $Tuple2([LeaseCancel(getBinaryValue(oldLeaseIdKey)), DeleteEntry(oldLeaseIdKey), DeleteEntry(oldLeaseAmtKey), StringEntry(groupKey, updatedGroupNodeListS), newLease, BinaryEntry(newLeaseIdKey, lcalc(newLease)), IntegerEntry(newLeaseAmtKey, leaseAmt)], unit)
11511168 }
11521169 else throw("Strict value is not equal to itself.")
11531170 }
11541171 }
11551172 }
11561173
11571174
11581175 @Verifier(tx)
11591176 func verify () = {
11601177 let pubKeyAdminsListStr = makeString(["ExtEEK19nmKj9mCpnWyvEEJFYATLMcVEMvohhUHkyHNm", "Ev5py5FfBQX9cZpYKnfQrTB49Byf8QmpZWeDVRim4yV7", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR", "DUuuLjXu98nBwZc7fqwCTjtA3nnRwgTbkMSr5SU2NmDR"], SEP)
11611178 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
11621179 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
11631180 then 1
11641181 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
11651182 then 1
11661183 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
11671184 then 1
11681185 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
11691186 then 2
11701187 else 0))
11711188 if (if (isBlocked)
11721189 then (getStringValue(controlContract, "is_blocked_caller") == toString(govContract))
11731190 else false)
11741191 then validateUpdate(tx)
11751192 else match tx {
11761193 case sponsorTx: SponsorFeeTransaction =>
11771194 if (checkIsValidMinSponsoredFee(sponsorTx))
11781195 then (count >= 3)
11791196 else false
11801197 case _ =>
11811198 (count >= 3)
11821199 }
11831200 }
11841201

github/deemru/w8io/169f3d6 
141.11 ms