tx · 2zKsFAsYic4tgnUUwQFye4EudvEtBr96NbZsQedhfidw

3N9KN3vqknYm5Gqh57pvxJ8hGeWLgAAnWAB:  -0.03000000 Waves

2023.02.20 18:10 [2458137] smart account 3N9KN3vqknYm5Gqh57pvxJ8hGeWLgAAnWAB > SELF 0.00000000 Waves

{ "type": 13, "id": "2zKsFAsYic4tgnUUwQFye4EudvEtBr96NbZsQedhfidw", "fee": 3000000, "feeAssetId": null, "timestamp": 1676905830475, "version": 1, "sender": "3N9KN3vqknYm5Gqh57pvxJ8hGeWLgAAnWAB", "senderPublicKey": "9xSPDSVYfs3YGN2xPAN7NGYG11ZHCduMeFTbTXkbQ8Fu", "proofs": [ "5Tx1Ao5Xrp3RxqxhwvjKdRMhCgHbbV1Aon4sJyxt5M9qeJBM6MeBLZVx4yn1g6rG9FgWTXBaB85EwDeg1y1q8ixu" ], "script": "base64:BgJFCAISAwoBCBIDCgEIEgMKAQgSABIAEgQKAggBEgMKAQgSBAoCCAgSBgoEARgIGBIECgIYCBIECgIICBIDCgEIEgQKAggIXgAGU0NBTEU4AAgABU1VTFQ4AIDC1y8AB1NDQUxFMTgAEgAGTVVMVDE4CQC2AgEAgICQu7rWrfANAANTRVACAl9fAA5QT09MV0VJR0hUTVVMVAUFTVVMVDgACnplcm9CaWdJbnQJALYCAQAAAAlvbmVCaWdJbnQJALYCAQABAQlhc0FueUxpc3QBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACCUxpc3RbQW55XQQKdmFsQW55THlzdAUHJG1hdGNoMAUKdmFsQW55THlzdAkAAgECG2ZhaWwgdG8gY2FzdCBpbnRvIExpc3RbQW55XQEFYXNJbnQBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACA0ludAQGdmFsSW50BQckbWF0Y2gwBQZ2YWxJbnQJAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBCGFzU3RyaW5nAQN2YWwEByRtYXRjaDAFA3ZhbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEBnZhbFN0cgUHJG1hdGNoMAUGdmFsU3RyCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQxhc0J5dGVWZWN0b3IBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEBnZhbEJpbgUHJG1hdGNoMAUGdmFsQmluCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQCsAgIJAKwCAgIPbWFuZGF0b3J5IHRoaXMuBQNrZXkCDyBpcyBub3QgZGVmaW5lZAEYZ2V0U3RyaW5nQnlBZGRyZXNzT3JGYWlsAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFB2FkZHJlc3MFA2tleQkArAICCQCsAgIJAKwCAgkArAICAgptYW5kYXRvcnkgCQClCAEFB2FkZHJlc3MCAS4FA2tleQIPIGlzIG5vdCBkZWZpbmVkAQxnZXRJbnRPclplcm8CB2FkZHJlc3MDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFB2FkZHJlc3MFA2tleQAAAQ9nZXRJbnRPckRlZmF1bHQDB2FkZHJlc3MDa2V5CmRlZmF1bHRWYWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUHYWRkcmVzcwUDa2V5BQpkZWZhdWx0VmFsAQxnZXRJbnRPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUHYWRkcmVzcwUDa2V5CQCsAgIJAKwCAgIPbWFuZGF0b3J5IHRoaXMuBQNrZXkCDyBpcyBub3QgZGVmaW5lZAEZZ2V0QmlnSW50RnJvbVN0cmluZ09yWmVybwIHYWRkcmVzcwNrZXkJAQV2YWx1ZQEJAKgDAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQdhZGRyZXNzBQNrZXkCATABHGdldEJpZ0ludEZyb21TdHJpbmdPckRlZmF1bHQDB2FkZHJlc3MDa2V5CmRlZmF1bHRWYWwEByRtYXRjaDAJAJ0IAgUHYWRkcmVzcwUDa2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkBBXZhbHVlAQkAqAMBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFCmRlZmF1bHRWYWwJAAIBAgtNYXRjaCBlcnJvcgEFdG9YMTgCB29yaWdWYWwNb3JpZ1NjYWxlTXVsdAkAvAIDCQC2AgEFB29yaWdWYWwFBk1VTFQxOAkAtgIBBQ1vcmlnU2NhbGVNdWx0AQdmcm9tWDE4AgN2YWwPcmVzdWx0U2NhbGVNdWx0CQCgAwEJALwCAwUDdmFsCQC2AgEFD3Jlc3VsdFNjYWxlTXVsdAUGTVVMVDE4ARFrZXlGYWN0b3J5QWRkcmVzcwACHCVzJXNfX2NvbmZpZ19fZmFjdG9yeUFkZHJlc3MBGWtleVZvdGluZ0VtaXNzaW9uQ29udHJhY3QAAholc19fdm90aW5nRW1pc3Npb25Db250cmFjdAAYSWR4RmFjdG9yeUNmZ1N0YWtpbmdEYXBwAAEAGUlkeEZhY3RvcnlDZmdCb29zdGluZ0RhcHAAAgAUSWR4RmFjdG9yeUNmZ0lkb0RhcHAAAwAVSWR4RmFjdG9yeUNmZ1RlYW1EYXBwAAQAGUlkeEZhY3RvcnlDZmdFbWlzc2lvbkRhcHAABQAVSWR4RmFjdG9yeUNmZ1Jlc3REYXBwAAYAGUlkeEZhY3RvcnlDZmdTbGlwcGFnZURhcHAABwENa2V5RmFjdG9yeUNmZwACESVzX19mYWN0b3J5Q29uZmlnARNrZXlNYW5hZ2VyUHVibGljS2V5AAIUJXNfX21hbmFnZXJQdWJsaWNLZXkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAIbJXNfX3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5ARZrZXlTdGFibGVQb29sQWRkb25BZGRyAAIXJXNfX3N0YWJsZVBvb2xBZGRvbkFkZHIBDGtleUFkZG9uQWRkcgACDSVzX19hZGRvbkFkZHIBGmtleUZhY3RvcnlMcDJBc3NldHNNYXBwaW5nAQpscEFzc2V0U3RyCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAIFCmxwQXNzZXRTdHIJAMwIAgIebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQNuaWwFA1NFUAEQa2V5RmFjdG9yeUxwTGlzdAACECVzX19scFRva2Vuc0xpc3QBJmtleUZhY3RvcnlMcEFzc2V0VG9Qb29sQ29udHJhY3RBZGRyZXNzAQpscEFzc2V0U3RyCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAIFCmxwQXNzZXRTdHIJAMwIAgIebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQNuaWwFA1NFUAEUa2V5RmFjdG9yeVBvb2xXZWlnaHQBD2NvbnRyYWN0QWRkcmVzcwkAuQkCCQDMCAICBCVzJXMJAMwIAgIKcG9vbFdlaWdodAkAzAgCBQ9jb250cmFjdEFkZHJlc3MFA25pbAUDU0VQAQpyZWFkTHBMaXN0AQdmYWN0b3J5CQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUHZmFjdG9yeQkBEGtleUZhY3RvcnlMcExpc3QAAgAFA1NFUAEUcmVhZEZhY3RvcnlDZmdPckZhaWwBB2ZhY3RvcnkJALUJAgkBGGdldFN0cmluZ0J5QWRkcmVzc09yRmFpbAIFB2ZhY3RvcnkJAQ1rZXlGYWN0b3J5Q2ZnAAUDU0VQARhnZXRCb29zdGluZ0FkZHJlc3NPckZhaWwBCmZhY3RvcnlDZmcJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUKZmFjdG9yeUNmZwUZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcAEYZ2V0RW1pc3Npb25BZGRyZXNzT3JGYWlsAQpmYWN0b3J5Q2ZnCQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFCmZhY3RvcnlDZmcFGUlkeEZhY3RvcnlDZmdFbWlzc2lvbkRhcHABF2dldFN0YWtpbmdBZGRyZXNzT3JGYWlsAQpmYWN0b3J5Q2ZnCQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFCmZhY3RvcnlDZmcFGElkeEZhY3RvcnlDZmdTdGFraW5nRGFwcAEea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50AAIbJXMlc19fcmF0ZVBlckJsb2NrX19jdXJyZW50ASFrZXlFbWlzc2lvblJhdGVQZXJCbG9ja01heEN1cnJlbnQAAh4lcyVzX19yYXRlUGVyQmxvY2tNYXhfX2N1cnJlbnQBFWtleUVtaXNzaW9uU3RhcnRCbG9jawACGiVzJXNfX2VtaXNzaW9uX19zdGFydEJsb2NrARtrZXlFbWlzc2lvbkR1cmF0aW9uSW5CbG9ja3MAAhglcyVzX19lbWlzc2lvbl9fZHVyYXRpb24BE2tleUVtaXNzaW9uRW5kQmxvY2sAAhglcyVzX19lbWlzc2lvbl9fZW5kQmxvY2sBD2tleVN0YWtlZEJ5VXNlcgIOdXNlckFkZHJlc3NTdHIMbHBBc3NldElkU3RyCQC5CQIJAMwIAgIOJXMlcyVzX19zdGFrZWQJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgUMbHBBc3NldElkU3RyBQNuaWwFA1NFUAEOa2V5U3Rha2VkVG90YWwBDGxwQXNzZXRJZFN0cgkArAICAhclcyVzJXNfX3N0YWtlZF9fdG90YWxfXwUMbHBBc3NldElkU3RyARBrZXlDbGFpbWVkQnlVc2VyAgxscEFzc2V0SWRTdHIOdXNlckFkZHJlc3NTdHIJALkJAgkAzAgCAg8lcyVzJXNfX2NsYWltZWQJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgUMbHBBc3NldElkU3RyBQNuaWwFA1NFUAEZa2V5Q2xhaW1lZEJ5VXNlck1pblJld2FyZAIMbHBBc3NldElkU3RyDnVzZXJBZGRyZXNzU3RyCQC5CQIJAMwIAgIYJXMlcyVzX19jbGFpbWVkTWluUmV3YXJkCQDMCAIFDnVzZXJBZGRyZXNzU3RyCQDMCAIFDGxwQXNzZXRJZFN0cgUDbmlsBQNTRVABG2tleUNsYWltZWRCeVVzZXJCb29zdFJld2FyZAIMbHBBc3NldElkU3RyDnVzZXJBZGRyZXNzU3RyCQC5CQIJAMwIAgIaJXMlcyVzX19jbGFpbWVkQm9vc3RSZXdhcmQJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgUMbHBBc3NldElkU3RyBQNuaWwFA1NFUAEPa2V5Q2xhaW1lZFRvdGFsAQxscEFzc2V0SWRTdHIJALkJAgkAzAgCAhYlcyVzJXNfX2NsYWltZWRfX3RvdGFsCQDMCAIFDGxwQXNzZXRJZFN0cgUDbmlsBQNTRVABCnJlYWRTdGFrZWQBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkAAAEVa2V5TGFzdFRvdGFsTHBCYWxhbmNlAQlscEFzc2V0SWQJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUJbHBBc3NldElkCQDMCAICBXRvdGFsCQDMCAICA2JhbAUDbmlsBQNTRVABFGtleUxhc3RVc2VyTHBCYWxhbmNlAglscEFzc2V0SWQLdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUJbHBBc3NldElkCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICA2JhbAUDbmlsBQNTRVABGWtleVRvdGFsTHBCYWxhbmNlSW50ZWdyYWwBCWxwQXNzZXRJZAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCBQlscEFzc2V0SWQJAMwIAgIFdG90YWwJAMwIAgIGYmFsSU5UBQNuaWwFA1NFUAEYa2V5VXNlckxwQmFsYW5jZUludGVncmFsAglscEFzc2V0SWQLdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUJbHBBc3NldElkCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICBmJhbElOVAUDbmlsBQNTRVABJmtleVRvdGFsTHBCYWxhbmNlSW50ZWdyYWxMYXN0VXBkSGVpZ2h0AQlscEFzc2V0SWQJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUJbHBBc3NldElkCQDMCAICBXRvdGFsCQDMCAICB2xhc3RVcGQFA25pbAUDU0VQASVrZXlVc2VyTHBCYWxhbmNlSW50ZWdyYWxMYXN0VXBkSGVpZ2h0AglscEFzc2V0SWQLdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUJbHBBc3NldElkCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICB2xhc3RVcGQFA25pbAUDU0VQARJrZXlXeFBlckxwSW50ZWdyYWwBCWxwQXNzZXRJZAkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAIFCWxwQXNzZXRJZAkAzAgCAgZjb21tb24JAMwIAgIFbHBJbnQFA25pbAUDU0VQAR9rZXlXeFBlckxwSW50ZWdyYWxMYXN0VXBkSGVpZ2h0AQlscEFzc2V0SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCBQlscEFzc2V0SWQJAMwIAgIGY29tbW9uCQDMCAICBmxwSW50SAUDbmlsBQNTRVABEGtleVd4VG9DbGFpbVVzZXICCWxwQXNzZXRJZAt1c2VyQWRkcmVzcwkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAIFCWxwQXNzZXRJZAkAzAgCBQt1c2VyQWRkcmVzcwkAzAgCAgVscEludAUDbmlsBQNTRVABI2tleVd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0VXBkSGVpZ2h0AglscEFzc2V0SWQLdXNlckFkZHJlc3MJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCBQlscEFzc2V0SWQJAMwIAgULdXNlckFkZHJlc3MJAMwIAgIGbHBJbnRIBQNuaWwFA1NFUAEKa2V5V3hQZXJMcAEJbHBBc3NldElkCQC5CQIJAMwIAgICJXMJAMwIAgUJbHBBc3NldElkCQDMCAICB3d4UGVyTHAFA25pbAUDU0VQAQ1rZXlXeFBlckxwWDE4AQlscEFzc2V0SWQJALkJAgkAzAgCAgIlcwkAzAgCBQlscEFzc2V0SWQJAMwIAgIKd3hQZXJMcFgxOAUDbmlsBQNTRVABGmtleVd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0AglscEFzc2V0SWQLdXNlckFkZHJlc3MJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCBQlscEFzc2V0SWQJAMwIAgULdXNlckFkZHJlc3MJAMwIAgIFdUludEwFA25pbAUDU0VQARlrZXlPcGVyYXRpb25IaXN0b3J5UmVjb3JkAwR0eXBlC3VzZXJBZGRyZXNzBnR4SWQ1OAkAuQkCCQDMCAICESVzJXMlcyVzX19oaXN0b3J5CQDMCAIFBHR5cGUJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUGdHhJZDU4BQNuaWwFA1NFUAETZm9ybWF0SGlzdG9yeVJlY29yZAQLdXNlckFkZHJlc3MJbHBBc3NldElkBHR5cGUGYW1vdW50CQC5CQIJAMwIAgIMJXMlcyVzJWQlZCVkCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFCWxwQXNzZXRJZAkAzAgCBQR0eXBlCQDMCAIJAKQDAQUGaGVpZ2h0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApAMBBQZhbW91bnQFA25pbAUDU0VQARVPcGVyYXRpb25IaXN0b3J5RW50cnkFBHR5cGULdXNlckFkZHJlc3MJbHBBc3NldElkBmFtb3VudAR0eElkCQELU3RyaW5nRW50cnkCCQEZa2V5T3BlcmF0aW9uSGlzdG9yeVJlY29yZAMFBHR5cGUFC3VzZXJBZGRyZXNzCQDYBAEFBHR4SWQJARNmb3JtYXRIaXN0b3J5UmVjb3JkBAULdXNlckFkZHJlc3MFCWxwQXNzZXRJZAUEdHlwZQUGYW1vdW50AA5mYWN0b3J5QWRkcmVzcwkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARFrZXlGYWN0b3J5QWRkcmVzcwAAD2ZhY3RvcnlDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQUOZmFjdG9yeUFkZHJlc3MACmZhY3RvcnlDZmcJARRyZWFkRmFjdG9yeUNmZ09yRmFpbAEFD2ZhY3RvcnlDb250cmFjdAAQZW1pc3Npb25Db250cmFjdAkBGGdldEVtaXNzaW9uQWRkcmVzc09yRmFpbAEFCmZhY3RvcnlDZmcAEGJvb3N0aW5nQ29udHJhY3QJARhnZXRCb29zdGluZ0FkZHJlc3NPckZhaWwBBQpmYWN0b3J5Q2ZnAQtrZXlOZXh0VXNlcgEJbHBBc3NldElkCQC5CQIJAMwIAgIEJXMlcwkAzAgCBQlscEFzc2V0SWQJAMwIAgIIbmV4dFVzZXIFA25pbAUDU0VQARBnZXRVc2Vyc0xpc3ROYW1lAQlscEFzc2V0SWQJALkJAgkAzAgCAgV1c2VycwkAzAgCBQlscEFzc2V0SWQFA25pbAUDU0VQAQtrZXlMaXN0SGVhZAEIbGlzdE5hbWUJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUIbGlzdE5hbWUJAMwIAgIEaGVhZAUDbmlsBQNTRVABC2tleUxpc3RTaXplAQhsaXN0TmFtZQkAuQkCCQDMCAICBiVzJXMlcwkAzAgCBQhsaXN0TmFtZQkAzAgCAgRzaXplBQNuaWwFA1NFUAELa2V5TGlzdFByZXYCCGxpc3ROYW1lAmlkCQC5CQIJAMwIAgIIJXMlcyVzJXMJAMwIAgUIbGlzdE5hbWUJAMwIAgUCaWQJAMwIAgIEcHJldgUDbmlsBQNTRVABC2tleUxpc3ROZXh0AghsaXN0TmFtZQJpZAkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAIFCGxpc3ROYW1lCQDMCAIFAmlkCQDMCAICBG5leHQFA25pbAUDU0VQAQxjb250YWluc05vZGUCCGxpc3ROYW1lAmlkBApoZWFkT3JVbml0CQCdCAIFBHRoaXMJAQtrZXlMaXN0SGVhZAEFCGxpc3ROYW1lBApwcmV2T3JVbml0CQCdCAIFBHRoaXMJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lBQJpZAQKbmV4dE9yVW5pdAkAnQgCBQR0aGlzCQELa2V5TGlzdE5leHQCBQhsaXN0TmFtZQUCaWQDAwkAAAIFAmlkCQELdmFsdWVPckVsc2UCBQpoZWFkT3JVbml0AgAGCQECIT0CBQpwcmV2T3JVbml0BQR1bml0BgkBAiE9AgUKbmV4dE9yVW5pdAUEdW5pdAERaW5zZXJ0Tm9kZUFjdGlvbnMCCGxpc3ROYW1lAmlkBApoZWFkT3JVbml0CQCdCAIFBHRoaXMJAQtrZXlMaXN0SGVhZAEFCGxpc3ROYW1lBAhsaXN0U2l6ZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQELa2V5TGlzdFNpemUBBQhsaXN0TmFtZQAABAljaGVja05vZGUDCQEBIQEJAQxjb250YWluc05vZGUCBQhsaXN0TmFtZQUCaWQGCQACAQILTm9kZSBleGlzdHMDCQAAAgUJY2hlY2tOb2RlBQljaGVja05vZGUJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQELa2V5TGlzdFNpemUBBQhsaXN0TmFtZQkAZAIFCGxpc3RTaXplAAEFA25pbAMJAQIhPQIFCmhlYWRPclVuaXQFBHVuaXQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBC2tleUxpc3ROZXh0AgUIbGlzdE5hbWUFAmlkCQEFdmFsdWUBBQpoZWFkT3JVbml0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lCQEFdmFsdWUBBQpoZWFkT3JVbml0BQJpZAUDbmlsBQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBC2tleUxpc3RIZWFkAQUIbGlzdE5hbWUFAmlkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BEWRlbGV0ZU5vZGVBY3Rpb25zAghsaXN0TmFtZQJpZAQKaGVhZE9yVW5pdAkAnQgCBQR0aGlzCQELa2V5TGlzdEhlYWQBBQhsaXN0TmFtZQQIbGlzdFNpemUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBC2tleUxpc3RTaXplAQUIbGlzdE5hbWUAAAQKcHJldk9yVW5pdAkAnQgCBQR0aGlzCQELa2V5TGlzdFByZXYCBQhsaXN0TmFtZQUCaWQECm5leHRPclVuaXQJAJ0IAgUEdGhpcwkBC2tleUxpc3ROZXh0AgUIbGlzdE5hbWUFAmlkCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQtrZXlMaXN0U2l6ZQEFCGxpc3ROYW1lCQBlAgUIbGlzdFNpemUAAQUDbmlsAwMJAQIhPQIFCnByZXZPclVuaXQFBHVuaXQJAQIhPQIFCm5leHRPclVuaXQFBHVuaXQHCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQtrZXlMaXN0TmV4dAIFCGxpc3ROYW1lCQEFdmFsdWUBBQpwcmV2T3JVbml0CQEFdmFsdWUBBQpuZXh0T3JVbml0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lCQEFdmFsdWUBBQpuZXh0T3JVbml0CQEFdmFsdWUBBQpwcmV2T3JVbml0CQDMCAIJAQtEZWxldGVFbnRyeQEJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lBQJpZAkAzAgCCQELRGVsZXRlRW50cnkBCQELa2V5TGlzdE5leHQCBQhsaXN0TmFtZQUCaWQFA25pbAMJAQIhPQIFCm5leHRPclVuaXQFBHVuaXQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBC2tleUxpc3RIZWFkAQUIbGlzdE5hbWUJAQV2YWx1ZQEFCm5leHRPclVuaXQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBC2tleUxpc3ROZXh0AgUIbGlzdE5hbWUFAmlkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lCQEFdmFsdWUBBQpuZXh0T3JVbml0BQNuaWwDCQECIT0CBQpwcmV2T3JVbml0BQR1bml0CQDMCAIJAQtEZWxldGVFbnRyeQEJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lBQJpZAkAzAgCCQELRGVsZXRlRW50cnkBCQELa2V5TGlzdE5leHQCBQhsaXN0TmFtZQkBBXZhbHVlAQUKcHJldk9yVW5pdAUDbmlsAwkAAAIFAmlkCQELdmFsdWVPckVsc2UCBQpoZWFkT3JVbml0AgAJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBC2tleUxpc3RIZWFkAQUIbGlzdE5hbWUFA25pbAkAAgEJAKwCAgkArAICCQCsAgICDmludmFsaWQgbm9kZTogBQhsaXN0TmFtZQIBLgUCaWQBG2NhbGNXeFBlckxwSW50ZWdyYWxVc2VyTGFzdAQMc3Rha2VkQnlVc2VyJnd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0VXBkSGVpZ2h0T3JaZXJvEnd4UGVyTHBJbnRlZ3JhbE5ldxp3eFBlckxwSW50ZWdyYWxVc2VyTGFzdEtFWQMDCQAAAgUmd3hQZXJMcEludGVncmFsVXNlckxhc3RVcGRIZWlnaHRPclplcm8FCnplcm9CaWdJbnQJAL8CAgUMc3Rha2VkQnlVc2VyBQp6ZXJvQmlnSW50BwUKemVyb0JpZ0ludAMJAAACBQxzdGFrZWRCeVVzZXIFCnplcm9CaWdJbnQFEnd4UGVyTHBJbnRlZ3JhbE5ldwMDCQC/AgIFJnd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0VXBkSGVpZ2h0T3JaZXJvBQp6ZXJvQmlnSW50CQC/AgIFDHN0YWtlZEJ5VXNlcgUKemVyb0JpZ0ludAcJAQV2YWx1ZQEJAKgDAQkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMFGnd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0S0VZCQACAQItY2FsY1d4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0OiB1bmV4cGVjdGVkIHN0YXRlARRyZWZyZXNoUG9vbElOVEVHUkFMUwMMbHBBc3NldElkU3RyDnBvb2xBZGRyZXNzU3RyDWxwRGVsdGFBbW91bnQEDnN0YWtlZFRvdGFsS0VZCQEOa2V5U3Rha2VkVG90YWwBBQxscEFzc2V0SWRTdHIEC3N0YWtlZFRvdGFsCQC2AgEJAQpyZWFkU3Rha2VkAQUOc3Rha2VkVG90YWxLRVkEEm5vblplcm9TdGFrZWRUb3RhbAMJAAACBQtzdGFrZWRUb3RhbAUKemVyb0JpZ0ludAUJb25lQmlnSW50BQtzdGFrZWRUb3RhbAQKcG9vbFdlaWdodAkBEUBleHRyTmF0aXZlKDEwNTApAgUPZmFjdG9yeUNvbnRyYWN0CQEUa2V5RmFjdG9yeVBvb2xXZWlnaHQBBQ5wb29sQWRkcmVzc1N0cgQSZW1pc3Npb25TdGFydEJsb2NrCQEMZ2V0SW50T3JGYWlsAgUQZW1pc3Npb25Db250cmFjdAkBFWtleUVtaXNzaW9uU3RhcnRCbG9jawAEBU1VTFQzAOgHBBR3eEVtaXNzaW9uUGVyQmxvY2tYMwkAaAIJAQxnZXRJbnRPckZhaWwCBRBlbWlzc2lvbkNvbnRyYWN0CQEea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50AAUFTVVMVDMEGHBvb2xXeEVtaXNzaW9uUGVyQmxvY2tYMwkAawMFFHd4RW1pc3Npb25QZXJCbG9ja1gzBQpwb29sV2VpZ2h0CQBoAgUOUE9PTFdFSUdIVE1VTFQAAwQSd3hQZXJMcEludGVncmFsS0VZCQESa2V5V3hQZXJMcEludGVncmFsAQUMbHBBc3NldElkU3RyBB93eFBlckxwSW50ZWdyYWxMYXN0VXBkSGVpZ2h0S0VZCQEfa2V5V3hQZXJMcEludGVncmFsTGFzdFVwZEhlaWdodAEFDGxwQXNzZXRJZFN0cgQKd3hQZXJMcEtFWQkBCmtleVd4UGVyTHABBQxscEFzc2V0SWRTdHIEHHd4UGVyTHBJbnRlZ3JhbExhc3RVcGRIZWlnaHQJAQ9nZXRJbnRPckRlZmF1bHQDBQR0aGlzBR93eFBlckxwSW50ZWdyYWxMYXN0VXBkSGVpZ2h0S0VZBRJlbWlzc2lvblN0YXJ0QmxvY2sED3d4UGVyTHBJbnRlZ3JhbAkBGWdldEJpZ0ludEZyb21TdHJpbmdPclplcm8CBQR0aGlzBRJ3eFBlckxwSW50ZWdyYWxLRVkED3d4UGVyTHBPclplcm9YMwAABAJkaAkAlgMBCQDMCAIJAGUCBQZoZWlnaHQFHHd4UGVyTHBJbnRlZ3JhbExhc3RVcGRIZWlnaHQJAMwIAgAABQNuaWwECXd4UGVyTHBYMwMJAQIhPQIFD3d4UGVyTHBPclplcm9YMwAACQC2AgEFD3d4UGVyTHBPclplcm9YMwkAvAIDCQC2AgEFGHBvb2xXeEVtaXNzaW9uUGVyQmxvY2tYMwkAtgIBBQVNVUxUOAUSbm9uWmVyb1N0YWtlZFRvdGFsBA5zdGFrZWRUb3RhbE5ldwkAtwICBQtzdGFrZWRUb3RhbAkAtgIBBQ1scERlbHRhQW1vdW50BBVub25aZXJvU3Rha2VkVG90YWxOZXcDCQAAAgUOc3Rha2VkVG90YWxOZXcFCnplcm9CaWdJbnQFCW9uZUJpZ0ludAUOc3Rha2VkVG90YWxOZXcEEnd4UGVyTHBJbnRlZ3JhbE5ldwkAtwICBQ93eFBlckxwSW50ZWdyYWwJALkCAgUJd3hQZXJMcFgzCQC2AgEFAmRoBAx3eFBlckxwWDNOZXcJALoCAgkAtgIBBRhwb29sV3hFbWlzc2lvblBlckJsb2NrWDMFFW5vblplcm9TdGFrZWRUb3RhbE5ldwQfd3hQZXJMcEludGVncmFsTGFzdFVwZEhlaWdodE5ldwUGaGVpZ2h0BAVkZWJ1ZwkAuQkCCQDMCAIJAKYDAQUSd3hQZXJMcEludGVncmFsTmV3CQDMCAIJAKQDAQUCZGgJAMwIAgkApgMBBQl3eFBlckxwWDMJAMwIAgkApgMBBQtzdGFrZWRUb3RhbAkAzAgCCQCkAwEFGHBvb2xXeEVtaXNzaW9uUGVyQmxvY2tYMwkAzAgCCQCkAwEFFHd4RW1pc3Npb25QZXJCbG9ja1gzCQDMCAIJAKQDAQUKcG9vbFdlaWdodAUDbmlsAgI6OgkAlQoDBRJ3eFBlckxwSW50ZWdyYWxOZXcJAMwIAgkBC1N0cmluZ0VudHJ5AgUSd3hQZXJMcEludGVncmFsS0VZCQCmAwEFEnd4UGVyTHBJbnRlZ3JhbE5ldwkAzAgCCQEMSW50ZWdlckVudHJ5AgUfd3hQZXJMcEludGVncmFsTGFzdFVwZEhlaWdodEtFWQUfd3hQZXJMcEludGVncmFsTGFzdFVwZEhlaWdodE5ldwkAzAgCCQELU3RyaW5nRW50cnkCBQp3eFBlckxwS0VZCQCmAwEFDHd4UGVyTHBYM05ldwUDbmlsBQVkZWJ1ZwEQcmVmcmVzaElOVEVHUkFMUwQMbHBBc3NldElkU3RyDnVzZXJBZGRyZXNzU3RyDnBvb2xBZGRyZXNzU3RyDWxwRGVsdGFBbW91bnQEDSR0MDE0NTc1MTQ2OTcJARRyZWZyZXNoUG9vbElOVEVHUkFMUwMFDGxwQXNzZXRJZFN0cgUOcG9vbEFkZHJlc3NTdHIFDWxwRGVsdGFBbW91bnQEEnd4UGVyTHBJbnRlZ3JhbE5ldwgFDSR0MDE0NTc1MTQ2OTcCXzEEEXBvb2xJbnRlZ3JhbFNUQVRFCAUNJHQwMTQ1NzUxNDY5NwJfMgQJcG9vbERFQlVHCAUNJHQwMTQ1NzUxNDY5NwJfMwQFTVVMVDMA6AcED3N0YWtlZEJ5VXNlcktFWQkBD2tleVN0YWtlZEJ5VXNlcgIFDnVzZXJBZGRyZXNzU3RyBQxscEFzc2V0SWRTdHIEDHN0YWtlZEJ5VXNlcgkBCnJlYWRTdGFrZWQBBQ9zdGFrZWRCeVVzZXJLRVkEEHd4VG9DbGFpbVVzZXJLRVkJARBrZXlXeFRvQ2xhaW1Vc2VyAgUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgQjd3hQZXJMcEludGVncmFsVXNlckxhc3RVcGRIZWlnaHRLRVkJASNrZXlXeFBlckxwSW50ZWdyYWxVc2VyTGFzdFVwZEhlaWdodAIFDGxwQXNzZXRJZFN0cgUOdXNlckFkZHJlc3NTdHIEGnd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0S0VZCQEaa2V5V3hQZXJMcEludGVncmFsVXNlckxhc3QCBQxscEFzc2V0SWRTdHIFDnVzZXJBZGRyZXNzU3RyBA13eFRvQ2xhaW1Vc2VyCQEZZ2V0QmlnSW50RnJvbVN0cmluZ09yWmVybwIFBHRoaXMFEHd4VG9DbGFpbVVzZXJLRVkEJnd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0VXBkSGVpZ2h0T3JaZXJvCQEMZ2V0SW50T3JaZXJvAgUEdGhpcwUjd3hQZXJMcEludGVncmFsVXNlckxhc3RVcGRIZWlnaHRLRVkEF3d4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0CQEbY2FsY1d4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0BAkAtgIBBQxzdGFrZWRCeVVzZXIJALYCAQUmd3hQZXJMcEludGVncmFsVXNlckxhc3RVcGRIZWlnaHRPclplcm8FEnd4UGVyTHBJbnRlZ3JhbE5ldwUad3hQZXJMcEludGVncmFsVXNlckxhc3RLRVkEBk1VTFQxMQkAaAIFBU1VTFQ4BQVNVUxUMwQQd3hUb0NsYWltVXNlck5ldwkAmAMBCQDMCAIJALcCAgUNd3hUb0NsYWltVXNlcgkAvAIDCQC4AgIFEnd4UGVyTHBJbnRlZ3JhbE5ldwUXd3hQZXJMcEludGVncmFsVXNlckxhc3QJALYCAQUMc3Rha2VkQnlVc2VyCQC2AgEFBk1VTFQxMQkAzAgCBQp6ZXJvQmlnSW50BQNuaWwEGnd4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0TmV3BRJ3eFBlckxwSW50ZWdyYWxOZXcEI3d4UGVyTHBJbnRlZ3JhbFVzZXJMYXN0VXBkSGVpZ2h0TmV3BQZoZWlnaHQEBWRlYnVnCQC5CQIJAMwIAgkApgMBBQ13eFRvQ2xhaW1Vc2VyCQDMCAIJAKYDAQUXd3hQZXJMcEludGVncmFsVXNlckxhc3QJAMwIAgkApAMBBQxzdGFrZWRCeVVzZXIJAMwIAgUJcG9vbERFQlVHCQDMCAIJAKQDAQUGaGVpZ2h0BQNuaWwCAjo6CQCVCgMFEHd4VG9DbGFpbVVzZXJOZXcJAM4IAgURcG9vbEludGVncmFsU1RBVEUJAMwIAgkBC1N0cmluZ0VudHJ5AgUQd3hUb0NsYWltVXNlcktFWQkApgMBBRB3eFRvQ2xhaW1Vc2VyTmV3CQDMCAIJAQxJbnRlZ2VyRW50cnkCBSN3eFBlckxwSW50ZWdyYWxVc2VyTGFzdFVwZEhlaWdodEtFWQUjd3hQZXJMcEludGVncmFsVXNlckxhc3RVcGRIZWlnaHROZXcJAMwIAgkBC1N0cmluZ0VudHJ5AgUad3hQZXJMcEludGVncmFsVXNlckxhc3RLRVkJAKYDAQUad3hQZXJMcEludGVncmFsVXNlckxhc3ROZXcFA25pbAUFZGVidWcBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQABAckbWF0Y2gwCQCiCAEJARNrZXlNYW5hZ2VyUHVibGljS2V5AAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJANkEAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IBHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0AAQHJG1hdGNoMAkAoggBCQEaa2V5UGVuZGluZ01hbmFnZXJQdWJsaWNLZXkAAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkA2QQBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgAVcGVybWlzc2lvbkRlbmllZEVycm9yCQACAQIRUGVybWlzc2lvbiBkZW5pZWQBCG11c3RUaGlzAQFpAwkAAAIIBQFpBmNhbGxlcgUEdGhpcwYFFXBlcm1pc3Npb25EZW5pZWRFcnJvcgELbXVzdE1hbmFnZXIBAWkEByRtYXRjaDAJARZtYW5hZ2VyUHVibGljS2V5T3JVbml0AAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJwawUHJG1hdGNoMAMJAAACCAUBaQ9jYWxsZXJQdWJsaWNLZXkFAnBrBgUVcGVybWlzc2lvbkRlbmllZEVycm9yAwkAAQIFByRtYXRjaDACBFVuaXQDCQAAAggFAWkGY2FsbGVyBQR0aGlzBgUVcGVybWlzc2lvbkRlbmllZEVycm9yCQACAQILTWF0Y2ggZXJyb3INAWkBC2NvbnN0cnVjdG9yARFmYWN0b3J5QWRkcmVzc1N0cgQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlGYWN0b3J5QWRkcmVzcwAFEWZhY3RvcnlBZGRyZXNzU3RyBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENY29uc3RydWN0b3JWMgEWdm90aW5nRW1pc3Npb25Db250cmFjdAQFY2hla3MJAMwIAgkBC211c3RNYW5hZ2VyAQUBaQkAzAgCAwkBAiE9AgkApggBBRZ2b3RpbmdFbWlzc2lvbkNvbnRyYWN0BQR1bml0BgIoaW52YWxpZCB2b3RpbmcgZW1pc3Npb24gY29udHJhY3QgYWRkcmVzcwUDbmlsAwkAAAIFBWNoZWtzBQVjaGVrcwkAzAgCCQELU3RyaW5nRW50cnkCCQEZa2V5Vm90aW5nRW1pc3Npb25Db250cmFjdAAFFnZvdGluZ0VtaXNzaW9uQ29udHJhY3QFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpzZXRNYW5hZ2VyARdwZW5kaW5nTWFuYWdlclB1YmxpY0tleQQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBBVjaGVja01hbmFnZXJQdWJsaWNLZXkJANkEAQUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkDCQAAAgUVY2hlY2tNYW5hZ2VyUHVibGljS2V5BRVjaGVja01hbmFnZXJQdWJsaWNLZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5jb25maXJtTWFuYWdlcgAEAnBtCQEdcGVuZGluZ01hbmFnZXJQdWJsaWNLZXlPclVuaXQABAVoYXNQTQMJAQlpc0RlZmluZWQBBQJwbQYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUFaGFzUE0FBWhhc1BNBAdjaGVja1BNAwkAAAIIBQFpD2NhbGxlclB1YmxpY0tleQkBBXZhbHVlAQUCcG0GCQACAQIbWW91IGFyZSBub3QgcGVuZGluZyBtYW5hZ2VyAwkAAAIFB2NoZWNrUE0FB2NoZWNrUE0JAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleU1hbmFnZXJQdWJsaWNLZXkACQDYBAEJAQV2YWx1ZQEFAnBtCQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQVzdGFrZQADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAjRpbnZhbGlkIHBheW1lbnQgLSBleGFjdCBvbmUgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQJbHBBc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEDGxwQXNzZXRJZFN0cgkA2AQBBQlscEFzc2V0SWQEBmFtb3VudAgFA3BtdAZhbW91bnQEDnBvb2xBZGRyZXNzU3RyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUPZmFjdG9yeUNvbnRyYWN0CQEaa2V5RmFjdG9yeUxwMkFzc2V0c01hcHBpbmcBBQxscEFzc2V0SWRTdHIJAKwCAgIVdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQxscEFzc2V0SWRTdHIECWNhbGxlclN0cgkApQgBCAUBaQZjYWxsZXIEDnVzZXJBZGRyZXNzU3RyAwkAAAIFCWNhbGxlclN0cgUOcG9vbEFkZHJlc3NTdHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQljYWxsZXJTdHIED3N0YWtlZEJ5VXNlcktFWQkBD2tleVN0YWtlZEJ5VXNlcgIFDnVzZXJBZGRyZXNzU3RyBQxscEFzc2V0SWRTdHIEDnN0YWtlZFRvdGFsS0VZCQEOa2V5U3Rha2VkVG90YWwBBQxscEFzc2V0SWRTdHIEDHN0YWtlZEJ5VXNlcgkBCnJlYWRTdGFrZWQBBQ9zdGFrZWRCeVVzZXJLRVkEC3N0YWtlZFRvdGFsCQEKcmVhZFN0YWtlZAEFDnN0YWtlZFRvdGFsS0VZBA0kdDAxOTI1OTE5Mzc2CQEQcmVmcmVzaElOVEVHUkFMUwQFDGxwQXNzZXRJZFN0cgUOdXNlckFkZHJlc3NTdHIFDnBvb2xBZGRyZXNzU3RyBQZhbW91bnQEEHd4VG9DbGFpbVVzZXJOZXcIBQ0kdDAxOTI1OTE5Mzc2Al8xBA1pbnRlZ3JhbFNUQVRFCAUNJHQwMTkyNTkxOTM3NgJfMgQFZGVidWcIBQ0kdDAxOTI1OTE5Mzc2Al8zBAhsaXN0TmFtZQkBEGdldFVzZXJzTGlzdE5hbWUBBQxscEFzc2V0SWRTdHIEC2xpc3RBY3Rpb25zAwkBDGNvbnRhaW5zTm9kZQIFCGxpc3ROYW1lBQ51c2VyQWRkcmVzc1N0cgUDbmlsCQERaW5zZXJ0Tm9kZUFjdGlvbnMCBQhsaXN0TmFtZQUOdXNlckFkZHJlc3NTdHIJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9zdGFrZWRCeVVzZXJLRVkJAGQCBQxzdGFrZWRCeVVzZXIFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOc3Rha2VkVG90YWxLRVkJAGQCBQtzdGFrZWRUb3RhbAUGYW1vdW50CQDMCAIJARVPcGVyYXRpb25IaXN0b3J5RW50cnkFAgVzdGFrZQUOdXNlckFkZHJlc3NTdHIFDGxwQXNzZXRJZFN0cgUGYW1vdW50CAUBaQ10cmFuc2FjdGlvbklkBQNuaWwFDWludGVncmFsU1RBVEUFC2xpc3RBY3Rpb25zAWkBB3Vuc3Rha2UCDGxwQXNzZXRJZFN0cgZhbW91bnQECWxwQXNzZXRJZAkA2QQBBQxscEFzc2V0SWRTdHIEDnBvb2xBZGRyZXNzU3RyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUPZmFjdG9yeUNvbnRyYWN0CQEaa2V5RmFjdG9yeUxwMkFzc2V0c01hcHBpbmcBBQxscEFzc2V0SWRTdHIJAKwCAgIVdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQxscEFzc2V0SWRTdHIECXBvb2xBZGRvbgkBC3ZhbHVlT3JFbHNlAgkAnQgCCQERQGV4dHJOYXRpdmUoMTA2MikBBQ5wb29sQWRkcmVzc1N0cgkBDGtleUFkZG9uQWRkcgAFDnBvb2xBZGRyZXNzU3RyBAljYWxsZXJTdHIJAKUIAQgFAWkGY2FsbGVyBA51c2VyQWRkcmVzc1N0cgMDCQAAAgUJY2FsbGVyU3RyBQ5wb29sQWRkcmVzc1N0cgYJAAACBQljYWxsZXJTdHIFCXBvb2xBZGRvbgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFCWNhbGxlclN0cgQPc3Rha2VkQnlVc2VyS0VZCQEPa2V5U3Rha2VkQnlVc2VyAgUOdXNlckFkZHJlc3NTdHIFDGxwQXNzZXRJZFN0cgQOc3Rha2VkVG90YWxLRVkJAQ5rZXlTdGFrZWRUb3RhbAEFDGxwQXNzZXRJZFN0cgQMc3Rha2VkQnlVc2VyCQEKcmVhZFN0YWtlZAEFD3N0YWtlZEJ5VXNlcktFWQQLc3Rha2VkVG90YWwJAQpyZWFkU3Rha2VkAQUOc3Rha2VkVG90YWxLRVkEDWludGVncmFsU1RBVEUICQEQcmVmcmVzaElOVEVHUkFMUwQFDGxwQXNzZXRJZFN0cgUOdXNlckFkZHJlc3NTdHIFDnBvb2xBZGRyZXNzU3RyCQEBLQEFBmFtb3VudAJfMgQIbGlzdE5hbWUJARBnZXRVc2Vyc0xpc3ROYW1lAQUMbHBBc3NldElkU3RyBAtsaXN0QWN0aW9ucwMDCQEMY29udGFpbnNOb2RlAgUIbGlzdE5hbWUFDnVzZXJBZGRyZXNzU3RyCQAAAgUGYW1vdW50BQxzdGFrZWRCeVVzZXIHCQERZGVsZXRlTm9kZUFjdGlvbnMCBQhsaXN0TmFtZQUOdXNlckFkZHJlc3NTdHIFA25pbAQWY2xhaW1lZEJ5VXNlck1pblJld2FyZAkBGWdldEJpZ0ludEZyb21TdHJpbmdPclplcm8CBQR0aGlzCQEZa2V5Q2xhaW1lZEJ5VXNlck1pblJld2FyZAIFDGxwQXNzZXRJZFN0cgUOdXNlckFkZHJlc3NTdHIEC3Bvb2xBZGRyZXNzCQEYZ2V0U3RyaW5nQnlBZGRyZXNzT3JGYWlsAgUPZmFjdG9yeUNvbnRyYWN0CQEma2V5RmFjdG9yeUxwQXNzZXRUb1Bvb2xDb250cmFjdEFkZHJlc3MBBQxscEFzc2V0SWRTdHIEEHd4VG9DbGFpbVVzZXJOZXcICQEQcmVmcmVzaElOVEVHUkFMUwQFDGxwQXNzZXRJZFN0cgUOdXNlckFkZHJlc3NTdHIFC3Bvb2xBZGRyZXNzAAACXzEEEGF2YWlsYWJsZVRvQ2xhaW0JALgCAgUQd3hUb0NsYWltVXNlck5ldwUWY2xhaW1lZEJ5VXNlck1pblJld2FyZAQBcgMJAL8CAgUQYXZhaWxhYmxlVG9DbGFpbQUKemVyb0JpZ0ludAkA/AcEBQR0aGlzAg9jbGFpbVd4SU5URVJOQUwJAMwIAgUMbHBBc3NldElkU3RyCQDMCAIFDnVzZXJBZGRyZXNzU3RyBQNuaWwFA25pbAUEdW5pdAMJAAACBQFyBQFyAwkAZgIFBmFtb3VudAUMc3Rha2VkQnlVc2VyCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg5wYXNzZWQgYW1vdW50PQkApAMBBQZhbW91bnQCGyBpcyBncmVhdGVyIHRoYW4gYXZhaWxhYmxlPQkApAMBBQxzdGFrZWRCeVVzZXICDC4gbHBBc3NldElkPQUMbHBBc3NldElkU3RyAhIuIHN0YWtlZEJ5VXNlcktFWT0FD3N0YWtlZEJ5VXNlcktFWQkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFD3N0YWtlZEJ5VXNlcktFWQkAZQIFDHN0YWtlZEJ5VXNlcgUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5zdGFrZWRUb3RhbEtFWQkAZQIFC3N0YWtlZFRvdGFsBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQZhbW91bnQFCWxwQXNzZXRJZAkAzAgCCQEVT3BlcmF0aW9uSGlzdG9yeUVudHJ5BQIHdW5zdGFrZQUOdXNlckFkZHJlc3NTdHIFDGxwQXNzZXRJZFN0cgUGYW1vdW50CAUBaQ10cmFuc2FjdGlvbklkBQNuaWwFDWludGVncmFsU1RBVEUFC2xpc3RBY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBB2NsYWltV3gBDGxwQXNzZXRJZFN0cgQOdXNlckFkZHJlc3NTdHIJAKUIAQgFAWkGY2FsbGVyBAZyZXN1bHQJAPwHBAUEdGhpcwIPY2xhaW1XeElOVEVSTkFMCQDMCAIFDGxwQXNzZXRJZFN0cgkAzAgCBQ51c2VyQWRkcmVzc1N0cgUDbmlsBQNuaWwJAJQKAgUDbmlsBQZyZXN1bHQBaQEPY2xhaW1XeElOVEVSTkFMAgxscEFzc2V0SWRTdHIOdXNlckFkZHJlc3NTdHIEC2NoZWNrQ2FsbGVyCQEIbXVzdFRoaXMBBQFpAwkAAAIFC2NoZWNrQ2FsbGVyBQtjaGVja0NhbGxlcgQLdXNlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQ51c2VyQWRkcmVzc1N0cgIlY2xhaW1XeElOVEVSTkFMOiBpbnZhbGlkIHVzZXIgYWRkcmVzcwQOcG9vbEFkZHJlc3NTdHIJARhnZXRTdHJpbmdCeUFkZHJlc3NPckZhaWwCBQ9mYWN0b3J5Q29udHJhY3QJASZrZXlGYWN0b3J5THBBc3NldFRvUG9vbENvbnRyYWN0QWRkcmVzcwEFDGxwQXNzZXRJZFN0cgQQY2xhaW1lZEJ5VXNlcktFWQkBEGtleUNsYWltZWRCeVVzZXICBQxscEFzc2V0SWRTdHIFDnVzZXJBZGRyZXNzU3RyBA9jbGFpbWVkVG90YWxLRVkJAQ9rZXlDbGFpbWVkVG90YWwBBQxscEFzc2V0SWRTdHIEGWNsYWltZWRCeVVzZXJNaW5SZXdhcmRLRVkJARlrZXlDbGFpbWVkQnlVc2VyTWluUmV3YXJkAgUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgQbY2xhaW1lZEJ5VXNlckJvb3N0UmV3YXJkS0VZCQEba2V5Q2xhaW1lZEJ5VXNlckJvb3N0UmV3YXJkAgUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgQNY2xhaW1lZEJ5VXNlcgkBGWdldEJpZ0ludEZyb21TdHJpbmdPclplcm8CBQR0aGlzBRBjbGFpbWVkQnlVc2VyS0VZBBZjbGFpbWVkQnlVc2VyTWluUmV3YXJkCQEZZ2V0QmlnSW50RnJvbVN0cmluZ09yWmVybwIFBHRoaXMFGWNsYWltZWRCeVVzZXJNaW5SZXdhcmRLRVkEGGNsYWltZWRCeVVzZXJCb29zdFJld2FyZAkBGWdldEJpZ0ludEZyb21TdHJpbmdPclplcm8CBQR0aGlzBRtjbGFpbWVkQnlVc2VyQm9vc3RSZXdhcmRLRVkEDGNsYWltZWRUb3RhbAkBGWdldEJpZ0ludEZyb21TdHJpbmdPclplcm8CBQR0aGlzBQ9jbGFpbWVkVG90YWxLRVkEDSR0MDIzMzE3MjM0MjkJARByZWZyZXNoSU5URUdSQUxTBAUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgUOcG9vbEFkZHJlc3NTdHIAAAQQd3hUb0NsYWltVXNlck5ldwgFDSR0MDIzMzE3MjM0MjkCXzEEDWludGVncmFsU1RBVEUIBQ0kdDAyMzMxNzIzNDI5Al8yBAVkZWJ1ZwgFDSR0MDIzMzE3MjM0MjkCXzMEEGF2YWlsYWJsZVRvQ2xhaW0JAJgDAQkAzAgCCQC4AgIFEHd4VG9DbGFpbVVzZXJOZXcFFmNsYWltZWRCeVVzZXJNaW5SZXdhcmQJAMwIAgUKemVyb0JpZ0ludAUDbmlsAwkAwAICBQp6ZXJvQmlnSW50BRBhdmFpbGFibGVUb0NsYWltCQACAQIQbm90aGluZyB0byBjbGFpbQQSd3hBbW91bnRCb29zdFRvdGFsCQCWAwEJAMwIAgkBBWFzSW50AQkAkQMCCQEJYXNBbnlMaXN0AQkA/AcEBRBib29zdGluZ0NvbnRyYWN0AgxjbGFpbVd4Qm9vc3QJAMwIAgUMbHBBc3NldElkU3RyCQDMCAIFDnVzZXJBZGRyZXNzU3RyBQNuaWwFA25pbAAACQDMCAIAAAUDbmlsBA1taW5SZXdhcmRQYXJ0BRBhdmFpbGFibGVUb0NsYWltBA9ib29zdFJld2FyZFBhcnQJAJkDAQkAzAgCCQC5AgIFDW1pblJld2FyZFBhcnQJALYCAQACCQDMCAIJALYCAQUSd3hBbW91bnRCb29zdFRvdGFsBQNuaWwECXd4QXNzZXRJZAkBDGFzQnl0ZVZlY3RvcgEJAJEDAgkBCWFzQW55TGlzdAEJAPwHBAUQZW1pc3Npb25Db250cmFjdAIEZW1pdAkAzAgCCQCgAwEFDW1pblJld2FyZFBhcnQFA25pbAUDbmlsAAAECWVtaXRCb29zdAkBCWFzQW55TGlzdAEJAPwHBAUQZW1pc3Npb25Db250cmFjdAIEZW1pdAkAzAgCCQCgAwEFD2Jvb3N0UmV3YXJkUGFydAUDbmlsBQNuaWwDCQAAAgUJZW1pdEJvb3N0BQllbWl0Qm9vc3QEEmNsYWltZWRCeVVzZXJWYWx1ZQkAtwICCQC3AgIFDWNsYWltZWRCeVVzZXIFDW1pblJld2FyZFBhcnQFD2Jvb3N0UmV3YXJkUGFydAQeY2xhaW1lZEJ5VXNlck1pblJld2FyZFBsdXNQYXJ0CQC3AgIFFmNsYWltZWRCeVVzZXJNaW5SZXdhcmQFDW1pblJld2FyZFBhcnQEK2NsYWltZWRCeVVzZXJCb29zdFJld2FyZFBsdXNCb29zdFJld2FyZFBhcnQJALcCAgUYY2xhaW1lZEJ5VXNlckJvb3N0UmV3YXJkBQ9ib29zdFJld2FyZFBhcnQEIGNsYWltZWRUb3RhbFBsdXNBdmFpbGFibGVUb0NsYWltCQC3AgIFDGNsYWltZWRUb3RhbAUQYXZhaWxhYmxlVG9DbGFpbQkAzAgCCQELU3RyaW5nRW50cnkCBRBjbGFpbWVkQnlVc2VyS0VZCQCmAwEFEmNsYWltZWRCeVVzZXJWYWx1ZQkAzAgCCQELU3RyaW5nRW50cnkCBRljbGFpbWVkQnlVc2VyTWluUmV3YXJkS0VZCQCmAwEFHmNsYWltZWRCeVVzZXJNaW5SZXdhcmRQbHVzUGFydAkAzAgCCQELU3RyaW5nRW50cnkCBRtjbGFpbWVkQnlVc2VyQm9vc3RSZXdhcmRLRVkJAKYDAQUrY2xhaW1lZEJ5VXNlckJvb3N0UmV3YXJkUGx1c0Jvb3N0UmV3YXJkUGFydAkAzAgCCQELU3RyaW5nRW50cnkCBQ9jbGFpbWVkVG90YWxLRVkJAKYDAQUgY2xhaW1lZFRvdGFsUGx1c0F2YWlsYWJsZVRvQ2xhaW0JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MJAKADAQUNbWluUmV3YXJkUGFydAUJd3hBc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFC3VzZXJBZGRyZXNzCQCgAwEFD2Jvb3N0UmV3YXJkUGFydAUJd3hBc3NldElkCQDMCAIJARVPcGVyYXRpb25IaXN0b3J5RW50cnkFAgVjbGFpbQUOdXNlckFkZHJlc3NTdHIFDGxwQXNzZXRJZFN0cgkAoAMBBRBhdmFpbGFibGVUb0NsYWltCAUBaQ10cmFuc2FjdGlvbklkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEbY2xhaW1XeEJ1bGtJbnRlcm5hbFJFQURPTkxZBAtjdXJyZW50SXRlcgpscEFzc2V0SWRzDnVzZXJBZGRyZXNzU3RyBnJlc0FjYwMJAAACBQtjdXJyZW50SXRlcgkAkAMBBQpscEFzc2V0SWRzCQCUCgIFA25pbAUGcmVzQWNjBAlscEFzc2V0SWQJAJEDAgUKbHBBc3NldElkcwULY3VycmVudEl0ZXIEBGluZm8JALUJAgoAAUAJAPwHBAUEdGhpcwIPY2xhaW1XeFJFQURPTkxZCQDMCAIFCWxwQXNzZXRJZAkAzAgCBQ51c2VyQWRkcmVzc1N0cgUDbmlsBQNuaWwDCQABAgUBQAIGU3RyaW5nBQFACQACAQkArAICCQADAQUBQAIbIGNvdWxkbid0IGJlIGNhc3QgdG8gU3RyaW5nBQNTRVAECXVuY2xhaW1lZAkAkQMCBQRpbmZvAAMEB2NsYWltZWQJAJEDAgUEaW5mbwAEBANyZXMJAM0IAgUGcmVzQWNjCQC5CQIJAMwIAgIEJWQlZAkAzAgCBQl1bmNsYWltZWQJAMwIAgUHY2xhaW1lZAUDbmlsBQNTRVAEA2ludgoAAUAJAPwHBAUEdGhpcwIbY2xhaW1XeEJ1bGtJbnRlcm5hbFJFQURPTkxZCQDMCAIJAGQCBQtjdXJyZW50SXRlcgABCQDMCAIFCmxwQXNzZXRJZHMJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgUDcmVzBQNuaWwFA25pbAMJAAECBQFAAglMaXN0W0FueV0FAUAJAAIBCQCsAgIJAAMBBQFAAh4gY291bGRuJ3QgYmUgY2FzdCB0byBMaXN0W0FueV0DCQAAAgUDaW52BQNpbnYJAJQKAgUDbmlsBQNpbnYJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETY2xhaW1XeEJ1bGtSRUFET05MWQIKbHBBc3NldElkcw51c2VyQWRkcmVzc1N0cgQDcmVzCQD8BwQFBHRoaXMCG2NsYWltV3hCdWxrSW50ZXJuYWxSRUFET05MWQkAzAgCAAAJAMwIAgUKbHBBc3NldElkcwkAzAgCBQ51c2VyQWRkcmVzc1N0cgkAzAgCBQNuaWwFA25pbAUDbmlsCQCUCgIFA25pbAUDcmVzAWkBD2NsYWltV3hSRUFET05MWQIMbHBBc3NldElkU3RyDnVzZXJBZGRyZXNzU3RyBA9zdGFrZWRCeVVzZXJLRVkJAQ9rZXlTdGFrZWRCeVVzZXICBQ51c2VyQWRkcmVzc1N0cgUMbHBBc3NldElkU3RyBA5zdGFrZWRUb3RhbEtFWQkBDmtleVN0YWtlZFRvdGFsAQUMbHBBc3NldElkU3RyBBBjbGFpbWVkQnlVc2VyS0VZCQEQa2V5Q2xhaW1lZEJ5VXNlcgIFDGxwQXNzZXRJZFN0cgUOdXNlckFkZHJlc3NTdHIEGWNsYWltZWRCeVVzZXJNaW5SZXdhcmRLRVkJARlrZXlDbGFpbWVkQnlVc2VyTWluUmV3YXJkAgUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgQMc3Rha2VkQnlVc2VyCQEKcmVhZFN0YWtlZAEFD3N0YWtlZEJ5VXNlcktFWQQLc3Rha2VkVG90YWwJAQpyZWFkU3Rha2VkAQUOc3Rha2VkVG90YWxLRVkEDWNsYWltZWRCeVVzZXIJARlnZXRCaWdJbnRGcm9tU3RyaW5nT3JaZXJvAgUEdGhpcwUQY2xhaW1lZEJ5VXNlcktFWQQWY2xhaW1lZEJ5VXNlck1pblJld2FyZAkBGWdldEJpZ0ludEZyb21TdHJpbmdPclplcm8CBQR0aGlzBRljbGFpbWVkQnlVc2VyTWluUmV3YXJkS0VZBA5wb29sQWRkcmVzc1N0cgkBGGdldFN0cmluZ0J5QWRkcmVzc09yRmFpbAIFD2ZhY3RvcnlDb250cmFjdAkBJmtleUZhY3RvcnlMcEFzc2V0VG9Qb29sQ29udHJhY3RBZGRyZXNzAQUMbHBBc3NldElkU3RyBApwb29sV2VpZ2h0CQERQGV4dHJOYXRpdmUoMTA1MCkCBQ9mYWN0b3J5Q29udHJhY3QJARRrZXlGYWN0b3J5UG9vbFdlaWdodAEFDnBvb2xBZGRyZXNzU3RyBBJ3eEVtaXNzaW9uUGVyQmxvY2sJAQxnZXRJbnRPckZhaWwCBRBlbWlzc2lvbkNvbnRyYWN0CQEea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50AAQSZW1pc3Npb25TdGFydEJsb2NrCQEMZ2V0SW50T3JGYWlsAgUQZW1pc3Npb25Db250cmFjdAkBFWtleUVtaXNzaW9uU3RhcnRCbG9jawAEDHBhc3NlZEJsb2NrcwMJAGYCBRJlbWlzc2lvblN0YXJ0QmxvY2sFBmhlaWdodAAACQBlAgUGaGVpZ2h0BRJlbWlzc2lvblN0YXJ0QmxvY2sEDnBvb2xXeEVtaXNzaW9uCQBrAwkAaAIFEnd4RW1pc3Npb25QZXJCbG9jawUMcGFzc2VkQmxvY2tzBQpwb29sV2VpZ2h0BQ5QT09MV0VJR0hUTVVMVAQMdXNlcld4UmV3YXJkCQBrAwUOcG9vbFd4RW1pc3Npb24FDHN0YWtlZEJ5VXNlcgULc3Rha2VkVG90YWwEDSR0MDI3MTU3MjcyNjkJARByZWZyZXNoSU5URUdSQUxTBAUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgUOcG9vbEFkZHJlc3NTdHIAAAQQd3hUb0NsYWltVXNlck5ldwgFDSR0MDI3MTU3MjcyNjkCXzEEDWludGVncmFsU1RBVEUIBQ0kdDAyNzE1NzI3MjY5Al8yBAVkZWJ1ZwgFDSR0MDI3MTU3MjcyNjkCXzMEEGF2YWlsYWJsZVRvQ2xhaW0JAJgDAQkAzAgCCQC4AgIFEHd4VG9DbGFpbVVzZXJOZXcFFmNsYWltZWRCeVVzZXJNaW5SZXdhcmQJAMwIAgUKemVyb0JpZ0ludAUDbmlsBA5ib29zdEludlJlc3VsdAkBCWFzQW55TGlzdAEJAPwHBAUQYm9vc3RpbmdDb250cmFjdAIUY2xhaW1XeEJvb3N0UkVBRE9OTFkJAMwIAgUMbHBBc3NldElkU3RyCQDMCAIFDnVzZXJBZGRyZXNzU3RyBQNuaWwFA25pbAQSd3hBbW91bnRCb29zdFRvdGFsCQCWAwEJAMwIAgkBBWFzSW50AQkAkQMCBQ5ib29zdEludlJlc3VsdAAACQDMCAIAAAUDbmlsBApib29zdERlYnVnCQEIYXNTdHJpbmcBCQCRAwIFDmJvb3N0SW52UmVzdWx0AAEEDW1pblJld2FyZFBhcnQFEGF2YWlsYWJsZVRvQ2xhaW0ED2Jvb3N0UmV3YXJkUGFydAkAmQMBCQDMCAIJALkCAgUNbWluUmV3YXJkUGFydAkAtgIBAAIJAMwIAgkAtgIBBRJ3eEFtb3VudEJvb3N0VG90YWwFA25pbAQLdG90YWxSZXdhcmQJALcCAgUNbWluUmV3YXJkUGFydAUPYm9vc3RSZXdhcmRQYXJ0CQCUCgIFA25pbAkAuQkCCQDMCAICDiVzJXMlZCVkJWQlZCVzCQDMCAIFDGxwQXNzZXRJZFN0cgkAzAgCBQ51c2VyQWRkcmVzc1N0cgkAzAgCCQCmAwEFC3RvdGFsUmV3YXJkCQDMCAIJAKYDAQUNY2xhaW1lZEJ5VXNlcgkAzAgCCQCmAwEFDW1pblJld2FyZFBhcnQJAMwIAgkApgMBBQ9ib29zdFJld2FyZFBhcnQJAMwIAgIEc29vbgUDbmlsBQNTRVABaQESdXNlcnNMaXN0VHJhdmVyc2FsAQlscEFzc2V0SWQEC2NoZWNrQ2FsbGVyAwkAAAIJANgEAQgIBQFpBmNhbGxlcgVieXRlcwkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQEZa2V5Vm90aW5nRW1pc3Npb25Db250cmFjdAACAAYJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBAhsaXN0TmFtZQkBEGdldFVzZXJzTGlzdE5hbWUBBQlscEFzc2V0SWQECnVzZXJPclVuaXQJAKIIAQkBC2tleU5leHRVc2VyAQUJbHBBc3NldElkBApoZWFkT3JVbml0CQCiCAEJAQtrZXlMaXN0SGVhZAEFCGxpc3ROYW1lBAckbWF0Y2gwBQp1c2VyT3JVbml0AwkAAQIFByRtYXRjaDACBFVuaXQEByRtYXRjaDEFCmhlYWRPclVuaXQDCQABAgUHJG1hdGNoMQIEVW5pdAkAlAoCBQNuaWwHAwkAAQIFByRtYXRjaDECBlN0cmluZwQEaGVhZAUHJG1hdGNoMQkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQtrZXlOZXh0VXNlcgEFCWxwQXNzZXRJZAUEaGVhZAUDbmlsBgkAAgECC01hdGNoIGVycm9yAwkAAQIFByRtYXRjaDACBlN0cmluZwQLdXNlckFkZHJlc3MFByRtYXRjaDAEFmNsYWltZWRCeVVzZXJNaW5SZXdhcmQJARlnZXRCaWdJbnRGcm9tU3RyaW5nT3JaZXJvAgUEdGhpcwkBGWtleUNsYWltZWRCeVVzZXJNaW5SZXdhcmQCBQlscEFzc2V0SWQFC3VzZXJBZGRyZXNzBAtwb29sQWRkcmVzcwkBGGdldFN0cmluZ0J5QWRkcmVzc09yRmFpbAIFD2ZhY3RvcnlDb250cmFjdAkBJmtleUZhY3RvcnlMcEFzc2V0VG9Qb29sQ29udHJhY3RBZGRyZXNzAQUJbHBBc3NldElkBBB3eFRvQ2xhaW1Vc2VyTmV3CAkBEHJlZnJlc2hJTlRFR1JBTFMEBQlscEFzc2V0SWQFC3VzZXJBZGRyZXNzBQtwb29sQWRkcmVzcwAAAl8xBBBhdmFpbGFibGVUb0NsYWltCQC4AgIFEHd4VG9DbGFpbVVzZXJOZXcFFmNsYWltZWRCeVVzZXJNaW5SZXdhcmQEAXIDCQC/AgIFEGF2YWlsYWJsZVRvQ2xhaW0FCnplcm9CaWdJbnQJAPwHBAUEdGhpcwIPY2xhaW1XeElOVEVSTkFMCQDMCAIFCWxwQXNzZXRJZAkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQNuaWwFBHVuaXQDCQAAAgUBcgUBcgQObmV4dFVzZXJPclVuaXQJAKIIAQkBC2tleUxpc3ROZXh0AgUIbGlzdE5hbWUFC3VzZXJBZGRyZXNzBAckbWF0Y2gxBQ5uZXh0VXNlck9yVW5pdAMJAAECBQckbWF0Y2gxAgRVbml0CQCUCgIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBC2tleU5leHRVc2VyAQUJbHBBc3NldElkBQNuaWwHAwkAAQIFByRtYXRjaDECBlN0cmluZwQIbmV4dFVzZXIFByRtYXRjaDEJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQELa2V5TmV4dFVzZXIBBQlscEFzc2V0SWQFCG5leHRVc2VyBQNuaWwGCQACAQILTWF0Y2ggZXJyb3IJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAgtNYXRjaCBlcnJvcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5vbk1vZGlmeVdlaWdodAIMbHBBc3NldElkU3RyDnBvb2xBZGRyZXNzU3RyAwkBAiE9AggFAWkGY2FsbGVyBQ9mYWN0b3J5Q29udHJhY3QJAAIBAhJwZXJtaXNzaW9ucyBkZW5pZWQEDSR0MDI5NjU3Mjk3NjcJARRyZWZyZXNoUG9vbElOVEVHUkFMUwMFDGxwQXNzZXRJZFN0cgUOcG9vbEFkZHJlc3NTdHIAAAQSd3hQZXJMcEludGVncmFsTmV3CAUNJHQwMjk2NTcyOTc2NwJfMQQRcG9vbEludGVncmFsU1RBVEUIBQ0kdDAyOTY1NzI5NzY3Al8yBAlwb29sREVCVUcIBQ0kdDAyOTY1NzI5NzY3Al8zBRFwb29sSW50ZWdyYWxTVEFURQECdHgBBnZlcmlmeQAED3RhcmdldFB1YmxpY0tleQQHJG1hdGNoMAkBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwBQJwawMJAAECBQckbWF0Y2gwAgRVbml0CAUCdHgPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAFD3RhcmdldFB1YmxpY0tledTyIRk=", "chainId": 84, "height": 2458137, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 5UUaHnBjkkMqHeoUVZWY3owN2u8n35ktgwFeburikQY Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let SCALE8 = 8
5+
6+let MULT8 = 100000000
7+
8+let SCALE18 = 18
9+
10+let MULT18 = toBigInt(1000000000000000000)
11+
12+let SEP = "__"
13+
14+let POOLWEIGHTMULT = MULT8
15+
16+let zeroBigInt = toBigInt(0)
17+
18+let oneBigInt = toBigInt(1)
19+
20+func asAnyList (val) = match val {
21+ case valAnyLyst: List[Any] =>
22+ valAnyLyst
23+ case _ =>
24+ throw("fail to cast into List[Any]")
25+}
26+
27+
28+func asInt (val) = match val {
29+ case valInt: Int =>
30+ valInt
31+ case _ =>
32+ throw("fail to cast into Int")
33+}
34+
35+
36+func asString (val) = match val {
37+ case valStr: String =>
38+ valStr
39+ case _ =>
40+ throw("fail to cast into Int")
41+}
42+
43+
44+func asByteVector (val) = match val {
45+ case valBin: ByteVector =>
46+ valBin
47+ case _ =>
48+ throw("fail to cast into Int")
49+}
50+
51+
52+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (("mandatory this." + key) + " is not defined"))
53+
54+
55+func getStringByAddressOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
56+
57+
58+func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
59+
60+
61+func getIntOrDefault (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
62+
63+
64+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
65+
66+
67+func getBigIntFromStringOrZero (address,key) = value(parseBigInt(valueOrElse(getString(address, key), "0")))
68+
69+
70+func getBigIntFromStringOrDefault (address,key,defaultVal) = match getString(address, key) {
71+ case s: String =>
72+ value(parseBigInt(s))
73+ case _: Unit =>
74+ defaultVal
75+ case _ =>
76+ throw("Match error")
77+}
78+
79+
80+func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), MULT18, toBigInt(origScaleMult))
81+
82+
83+func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), MULT18))
84+
85+
86+func keyFactoryAddress () = "%s%s__config__factoryAddress"
87+
88+
89+func keyVotingEmissionContract () = "%s__votingEmissionContract"
90+
91+
92+let IdxFactoryCfgStakingDapp = 1
93+
94+let IdxFactoryCfgBoostingDapp = 2
95+
96+let IdxFactoryCfgIdoDapp = 3
97+
98+let IdxFactoryCfgTeamDapp = 4
99+
100+let IdxFactoryCfgEmissionDapp = 5
101+
102+let IdxFactoryCfgRestDapp = 6
103+
104+let IdxFactoryCfgSlippageDapp = 7
105+
106+func keyFactoryCfg () = "%s__factoryConfig"
107+
108+
109+func keyManagerPublicKey () = "%s__managerPublicKey"
110+
111+
112+func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
113+
114+
115+func keyStablePoolAddonAddr () = "%s__stablePoolAddonAddr"
116+
117+
118+func keyAddonAddr () = "%s__addonAddr"
119+
120+
121+func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
122+
123+
124+func keyFactoryLpList () = "%s__lpTokensList"
125+
126+
127+func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
128+
129+
130+func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
131+
132+
133+func readLpList (factory) = split(valueOrElse(getString(factory, keyFactoryLpList()), ""), SEP)
134+
135+
136+func readFactoryCfgOrFail (factory) = split(getStringByAddressOrFail(factory, keyFactoryCfg()), SEP)
137+
138+
139+func getBoostingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgBoostingDapp])
140+
141+
142+func getEmissionAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgEmissionDapp])
143+
144+
145+func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
146+
147+
148+func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
149+
150+
151+func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
152+
153+
154+func keyEmissionStartBlock () = "%s%s__emission__startBlock"
155+
156+
157+func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
158+
159+
160+func keyEmissionEndBlock () = "%s%s__emission__endBlock"
161+
162+
163+func keyStakedByUser (userAddressStr,lpAssetIdStr) = makeString(["%s%s%s__staked", userAddressStr, lpAssetIdStr], SEP)
164+
165+
166+func keyStakedTotal (lpAssetIdStr) = ("%s%s%s__staked__total__" + lpAssetIdStr)
167+
168+
169+func keyClaimedByUser (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimed", userAddressStr, lpAssetIdStr], SEP)
170+
171+
172+func keyClaimedByUserMinReward (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimedMinReward", userAddressStr, lpAssetIdStr], SEP)
173+
174+
175+func keyClaimedByUserBoostReward (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimedBoostReward", userAddressStr, lpAssetIdStr], SEP)
176+
177+
178+func keyClaimedTotal (lpAssetIdStr) = makeString(["%s%s%s__claimed__total", lpAssetIdStr], SEP)
179+
180+
181+func readStaked (key) = valueOrElse(getInteger(this, key), 0)
182+
183+
184+func keyLastTotalLpBalance (lpAssetId) = makeString(["%s%s%s", lpAssetId, "total", "bal"], SEP)
185+
186+
187+func keyLastUserLpBalance (lpAssetId,userAddress) = makeString(["%s%s%s", lpAssetId, userAddress, "bal"], SEP)
188+
189+
190+func keyTotalLpBalanceIntegral (lpAssetId) = makeString(["%s%s%s", lpAssetId, "total", "balINT"], SEP)
191+
192+
193+func keyUserLpBalanceIntegral (lpAssetId,userAddress) = makeString(["%s%s%s", lpAssetId, userAddress, "balINT"], SEP)
194+
195+
196+func keyTotalLpBalanceIntegralLastUpdHeight (lpAssetId) = makeString(["%s%s%s", lpAssetId, "total", "lastUpd"], SEP)
197+
198+
199+func keyUserLpBalanceIntegralLastUpdHeight (lpAssetId,userAddress) = makeString(["%s%s%s", lpAssetId, userAddress, "lastUpd"], SEP)
200+
201+
202+func keyWxPerLpIntegral (lpAssetId) = makeString(["%s%s%s%s", lpAssetId, "common", "lpInt"], SEP)
203+
204+
205+func keyWxPerLpIntegralLastUpdHeight (lpAssetId) = makeString(["%s%s%s%s", lpAssetId, "common", "lpIntH"], SEP)
206+
207+
208+func keyWxToClaimUser (lpAssetId,userAddress) = makeString(["%s%s%s%s", lpAssetId, userAddress, "lpInt"], SEP)
209+
210+
211+func keyWxPerLpIntegralUserLastUpdHeight (lpAssetId,userAddress) = makeString(["%s%s%s%s", lpAssetId, userAddress, "lpIntH"], SEP)
212+
213+
214+func keyWxPerLp (lpAssetId) = makeString(["%s", lpAssetId, "wxPerLp"], SEP)
215+
216+
217+func keyWxPerLpX18 (lpAssetId) = makeString(["%s", lpAssetId, "wxPerLpX18"], SEP)
218+
219+
220+func keyWxPerLpIntegralUserLast (lpAssetId,userAddress) = makeString(["%s%s%s%s", lpAssetId, userAddress, "uIntL"], SEP)
221+
222+
223+func keyOperationHistoryRecord (type,userAddress,txId58) = makeString(["%s%s%s%s__history", type, userAddress, txId58], SEP)
224+
225+
226+func formatHistoryRecord (userAddress,lpAssetId,type,amount) = makeString(["%s%s%s%d%d%d", userAddress, lpAssetId, type, toString(height), toString(lastBlock.timestamp), toString(amount)], SEP)
227+
228+
229+func OperationHistoryEntry (type,userAddress,lpAssetId,amount,txId) = StringEntry(keyOperationHistoryRecord(type, userAddress, toBase58String(txId)), formatHistoryRecord(userAddress, lpAssetId, type, amount))
230+
231+
232+let factoryAddress = getStringOrFail(this, keyFactoryAddress())
233+
234+let factoryContract = addressFromStringValue(factoryAddress)
235+
236+let factoryCfg = readFactoryCfgOrFail(factoryContract)
237+
238+let emissionContract = getEmissionAddressOrFail(factoryCfg)
239+
240+let boostingContract = getBoostingAddressOrFail(factoryCfg)
241+
242+func keyNextUser (lpAssetId) = makeString(["%s%s", lpAssetId, "nextUser"], SEP)
243+
244+
245+func getUsersListName (lpAssetId) = makeString(["users", lpAssetId], SEP)
246+
247+
248+func keyListHead (listName) = makeString(["%s%s%s", listName, "head"], SEP)
249+
250+
251+func keyListSize (listName) = makeString(["%s%s%s", listName, "size"], SEP)
252+
253+
254+func keyListPrev (listName,id) = makeString(["%s%s%s%s", listName, id, "prev"], SEP)
255+
256+
257+func keyListNext (listName,id) = makeString(["%s%s%s%s", listName, id, "next"], SEP)
258+
259+
260+func containsNode (listName,id) = {
261+ let headOrUnit = getString(this, keyListHead(listName))
262+ let prevOrUnit = getString(this, keyListPrev(listName, id))
263+ let nextOrUnit = getString(this, keyListNext(listName, id))
264+ if (if ((id == valueOrElse(headOrUnit, "")))
265+ then true
266+ else (prevOrUnit != unit))
267+ then true
268+ else (nextOrUnit != unit)
269+ }
270+
271+
272+func insertNodeActions (listName,id) = {
273+ let headOrUnit = getString(this, keyListHead(listName))
274+ let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
275+ let checkNode = if (!(containsNode(listName, id)))
276+ then true
277+ else throw("Node exists")
278+ if ((checkNode == checkNode))
279+ then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if ((headOrUnit != unit))
280+ then [StringEntry(keyListNext(listName, id), value(headOrUnit)), StringEntry(keyListPrev(listName, value(headOrUnit)), id)]
281+ else nil)) ++ [StringEntry(keyListHead(listName), id)])
282+ else throw("Strict value is not equal to itself.")
283+ }
284+
285+
286+func deleteNodeActions (listName,id) = {
287+ let headOrUnit = getString(this, keyListHead(listName))
288+ let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
289+ let prevOrUnit = getString(this, keyListPrev(listName, id))
290+ let nextOrUnit = getString(this, keyListNext(listName, id))
291+ ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if ((prevOrUnit != unit))
292+ then (nextOrUnit != unit)
293+ else false)
294+ then [StringEntry(keyListNext(listName, value(prevOrUnit)), value(nextOrUnit)), StringEntry(keyListPrev(listName, value(nextOrUnit)), value(prevOrUnit)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))]
295+ else if ((nextOrUnit != unit))
296+ then [StringEntry(keyListHead(listName), value(nextOrUnit)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(nextOrUnit)))]
297+ else if ((prevOrUnit != unit))
298+ then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prevOrUnit)))]
299+ else if ((id == valueOrElse(headOrUnit, "")))
300+ then [DeleteEntry(keyListHead(listName))]
301+ else throw(((("invalid node: " + listName) + ".") + id))))
302+ }
303+
304+
305+func calcWxPerLpIntegralUserLast (stakedByUser,wxPerLpIntegralUserLastUpdHeightOrZero,wxPerLpIntegralNew,wxPerLpIntegralUserLastKEY) = if (if ((wxPerLpIntegralUserLastUpdHeightOrZero == zeroBigInt))
306+ then (stakedByUser > zeroBigInt)
307+ else false)
308+ then zeroBigInt
309+ else if ((stakedByUser == zeroBigInt))
310+ then wxPerLpIntegralNew
311+ else if (if ((wxPerLpIntegralUserLastUpdHeightOrZero > zeroBigInt))
312+ then (stakedByUser > zeroBigInt)
313+ else false)
314+ then value(parseBigInt(getStringOrFail(this, wxPerLpIntegralUserLastKEY)))
315+ else throw("calcWxPerLpIntegralUserLast: unexpected state")
316+
317+
318+func refreshPoolINTEGRALS (lpAssetIdStr,poolAddressStr,lpDeltaAmount) = {
319+ let stakedTotalKEY = keyStakedTotal(lpAssetIdStr)
320+ let stakedTotal = toBigInt(readStaked(stakedTotalKEY))
321+ let nonZeroStakedTotal = if ((stakedTotal == zeroBigInt))
322+ then oneBigInt
323+ else stakedTotal
324+ let poolWeight = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
325+ let emissionStartBlock = getIntOrFail(emissionContract, keyEmissionStartBlock())
326+ let MULT3 = 1000
327+ let wxEmissionPerBlockX3 = (getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent()) * MULT3)
328+ let poolWxEmissionPerBlockX3 = fraction(wxEmissionPerBlockX3, poolWeight, (POOLWEIGHTMULT * 3))
329+ let wxPerLpIntegralKEY = keyWxPerLpIntegral(lpAssetIdStr)
330+ let wxPerLpIntegralLastUpdHeightKEY = keyWxPerLpIntegralLastUpdHeight(lpAssetIdStr)
331+ let wxPerLpKEY = keyWxPerLp(lpAssetIdStr)
332+ let wxPerLpIntegralLastUpdHeight = getIntOrDefault(this, wxPerLpIntegralLastUpdHeightKEY, emissionStartBlock)
333+ let wxPerLpIntegral = getBigIntFromStringOrZero(this, wxPerLpIntegralKEY)
334+ let wxPerLpOrZeroX3 = 0
335+ let dh = max([(height - wxPerLpIntegralLastUpdHeight), 0])
336+ let wxPerLpX3 = if ((wxPerLpOrZeroX3 != 0))
337+ then toBigInt(wxPerLpOrZeroX3)
338+ else fraction(toBigInt(poolWxEmissionPerBlockX3), toBigInt(MULT8), nonZeroStakedTotal)
339+ let stakedTotalNew = (stakedTotal + toBigInt(lpDeltaAmount))
340+ let nonZeroStakedTotalNew = if ((stakedTotalNew == zeroBigInt))
341+ then oneBigInt
342+ else stakedTotalNew
343+ let wxPerLpIntegralNew = (wxPerLpIntegral + (wxPerLpX3 * toBigInt(dh)))
344+ let wxPerLpX3New = (toBigInt(poolWxEmissionPerBlockX3) / nonZeroStakedTotalNew)
345+ let wxPerLpIntegralLastUpdHeightNew = height
346+ let debug = makeString([toString(wxPerLpIntegralNew), toString(dh), toString(wxPerLpX3), toString(stakedTotal), toString(poolWxEmissionPerBlockX3), toString(wxEmissionPerBlockX3), toString(poolWeight)], "::")
347+ $Tuple3(wxPerLpIntegralNew, [StringEntry(wxPerLpIntegralKEY, toString(wxPerLpIntegralNew)), IntegerEntry(wxPerLpIntegralLastUpdHeightKEY, wxPerLpIntegralLastUpdHeightNew), StringEntry(wxPerLpKEY, toString(wxPerLpX3New))], debug)
348+ }
349+
350+
351+func refreshINTEGRALS (lpAssetIdStr,userAddressStr,poolAddressStr,lpDeltaAmount) = {
352+ let $t01457514697 = refreshPoolINTEGRALS(lpAssetIdStr, poolAddressStr, lpDeltaAmount)
353+ let wxPerLpIntegralNew = $t01457514697._1
354+ let poolIntegralSTATE = $t01457514697._2
355+ let poolDEBUG = $t01457514697._3
356+ let MULT3 = 1000
357+ let stakedByUserKEY = keyStakedByUser(userAddressStr, lpAssetIdStr)
358+ let stakedByUser = readStaked(stakedByUserKEY)
359+ let wxToClaimUserKEY = keyWxToClaimUser(lpAssetIdStr, userAddressStr)
360+ let wxPerLpIntegralUserLastUpdHeightKEY = keyWxPerLpIntegralUserLastUpdHeight(lpAssetIdStr, userAddressStr)
361+ let wxPerLpIntegralUserLastKEY = keyWxPerLpIntegralUserLast(lpAssetIdStr, userAddressStr)
362+ let wxToClaimUser = getBigIntFromStringOrZero(this, wxToClaimUserKEY)
363+ let wxPerLpIntegralUserLastUpdHeightOrZero = getIntOrZero(this, wxPerLpIntegralUserLastUpdHeightKEY)
364+ let wxPerLpIntegralUserLast = calcWxPerLpIntegralUserLast(toBigInt(stakedByUser), toBigInt(wxPerLpIntegralUserLastUpdHeightOrZero), wxPerLpIntegralNew, wxPerLpIntegralUserLastKEY)
365+ let MULT11 = (MULT8 * MULT3)
366+ let wxToClaimUserNew = max([(wxToClaimUser + fraction((wxPerLpIntegralNew - wxPerLpIntegralUserLast), toBigInt(stakedByUser), toBigInt(MULT11))), zeroBigInt])
367+ let wxPerLpIntegralUserLastNew = wxPerLpIntegralNew
368+ let wxPerLpIntegralUserLastUpdHeightNew = height
369+ let debug = makeString([toString(wxToClaimUser), toString(wxPerLpIntegralUserLast), toString(stakedByUser), poolDEBUG, toString(height)], "::")
370+ $Tuple3(wxToClaimUserNew, (poolIntegralSTATE ++ [StringEntry(wxToClaimUserKEY, toString(wxToClaimUserNew)), IntegerEntry(wxPerLpIntegralUserLastUpdHeightKEY, wxPerLpIntegralUserLastUpdHeightNew), StringEntry(wxPerLpIntegralUserLastKEY, toString(wxPerLpIntegralUserLastNew))]), debug)
371+ }
372+
373+
374+func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
375+ case s: String =>
376+ fromBase58String(s)
377+ case _: Unit =>
378+ unit
379+ case _ =>
380+ throw("Match error")
381+}
382+
383+
384+func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
385+ case s: String =>
386+ fromBase58String(s)
387+ case _: Unit =>
388+ unit
389+ case _ =>
390+ throw("Match error")
391+}
392+
393+
394+let permissionDeniedError = throw("Permission denied")
395+
396+func mustThis (i) = if ((i.caller == this))
397+ then true
398+ else permissionDeniedError
399+
400+
401+func mustManager (i) = match managerPublicKeyOrUnit() {
402+ case pk: ByteVector =>
403+ if ((i.callerPublicKey == pk))
404+ then true
405+ else permissionDeniedError
406+ case _: Unit =>
407+ if ((i.caller == this))
408+ then true
409+ else permissionDeniedError
410+ case _ =>
411+ throw("Match error")
412+}
413+
414+
415+@Callable(i)
416+func constructor (factoryAddressStr) = {
417+ let checkCaller = mustManager(i)
418+ if ((checkCaller == checkCaller))
419+ then [StringEntry(keyFactoryAddress(), factoryAddressStr)]
420+ else throw("Strict value is not equal to itself.")
421+ }
422+
423+
424+
425+@Callable(i)
426+func constructorV2 (votingEmissionContract) = {
427+ let cheks = [mustManager(i), if ((addressFromString(votingEmissionContract) != unit))
428+ then true
429+ else "invalid voting emission contract address"]
430+ if ((cheks == cheks))
431+ then [StringEntry(keyVotingEmissionContract(), votingEmissionContract)]
432+ else throw("Strict value is not equal to itself.")
433+ }
434+
435+
436+
437+@Callable(i)
438+func setManager (pendingManagerPublicKey) = {
439+ let checkCaller = mustManager(i)
440+ if ((checkCaller == checkCaller))
441+ then {
442+ let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
443+ if ((checkManagerPublicKey == checkManagerPublicKey))
444+ then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
445+ else throw("Strict value is not equal to itself.")
446+ }
447+ else throw("Strict value is not equal to itself.")
448+ }
449+
450+
451+
452+@Callable(i)
453+func confirmManager () = {
454+ let pm = pendingManagerPublicKeyOrUnit()
455+ let hasPM = if (isDefined(pm))
456+ then true
457+ else throw("No pending manager")
458+ if ((hasPM == hasPM))
459+ then {
460+ let checkPM = if ((i.callerPublicKey == value(pm)))
461+ then true
462+ else throw("You are not pending manager")
463+ if ((checkPM == checkPM))
464+ then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
465+ else throw("Strict value is not equal to itself.")
466+ }
467+ else throw("Strict value is not equal to itself.")
468+ }
469+
470+
471+
472+@Callable(i)
473+func stake () = if ((size(i.payments) != 1))
474+ then throw("invalid payment - exact one payment must be attached")
475+ else {
476+ let pmt = i.payments[0]
477+ let lpAssetId = value(pmt.assetId)
478+ let lpAssetIdStr = toBase58String(lpAssetId)
479+ let amount = pmt.amount
480+ let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
481+ let callerStr = toString(i.caller)
482+ let userAddressStr = if ((callerStr == poolAddressStr))
483+ then toString(i.originCaller)
484+ else callerStr
485+ let stakedByUserKEY = keyStakedByUser(userAddressStr, lpAssetIdStr)
486+ let stakedTotalKEY = keyStakedTotal(lpAssetIdStr)
487+ let stakedByUser = readStaked(stakedByUserKEY)
488+ let stakedTotal = readStaked(stakedTotalKEY)
489+ let $t01925919376 = refreshINTEGRALS(lpAssetIdStr, userAddressStr, poolAddressStr, amount)
490+ let wxToClaimUserNew = $t01925919376._1
491+ let integralSTATE = $t01925919376._2
492+ let debug = $t01925919376._3
493+ let listName = getUsersListName(lpAssetIdStr)
494+ let listActions = if (containsNode(listName, userAddressStr))
495+ then nil
496+ else insertNodeActions(listName, userAddressStr)
497+ (([IntegerEntry(stakedByUserKEY, (stakedByUser + amount)), IntegerEntry(stakedTotalKEY, (stakedTotal + amount)), OperationHistoryEntry("stake", userAddressStr, lpAssetIdStr, amount, i.transactionId)] ++ integralSTATE) ++ listActions)
498+ }
499+
500+
501+
502+@Callable(i)
503+func unstake (lpAssetIdStr,amount) = {
504+ let lpAssetId = fromBase58String(lpAssetIdStr)
505+ let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
506+ let poolAddon = valueOrElse(getString(addressFromStringValue(poolAddressStr), keyAddonAddr()), poolAddressStr)
507+ let callerStr = toString(i.caller)
508+ let userAddressStr = if (if ((callerStr == poolAddressStr))
509+ then true
510+ else (callerStr == poolAddon))
511+ then toString(i.originCaller)
512+ else callerStr
513+ let stakedByUserKEY = keyStakedByUser(userAddressStr, lpAssetIdStr)
514+ let stakedTotalKEY = keyStakedTotal(lpAssetIdStr)
515+ let stakedByUser = readStaked(stakedByUserKEY)
516+ let stakedTotal = readStaked(stakedTotalKEY)
517+ let integralSTATE = refreshINTEGRALS(lpAssetIdStr, userAddressStr, poolAddressStr, -(amount))._2
518+ let listName = getUsersListName(lpAssetIdStr)
519+ let listActions = if (if (containsNode(listName, userAddressStr))
520+ then (amount == stakedByUser)
521+ else false)
522+ then deleteNodeActions(listName, userAddressStr)
523+ else nil
524+ let claimedByUserMinReward = getBigIntFromStringOrZero(this, keyClaimedByUserMinReward(lpAssetIdStr, userAddressStr))
525+ let poolAddress = getStringByAddressOrFail(factoryContract, keyFactoryLpAssetToPoolContractAddress(lpAssetIdStr))
526+ let wxToClaimUserNew = refreshINTEGRALS(lpAssetIdStr, userAddressStr, poolAddress, 0)._1
527+ let availableToClaim = (wxToClaimUserNew - claimedByUserMinReward)
528+ let r = if ((availableToClaim > zeroBigInt))
529+ then invoke(this, "claimWxINTERNAL", [lpAssetIdStr, userAddressStr], nil)
530+ else unit
531+ if ((r == r))
532+ then if ((amount > stakedByUser))
533+ then throw(((((((("passed amount=" + toString(amount)) + " is greater than available=") + toString(stakedByUser)) + ". lpAssetId=") + lpAssetIdStr) + ". stakedByUserKEY=") + stakedByUserKEY))
534+ else (([IntegerEntry(stakedByUserKEY, (stakedByUser - amount)), IntegerEntry(stakedTotalKEY, (stakedTotal - amount)), ScriptTransfer(i.caller, amount, lpAssetId), OperationHistoryEntry("unstake", userAddressStr, lpAssetIdStr, amount, i.transactionId)] ++ integralSTATE) ++ listActions)
535+ else throw("Strict value is not equal to itself.")
536+ }
537+
538+
539+
540+@Callable(i)
541+func claimWx (lpAssetIdStr) = {
542+ let userAddressStr = toString(i.caller)
543+ let result = invoke(this, "claimWxINTERNAL", [lpAssetIdStr, userAddressStr], nil)
544+ $Tuple2(nil, result)
545+ }
546+
547+
548+
549+@Callable(i)
550+func claimWxINTERNAL (lpAssetIdStr,userAddressStr) = {
551+ let checkCaller = mustThis(i)
552+ if ((checkCaller == checkCaller))
553+ then {
554+ let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), "claimWxINTERNAL: invalid user address")
555+ let poolAddressStr = getStringByAddressOrFail(factoryContract, keyFactoryLpAssetToPoolContractAddress(lpAssetIdStr))
556+ let claimedByUserKEY = keyClaimedByUser(lpAssetIdStr, userAddressStr)
557+ let claimedTotalKEY = keyClaimedTotal(lpAssetIdStr)
558+ let claimedByUserMinRewardKEY = keyClaimedByUserMinReward(lpAssetIdStr, userAddressStr)
559+ let claimedByUserBoostRewardKEY = keyClaimedByUserBoostReward(lpAssetIdStr, userAddressStr)
560+ let claimedByUser = getBigIntFromStringOrZero(this, claimedByUserKEY)
561+ let claimedByUserMinReward = getBigIntFromStringOrZero(this, claimedByUserMinRewardKEY)
562+ let claimedByUserBoostReward = getBigIntFromStringOrZero(this, claimedByUserBoostRewardKEY)
563+ let claimedTotal = getBigIntFromStringOrZero(this, claimedTotalKEY)
564+ let $t02331723429 = refreshINTEGRALS(lpAssetIdStr, userAddressStr, poolAddressStr, 0)
565+ let wxToClaimUserNew = $t02331723429._1
566+ let integralSTATE = $t02331723429._2
567+ let debug = $t02331723429._3
568+ let availableToClaim = max([(wxToClaimUserNew - claimedByUserMinReward), zeroBigInt])
569+ if ((zeroBigInt >= availableToClaim))
570+ then throw("nothing to claim")
571+ else {
572+ let wxAmountBoostTotal = max([asInt(asAnyList(invoke(boostingContract, "claimWxBoost", [lpAssetIdStr, userAddressStr], nil))[0]), 0])
573+ let minRewardPart = availableToClaim
574+ let boostRewardPart = min([(minRewardPart * toBigInt(2)), toBigInt(wxAmountBoostTotal)])
575+ let wxAssetId = asByteVector(asAnyList(invoke(emissionContract, "emit", [toInt(minRewardPart)], nil))[0])
576+ let emitBoost = asAnyList(invoke(emissionContract, "emit", [toInt(boostRewardPart)], nil))
577+ if ((emitBoost == emitBoost))
578+ then {
579+ let claimedByUserValue = ((claimedByUser + minRewardPart) + boostRewardPart)
580+ let claimedByUserMinRewardPlusPart = (claimedByUserMinReward + minRewardPart)
581+ let claimedByUserBoostRewardPlusBoostRewardPart = (claimedByUserBoostReward + boostRewardPart)
582+ let claimedTotalPlusAvailableToClaim = (claimedTotal + availableToClaim)
583+[StringEntry(claimedByUserKEY, toString(claimedByUserValue)), StringEntry(claimedByUserMinRewardKEY, toString(claimedByUserMinRewardPlusPart)), StringEntry(claimedByUserBoostRewardKEY, toString(claimedByUserBoostRewardPlusBoostRewardPart)), StringEntry(claimedTotalKEY, toString(claimedTotalPlusAvailableToClaim)), ScriptTransfer(userAddress, toInt(minRewardPart), wxAssetId), ScriptTransfer(userAddress, toInt(boostRewardPart), wxAssetId), OperationHistoryEntry("claim", userAddressStr, lpAssetIdStr, toInt(availableToClaim), i.transactionId)]
584+ }
585+ else throw("Strict value is not equal to itself.")
586+ }
587+ }
588+ else throw("Strict value is not equal to itself.")
589+ }
590+
591+
592+
593+@Callable(i)
594+func claimWxBulkInternalREADONLY (currentIter,lpAssetIds,userAddressStr,resAcc) = if ((currentIter == size(lpAssetIds)))
595+ then $Tuple2(nil, resAcc)
596+ else {
597+ let lpAssetId = lpAssetIds[currentIter]
598+ let info = split({
599+ let @ = invoke(this, "claimWxREADONLY", [lpAssetId, userAddressStr], nil)
600+ if ($isInstanceOf(@, "String"))
601+ then @
602+ else throw(($getType(@) + " couldn't be cast to String"))
603+ }, SEP)
604+ let unclaimed = info[3]
605+ let claimed = info[4]
606+ let res = (resAcc :+ makeString(["%d%d", unclaimed, claimed], SEP))
607+ let inv = {
608+ let @ = invoke(this, "claimWxBulkInternalREADONLY", [(currentIter + 1), lpAssetIds, userAddressStr, res], nil)
609+ if ($isInstanceOf(@, "List[Any]"))
610+ then @
611+ else throw(($getType(@) + " couldn't be cast to List[Any]"))
612+ }
613+ if ((inv == inv))
614+ then $Tuple2(nil, inv)
615+ else throw("Strict value is not equal to itself.")
616+ }
617+
618+
619+
620+@Callable(i)
621+func claimWxBulkREADONLY (lpAssetIds,userAddressStr) = {
622+ let res = invoke(this, "claimWxBulkInternalREADONLY", [0, lpAssetIds, userAddressStr, nil], nil)
623+ $Tuple2(nil, res)
624+ }
625+
626+
627+
628+@Callable(i)
629+func claimWxREADONLY (lpAssetIdStr,userAddressStr) = {
630+ let stakedByUserKEY = keyStakedByUser(userAddressStr, lpAssetIdStr)
631+ let stakedTotalKEY = keyStakedTotal(lpAssetIdStr)
632+ let claimedByUserKEY = keyClaimedByUser(lpAssetIdStr, userAddressStr)
633+ let claimedByUserMinRewardKEY = keyClaimedByUserMinReward(lpAssetIdStr, userAddressStr)
634+ let stakedByUser = readStaked(stakedByUserKEY)
635+ let stakedTotal = readStaked(stakedTotalKEY)
636+ let claimedByUser = getBigIntFromStringOrZero(this, claimedByUserKEY)
637+ let claimedByUserMinReward = getBigIntFromStringOrZero(this, claimedByUserMinRewardKEY)
638+ let poolAddressStr = getStringByAddressOrFail(factoryContract, keyFactoryLpAssetToPoolContractAddress(lpAssetIdStr))
639+ let poolWeight = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
640+ let wxEmissionPerBlock = getIntOrFail(emissionContract, keyEmissionRatePerBlockCurrent())
641+ let emissionStartBlock = getIntOrFail(emissionContract, keyEmissionStartBlock())
642+ let passedBlocks = if ((emissionStartBlock > height))
643+ then 0
644+ else (height - emissionStartBlock)
645+ let poolWxEmission = fraction((wxEmissionPerBlock * passedBlocks), poolWeight, POOLWEIGHTMULT)
646+ let userWxReward = fraction(poolWxEmission, stakedByUser, stakedTotal)
647+ let $t02715727269 = refreshINTEGRALS(lpAssetIdStr, userAddressStr, poolAddressStr, 0)
648+ let wxToClaimUserNew = $t02715727269._1
649+ let integralSTATE = $t02715727269._2
650+ let debug = $t02715727269._3
651+ let availableToClaim = max([(wxToClaimUserNew - claimedByUserMinReward), zeroBigInt])
652+ let boostInvResult = asAnyList(invoke(boostingContract, "claimWxBoostREADONLY", [lpAssetIdStr, userAddressStr], nil))
653+ let wxAmountBoostTotal = max([asInt(boostInvResult[0]), 0])
654+ let boostDebug = asString(boostInvResult[1])
655+ let minRewardPart = availableToClaim
656+ let boostRewardPart = min([(minRewardPart * toBigInt(2)), toBigInt(wxAmountBoostTotal)])
657+ let totalReward = (minRewardPart + boostRewardPart)
658+ $Tuple2(nil, makeString(["%s%s%d%d%d%d%s", lpAssetIdStr, userAddressStr, toString(totalReward), toString(claimedByUser), toString(minRewardPart), toString(boostRewardPart), "soon"], SEP))
659+ }
660+
661+
662+
663+@Callable(i)
664+func usersListTraversal (lpAssetId) = {
665+ let checkCaller = if ((toBase58String(i.caller.bytes) == valueOrElse(getString(this, keyVotingEmissionContract()), "")))
666+ then true
667+ else mustManager(i)
668+ if ((checkCaller == checkCaller))
669+ then {
670+ let listName = getUsersListName(lpAssetId)
671+ let userOrUnit = getString(keyNextUser(lpAssetId))
672+ let headOrUnit = getString(keyListHead(listName))
673+ match userOrUnit {
674+ case _: Unit =>
675+ match headOrUnit {
676+ case _: Unit =>
677+ $Tuple2(nil, false)
678+ case head: String =>
679+ $Tuple2([StringEntry(keyNextUser(lpAssetId), head)], true)
680+ case _ =>
681+ throw("Match error")
682+ }
683+ case userAddress: String =>
684+ let claimedByUserMinReward = getBigIntFromStringOrZero(this, keyClaimedByUserMinReward(lpAssetId, userAddress))
685+ let poolAddress = getStringByAddressOrFail(factoryContract, keyFactoryLpAssetToPoolContractAddress(lpAssetId))
686+ let wxToClaimUserNew = refreshINTEGRALS(lpAssetId, userAddress, poolAddress, 0)._1
687+ let availableToClaim = (wxToClaimUserNew - claimedByUserMinReward)
688+ let r = if ((availableToClaim > zeroBigInt))
689+ then invoke(this, "claimWxINTERNAL", [lpAssetId, userAddress], nil)
690+ else unit
691+ if ((r == r))
692+ then {
693+ let nextUserOrUnit = getString(keyListNext(listName, userAddress))
694+ match nextUserOrUnit {
695+ case _: Unit =>
696+ $Tuple2([DeleteEntry(keyNextUser(lpAssetId))], false)
697+ case nextUser: String =>
698+ $Tuple2([StringEntry(keyNextUser(lpAssetId), nextUser)], true)
699+ case _ =>
700+ throw("Match error")
701+ }
702+ }
703+ else throw("Strict value is not equal to itself.")
704+ case _ =>
705+ throw("Match error")
706+ }
707+ }
708+ else throw("Strict value is not equal to itself.")
709+ }
710+
711+
712+
713+@Callable(i)
714+func onModifyWeight (lpAssetIdStr,poolAddressStr) = if ((i.caller != factoryContract))
715+ then throw("permissions denied")
716+ else {
717+ let $t02965729767 = refreshPoolINTEGRALS(lpAssetIdStr, poolAddressStr, 0)
718+ let wxPerLpIntegralNew = $t02965729767._1
719+ let poolIntegralSTATE = $t02965729767._2
720+ let poolDEBUG = $t02965729767._3
721+ poolIntegralSTATE
722+ }
723+
724+
725+@Verifier(tx)
726+func verify () = {
727+ let targetPublicKey = match managerPublicKeyOrUnit() {
728+ case pk: ByteVector =>
729+ pk
730+ case _: Unit =>
731+ tx.senderPublicKey
732+ case _ =>
733+ throw("Match error")
734+ }
735+ sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
736+ }
737+

github/deemru/w8io/873ac7e 
35.85 ms