tx · 7jUP7RZW931eSHAxcMhYdAVZoGUAuGbQYGGahpUgcspA 3MvdaY2bNUeXhNEAAbUi1TziTnk1d4R7tJJ: -0.01000000 Waves 2021.07.07 18:11 [1603335] smart account 3MvdaY2bNUeXhNEAAbUi1TziTnk1d4R7tJJ > SELF 0.00000000 Waves
{ "type": 13, "id": "7jUP7RZW931eSHAxcMhYdAVZoGUAuGbQYGGahpUgcspA", "fee": 1000000, "feeAssetId": null, "timestamp": 1625670661152, "version": 2, "chainId": 84, "sender": "3MvdaY2bNUeXhNEAAbUi1TziTnk1d4R7tJJ", "senderPublicKey": "2B3qchDqepnLaAZbMGF9si9fhU4gjAhgRy2uRXfB1mce", "proofs": [ "3SuxaVvzeqyoini5Fn1myCU4jupS5zf4BGoFtw9LxX2LeGnxvzkjL6mQhB1h8N4uGZf7tqSoqQYxBAyf54H9bWsF" ], "script": "base64:AAIEAAAAAAAAADAIAhIICgYICAEBCAgSBgoECAEIARIDCgEIEgMKAQgSBAoCCAESBAoCCAgSBAoCCAgAAABrAQAAAAxnZXRCb29sQnlLZXkAAAABAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACBQAAAAR0aGlzBQAAAANrZXkHAAAAAANTRVACAAAAAl9fAAAAAAxrZXlBc3NldENvZGUAAAAAAAAAAAEAAAAACmtleUFzc2V0SWQAAAAAAAAAAAIAAAAADmtleUFzc2V0U3RhdHVzAAAAAAAAAAADAAAAABVrZXlBc3NldFByaWNlRGVjaW1hbHMAAAAAAAAAAAQAAAAAE2tleUFzc2V0QmFraW5nQXNzZXQAAAAAAAAAAAUAAAAAG2tleU92ZXJjb2xsYXRlcmFsUGVyY2VudGFnZQAAAAAAAAAABgAAAAAKa2V5TWluUG9vbAAAAAAAAAAABwAAAAAVa2V5UHJpY2VPcmFjbGVBZGRyZXNzAAAAAAAAAAAIAAAAABBrZXlNaW5CdXlQYXltZW50AAAAAAAAAAAJAAAAABFrZXlNaW5TZWxsUGF5bWVudAAAAAAAAAAACgAAAAASa2V5QnV5TG9ja0ludGVydmFsAAAAAAAAAAALAAAAABNrZXlTZWxsTG9ja0ludGVydmFsAAAAAAAAAAAMAAAAAAlrZXlCdXlGZWUAAAAAAAAAAA0AAAAACmtleVNlbGxGZWUAAAAAAAAAAA4AAAAAGGtleVBvb2xSZWRlbXB0aW9uVGltZW91dAAAAAAAAAAADwAAAAAha2V5V2Vla2VuZHNQcmljZUNoYW5nZUNvZWZmaWNpZW50AAAAAAAAAAAQAAAAABhrZXlBc3NldEFjY291bnRQdWJsaWNTdHIAAAAAAAAAABEAAAAAIGtleUFzc2V0U3Rha2luZ1JlZmVycmFsUHVibGljU3RyAAAAAAAAAAASAAAAABtrZXlDcm9zc0V4Y2hhbmdlQ29lZmZpY2llbnQAAAAAAAAAABMAAAAAI2tleVN0YWtpbmdNaW5BbXRGcm9tU2VsbENvZWZmaWNpZW50AAAAAAAAAAAUAAAAABNrZXlQb29sU3RhYmlsaXR5RmVlAAAAAAAAAAAVAAAAAA5rZXlQcm90b2NvbEZlZQAAAAAAAAAAFgAAAAAOYWRtaW5QdWJsaWNLZXkCAAAALDNZU01zMnhYMzg1NzVrUXF5V3RIRWN5ZFUzemZEWHFjYml1RUxSaERodkI4AAAAABpuZXV0cmlub0NvbnRyYWN0QWRkcmVzc0tleQIAAAArJXMlc19fY29tbW9uQ29uZmlnX19uZXV0cmlub0NvbnRyYWN0QWRkcmVzcwAAAAAZbmV1dHJpbm9TdGFraW5nQWRkcmVzc0tleQIAAAAqJXMlc19fY29tbW9uQ29uZmlnX19uZXV0cmlub1N0YWtpbmdBZGRyZXNzAAAAABttaW5pbXVuUG9vbEZ1bmRpbmdBbW91bnRLZXkCAAAALCVzJXNfX2NvbW1vbkNvbmZpZ19fbWluaW11bVBvb2xGdW5kaW5nQW1vdW50AAAAABBpc0luaXRpYWxpemVkS2V5AgAAAB8lcyVzX19jb21tb25Db25maWdfX2luaXRpYWxpemVkAAAAAA5kZWJ0VG9rZW5JZEtleQIAAAAfJXMlc19fY29tbW9uQ29uZmlnX19kZWJ0QXNzZXRJZAAAAAAZZGVidFRva2VuRXRhbG9uQmFsYW5jZUtleQIAAAAqJXMlc19fY29tbW9uQ29uZmlnX19kZWJ0QXNzZXRFdGFsb25CYWxhbmNlAAAAABVkZWZvU3Rha2luZ0FkZHJlc3NLZXkCAAAAJiVzJXNfX2NvbW1vbkNvbmZpZ19fZGVmb1N0YWtpbmdBZGRyZXNzAAAAABpkZWZvU3Rha2luZ1BhY2VtYWtlclB1YktleQIAAAArJXMlc19fY29tbW9uQ29uZmlnX19kZWZvU3Rha2luZ1BhY2VtYWtlclB1YgAAAAASbmV1dHJpbm9Bc3NldElkS2V5AgAAABFuZXV0cmlub19hc3NldF9pZAAAAAAObnNidEFzc2V0SWRLZXkCAAAADWJvbmRfYXNzZXRfaWQAAAAADm5ldXRyaW5vUnBkS2V5AgAAAAxycGRfY29udHJhY3QAAAAADmRlZm9Bc3NldElkS2V5AgAAAA8lc19fZGVmb0Fzc2V0SWQAAAAAFXNldEFzc2V0U2NyaXB0VHhJZEtleQIAAAATJXNfX2Fzc2V0U2NyaXB0VHhJZAEAAAARZ2V0QXNzZXRDb25maWdLZXkAAAABAAAADGFzc2V0QWRkcmVzcwkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAADGFzc2V0QWRkcmVzcwIAAAAIX19jb25maWcAAAAAHElkeFByZUluaXRpYWxpemVkQXNzZXRQdWJsaWMAAAAAAAAAAAAAAAAAK0lkeFByZUluaXRpYWxpemVkQXNzZXRTdGFraW5nUmVmZXJyYWxQdWJsaWMAAAAAAAAAAAEAAAAAIUlkeFByZUluaXRpYWxpemVkQXNzZXREZXNjcmlwdGlvbgAAAAAAAAAAAgEAAAAdZ2V0UHJlSW5pdGlhbGl6ZWRBc3NldERhdGFLZXkAAAABAAAACWFzc2V0Q29kZQkAASwAAAACAgAAAB8lcyVzX19wcmVJbml0aWFsaXplZEFzc2V0RGF0YV9fBQAAAAlhc3NldENvZGUBAAAAEGdldEFzc2V0UHJpY2VLZXkAAAABAAAACWFzc2V0Q29kZQkAASwAAAACAgAAAA0lcyVzX19wcmljZV9fBQAAAAlhc3NldENvZGUBAAAAFWdldEFzc2V0SW5pdEhlaWdodEtleQAAAAEAAAAMYXNzZXRBZGRyZXNzCQABLAAAAAIJAAEsAAAAAgIAAAATJXMlcyVzX19kZWZvQXNzZXRfXwUAAAAMYXNzZXRBZGRyZXNzAgAAAAxfX2luaXRIZWlnaHQBAAAAGWdldEFzc2V0QWN0aXZhdGVIZWlnaHRLZXkAAAABAAAADGFzc2V0QWRkcmVzcwkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAADGFzc2V0QWRkcmVzcwIAAAAQX19hY3RpdmF0ZUhlaWdodAEAAAAdZ2V0QXNzZXRDdXJycmVudFBvb2xBbW91bnRLZXkAAAABAAAADGFzc2V0QWRkcmVzcwkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAADGFzc2V0QWRkcmVzcwIAAAANX19jdXJyZW50UG9vbAEAAAAYZ2V0QXNzZXRNYXhQb29sQW1vdW50S2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAxhc3NldEFkZHJlc3MCAAAACV9fbWF4UG9vbAEAAAAPZ2V0QXNzZXRNZXRhS2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAxhc3NldEFkZHJlc3MCAAAABl9fbWV0YQEAAAAYZ2V0QXNzZXRBZGRyZXNzQnlDb2RlS2V5AAAAAQAAAAlhc3NldENvZGUJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAlhc3NldENvZGUCAAAAFF9fYWRkcmVzc0J5QXNzZXRDb2RlAQAAABtnZXRBc3NldEFkZHJlc3NCeUFzc2V0SWRLZXkAAAABAAAAB2Fzc2V0SWQJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAdhc3NldElkAgAAABJfX2FkZHJlc3NCeUFzc2V0SWQBAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25BbW91bnRLZXkAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAOJXMlcyVzJXNfX3Bvb2wJAARMAAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAIFAAAAEHBvb2xNYWtlckFkZHJlc3MJAARMAAAAAgIAAAAGYW1vdW50BQAAAANuaWwFAAAAA1NFUAEAAAAlZ2V0UG9vbE1ha2VyUGFydGljaXBhdGlvbk1heEFtb3VudEtleQAAAAIAAAAMYXNzZXRBZGRyZXNzAAAAEHBvb2xNYWtlckFkZHJlc3MJAAS5AAAAAgkABEwAAAACAgAAAA4lcyVzJXMlc19fcG9vbAkABEwAAAACBQAAAAxhc3NldEFkZHJlc3MJAARMAAAAAgUAAAAQcG9vbE1ha2VyQWRkcmVzcwkABEwAAAACAgAAAAltYXhBbW91bnQFAAAAA25pbAUAAAADU0VQAQAAABtnZXRQb29sTWFrZXJMb2NrZWRBbW91bnRLZXkAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAOJXMlcyVzJXNfX3Bvb2wJAARMAAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAIFAAAAEHBvb2xNYWtlckFkZHJlc3MJAARMAAAAAgIAAAAMbG9ja2VkQW1vdW50BQAAAANuaWwFAAAAA1NFUAEAAAAbZ2V0UG9vbE1ha2VyVW5sb2NrSGVpZ2h0S2V5AAAAAgAAAAxhc3NldEFkZHJlc3MAAAAQcG9vbE1ha2VyQWRkcmVzcwkABLkAAAACCQAETAAAAAICAAAADiVzJXMlcyVzX19wb29sCQAETAAAAAIFAAAADGFzc2V0QWRkcmVzcwkABEwAAAACBQAAABBwb29sTWFrZXJBZGRyZXNzCQAETAAAAAICAAAADHVubG9ja0hlaWdodAUAAAADbmlsBQAAAANTRVABAAAAH2dldFBvb2xNYWtlckxpcXVpZGl0eVJlcXVlc3RLZXkAAAADAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzAAAAAWgJAAS5AAAAAgkABEwAAAACAgAAABAlcyVzJXMlZCVzX19wb29sCQAETAAAAAIFAAAADGFzc2V0QWRkcmVzcwkABEwAAAACBQAAABBwb29sTWFrZXJBZGRyZXNzCQAETAAAAAIJAAGkAAAAAQUAAAABaAkABEwAAAACAgAAABBsaXF1aWRpdHlSZXF1ZXN0BQAAAANuaWwFAAAAA1NFUAEAAAAbZ2V0UG9vbFRvdGFsTG9ja2VkQW1vdW50S2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAS5AAAAAgkABEwAAAACAgAAAAwlcyVzJXNfX3Bvb2wJAARMAAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAICAAAAEXRvdGFsTG9ja2VkQW1vdW50BQAAAANuaWwFAAAAA1NFUAEAAAAZZ2V0UG9vbE1pbkludmVzdEFtb3VudEtleQAAAAEAAAAMYXNzZXRBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAMJXMlcyVzX19wb29sCQAETAAAAAIFAAAADGFzc2V0QWRkcmVzcwkABEwAAAACAgAAAA9taW5JbnZlc3RBbW91bnQFAAAAA25pbAUAAAADU0VQAQAAABlnZXRQb29sTWluUmVkZWVtQW1vdW50S2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAS5AAAAAgkABEwAAAACAgAAAAwlcyVzJXNfX3Bvb2wJAARMAAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAICAAAAD21pblJlZGVlbUFtb3VudAUAAAADbmlsBQAAAANTRVABAAAAE2dldEFzc2V0Q29uZmlnQXJyYXkAAAABAAAADGFzc2V0QWRkcmVzcwkABLUAAAACCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwkBAAAAEWdldEFzc2V0Q29uZmlnS2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzCQABLAAAAAICAAAAIU5vIERFRk8gQXNzZXQgY29uZmlnIHByZXNlbnQgZm9yIAUAAAAMYXNzZXRBZGRyZXNzBQAAAANTRVAAAAAADW11bHRpcGxpY2F0b3IAAAAAAAAPQkAAAAAAEG5ldXRyaW5vQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAABpuZXV0cmlub0NvbnRyYWN0QWRkcmVzc0tleQIAAAAfTm8gbmV1dHJpbm8gY29udHJhY3Qgc3BlY2lmaWVkLgAAAAASbmV1dHJpbm9Bc3NldElkU3RyCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAQbmV1dHJpbm9Db250cmFjdAUAAAASbmV1dHJpbm9Bc3NldElkS2V5AgAAABdObyBVU0ROIGFzc2V0IGlkIGZvdW5kLgAAAAAPbmV1dHJpbm9Bc3NldElkCQACWQAAAAEFAAAAEm5ldXRyaW5vQXNzZXRJZFN0cgAAAAALbnNidEFzc2V0SWQJAAJZAAAAAQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAAEG5ldXRyaW5vQ29udHJhY3QFAAAADm5zYnRBc3NldElkS2V5AgAAABZObyBOU0JUIGFzc2V0IGlkIGZvdW5kAAAAABJtaW5pbXVtUG9vbEZ1bmRpbmcJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAABttaW5pbXVuUG9vbEZ1bmRpbmdBbW91bnRLZXkCAAAALU1pbmltdW0gcG9vbCBmdW5kaW5nIGFtb3VudCBpcyBub3Qgc3BlY2lmaWVkLgAAAAANQVNTRXRQUk9QT1NFRAIAAAAIUFJPUE9TRUQAAAAACkFTU0V0UkVBRFkCAAAABVJFQURZAAAAAAtBU1NFdElTU1VFRAIAAAAGSVNTVUVEAAAAAAthc3NldFN0YXR1cwkABRUAAAADBQAAAA1BU1NFdFBST1BPU0VEBQAAAApBU1NFdFJFQURZBQAAAAtBU1NFdElTU1VFRAAAAAAJZGVidFRva2VuCQACWQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAAA5kZWJ0VG9rZW5JZEtleQIAAAATTm8gZGVidCB0b2tlbiBmb3VuZAAAAAAWZGVidFRva2VuUmVpc3N1ZUFtb3VudAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAABlkZWJ0VG9rZW5FdGFsb25CYWxhbmNlS2V5AAAAAAAAAAAAAAAAABNuZXV0cmlub1JwZENvbnRyYWN0CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAARQGV4dHJOYXRpdmUoMTA1MykAAAACBQAAABBuZXV0cmlub0NvbnRyYWN0BQAAAA5uZXV0cmlub1JwZEtleQEAAAAVZ2V0TmV1dHJpbm9ScGRCYWxhbmNlAAAAAQAAAAt1c2VyQWRkcmVzcwQAAAAWdXNlck5ldXRyaW5vUnBkQmFsYW5jZQkABLkAAAACCQAETAAAAAICAAAAC3JwZF9iYWxhbmNlCQAETAAAAAIFAAAAEm5ldXRyaW5vQXNzZXRJZFN0cgkABEwAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAADbmlsAgAAAAFfCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAAE25ldXRyaW5vUnBkQ29udHJhY3QFAAAAFnVzZXJOZXV0cmlub1JwZEJhbGFuY2UAAAAAAAAAAAABAAAAFWdldEFzc2V0QWRkcmVzc0J5Q29kZQAAAAEAAAALYXNzZXRTeW1ib2wJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwkBAAAAGGdldEFzc2V0QWRkcmVzc0J5Q29kZUtleQAAAAEFAAAAC2Fzc2V0U3ltYm9sAgAAAAABAAAAG2dldEFzc2V0QWRkcmVzc0J5Q29kZU9yRmFpbAAAAAEAAAALYXNzZXRTeW1ib2wJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzCQEAAAAYZ2V0QXNzZXRBZGRyZXNzQnlDb2RlS2V5AAAAAQUAAAALYXNzZXRTeW1ib2wJAAEsAAAAAgkAASwAAAACAgAAAB1DYW5ub3QgZmluZCBhc3NldCBhZGRyZXNzIGJ5IAUAAAALYXNzZXRTeW1ib2wCAAAABSBjb2RlAQAAAAxnZXRBc3NldENvZGUAAAABAAAAC2Fzc2V0Q29uZmlnCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAAAxrZXlBc3NldENvZGUBAAAACmdldEFzc2V0SUQAAAABAAAAC2Fzc2V0Q29uZmlnCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAAAprZXlBc3NldElkAQAAAA5nZXRBc3NldFN0YXR1cwAAAAEAAAALYXNzZXRDb25maWcJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAADmtleUFzc2V0U3RhdHVzAQAAABVnZXRBc3NldFByaWNlRGVjaW1hbHMAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAFWtleUFzc2V0UHJpY2VEZWNpbWFscwEAAAAVZ2V0QXNzZXRCYWtpbmdBc3NldElkAAAAAQAAAAthc3NldENvbmZpZwkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAATa2V5QXNzZXRCYWtpbmdBc3NldAEAAAAdZ2V0QXNzZXRPdmVyQ29sbGF0ZXJhbFBlcmNlbnQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAG2tleU92ZXJjb2xsYXRlcmFsUGVyY2VudGFnZQEAAAAdZ2V0QXNzZXRNaW5SZXF1aXJlZFBvb2xBbW91bnQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAACmtleU1pblBvb2wBAAAAGmdldEFzc2V0UHJpY2VPcmFjbGVBZGRyZXNzAAAAAQAAAAthc3NldENvbmZpZwkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAAVa2V5UHJpY2VPcmFjbGVBZGRyZXNzAQAAABhnZXRNaW5CdXlQYXltZW50UGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAEGtleU1pbkJ1eVBheW1lbnQBAAAAGWdldE1pblNlbGxQYXltZW50UGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAEWtleU1pblNlbGxQYXltZW50AQAAABpnZXRCdXlMb2NrSW50ZXJ2YWxQZXJBc3NldAAAAAEAAAALYXNzZXRDb25maWcJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAASa2V5QnV5TG9ja0ludGVydmFsAQAAABtnZXRTZWxsTG9ja0ludGVydmFsUGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAE2tleVNlbGxMb2NrSW50ZXJ2YWwBAAAAEWdldEJ1eUZlZVBlckFzc2V0AAAAAQAAAAthc3NldENvbmZpZwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAAAlrZXlCdXlGZWUBAAAAEmdldFNlbGxGZWVQZXJBc3NldAAAAAEAAAALYXNzZXRDb25maWcJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAAKa2V5U2VsbEZlZQEAAAAaZ2V0UmVkZW1wdGlvblRpbWVvdXRCbG9ja3MAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAGGtleVBvb2xSZWRlbXB0aW9uVGltZW91dAEAAAAhZ2V0V2Vla2VuZHNQcmljZUNoYW5nZUNvZWZmaWNpZW50AAAAAQAAAAthc3NldENvbmZpZwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAACFrZXlXZWVrZW5kc1ByaWNlQ2hhbmdlQ29lZmZpY2llbnQBAAAAFmdldFByb3RvY29sRmVlUGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAADmtleVByb3RvY29sRmVlAQAAABJnZXRBc3NldEluaXRIZWlnaHQAAAABAAAADGFzc2V0QWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAVZ2V0QXNzZXRJbml0SGVpZ2h0S2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzAAAAAAAAAAAAAQAAABZnZXRBc3NldEFjdGl2YXRlSGVpZ2h0AAAAAQAAAAxhc3NldEFkZHJlc3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAGWdldEFzc2V0QWN0aXZhdGVIZWlnaHRLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MAAAAAAAAAAAABAAAAGWdldEFzc2V0Q3VycmVudFBvb2xBbW91bnQAAAABAAAADGFzc2V0QWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAdZ2V0QXNzZXRDdXJycmVudFBvb2xBbW91bnRLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MAAAAAAAAAAAABAAAAFWdldEFzc2V0TWF4UG9vbEFtb3VudAAAAAEAAAAMYXNzZXRBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABhnZXRBc3NldE1heFBvb2xBbW91bnRLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MAAAAAAAAAAAABAAAADGdldEFzc2V0TWV0YQAAAAEAAAAMYXNzZXRBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMJAQAAAA9nZXRBc3NldE1ldGFLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MCAAAAAAEAAAAfZ2V0UG9vbE1ha2VyUGFydGljaXBhdGlvbkFtb3VudAAAAAIAAAAMYXNzZXRBZGRyZXNzAAAAEHBvb2xNYWtlckFkZHJlc3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25BbW91bnRLZXkAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAAEHBvb2xNYWtlckFkZHJlc3MAAAAAAAAAAAABAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25NYXhBbW91bnQAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAACVnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uTWF4QW1vdW50S2V5AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAABBwb29sTWFrZXJBZGRyZXNzAAAAAAAAAAAAAQAAABhnZXRQb29sTWFrZXJMb2NrZWRBbW91bnQAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABtnZXRQb29sTWFrZXJMb2NrZWRBbW91bnRLZXkAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAAEHBvb2xNYWtlckFkZHJlc3MAAAAAAAAAAAABAAAAGGdldFBvb2xNYWtlclVubG9ja0hlaWdodAAAAAIAAAAMYXNzZXRBZGRyZXNzAAAAEHBvb2xNYWtlckFkZHJlc3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAG2dldFBvb2xNYWtlclVubG9ja0hlaWdodEtleQAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAAQcG9vbE1ha2VyQWRkcmVzcwAAAAAAAAAAAAEAAAANZ2V0QXNzZXRQcmljZQAAAAIAAAAScHJpY2VPcmFjbGVBZGRyZXNzAAAACWFzc2V0Q29kZQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAAEnByaWNlT3JhY2xlQWRkcmVzcwkBAAAAEGdldEFzc2V0UHJpY2VLZXkAAAABBQAAAAlhc3NldENvZGUCAAAAFE5vIEFzc2V0IHByaWNlIGZvdW5kAQAAABhnZXRQb29sVG90YWxMb2NrZWRBbW91bnQAAAABAAAADGFzc2V0QWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAbZ2V0UG9vbFRvdGFsTG9ja2VkQW1vdW50S2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzAAAAAAAAAAAAAQAAAB9jb21wb3NlQXNzZXRDb25maWd1cmF0aW9uU3RyaW5nAAAAFgAAAAlhc3NldENvZGUAAAAHYXNzZXRJZAAAAAthc3NldFN0YXR1cwAAAA1wcmljZURlY2ltYWxzAAAADmJhY2tpbmdBc3NldElkAAAAFW92ZXJDb2xsYXRlcmFsUGVyY2VudAAAAAdtaW5Qb29sAAAAEnByaWNlT3JhY2xlQWRkcmVzcwAAAA1taW5CdXlQYXltZW50AAAADm1pblNlbGxQYXltZW50AAAAD2J1eUxvY2tJbnRlcnZhbAAAABBzZWxsTG9ja0ludGVydmFsAAAABmJ1eUZlZQAAAAdzZWxsRmVlAAAAFXBvb2xSZWRlbXB0aW9uVGltZW91dAAAAB53ZWVrZW5kc1ByaWNlQ2hhbmdlQ29lZmZpY2llbnQAAAAVYXNzZXRBY2NvdW50UHVibGljU3RyAAAAHWFzc2V0U3Rha2luZ1JlZmVycmFsUHVibGljU3RyAAAAG2Nyb3NzRXhjaGFuZ2VDb2VmZmljaWVudFN0cgAAACNzdGFraW5nTWluQW10RnJvbVNlbGxDb2VmZmljaWVudFN0cgAAABNwb29sU3RhYmlsaXR5RmVlU3RyAAAADnByb3RvY29sRmVlU3RyCQAEuQAAAAIJAARMAAAAAgIAAAAqJXMlcyVzJWQlcyVkJWQlcyVkJWQlZCVkJWQlZCVkJWQlcyVzJWQlZCVkCQAETAAAAAIFAAAACWFzc2V0Q29kZQkABEwAAAACBQAAAAdhc3NldElkCQAETAAAAAIFAAAAC2Fzc2V0U3RhdHVzCQAETAAAAAIJAAGkAAAAAQUAAAANcHJpY2VEZWNpbWFscwkABEwAAAACBQAAAA5iYWNraW5nQXNzZXRJZAkABEwAAAACCQABpAAAAAEFAAAAFW92ZXJDb2xsYXRlcmFsUGVyY2VudAkABEwAAAACCQABpAAAAAEFAAAAB21pblBvb2wJAARMAAAAAgUAAAAScHJpY2VPcmFjbGVBZGRyZXNzCQAETAAAAAIJAAGkAAAAAQUAAAANbWluQnV5UGF5bWVudAkABEwAAAACCQABpAAAAAEFAAAADm1pblNlbGxQYXltZW50CQAETAAAAAIJAAGkAAAAAQUAAAAPYnV5TG9ja0ludGVydmFsCQAETAAAAAIJAAGkAAAAAQUAAAAQc2VsbExvY2tJbnRlcnZhbAkABEwAAAACCQABpAAAAAEFAAAABmJ1eUZlZQkABEwAAAACCQABpAAAAAEFAAAAB3NlbGxGZWUJAARMAAAAAgkAAaQAAAABBQAAABVwb29sUmVkZW1wdGlvblRpbWVvdXQJAARMAAAAAgkAAaQAAAABBQAAAB53ZWVrZW5kc1ByaWNlQ2hhbmdlQ29lZmZpY2llbnQJAARMAAAAAgUAAAAVYXNzZXRBY2NvdW50UHVibGljU3RyCQAETAAAAAIFAAAAHWFzc2V0U3Rha2luZ1JlZmVycmFsUHVibGljU3RyCQAETAAAAAIFAAAAG2Nyb3NzRXhjaGFuZ2VDb2VmZmljaWVudFN0cgkABEwAAAACBQAAACNzdGFraW5nTWluQW10RnJvbVNlbGxDb2VmZmljaWVudFN0cgkABEwAAAACBQAAABNwb29sU3RhYmlsaXR5RmVlU3RyCQAETAAAAAIFAAAADnByb3RvY29sRmVlU3RyBQAAAANuaWwCAAAAAl9fAQAAABR1cGRhdGVBc3NldENmZ1N0YXR1cwAAAAIAAAAJbmV3U3RhdHVzAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAABWFDb2RlCQEAAAAMZ2V0QXNzZXRDb2RlAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAADYUlECQEAAAAKZ2V0QXNzZXRJRAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAADmFQcmljZURlY2ltYWxzCQEAAAAVZ2V0QXNzZXRQcmljZURlY2ltYWxzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAOYUJha2luZ0Fzc2V0SWQJAQAAABVnZXRBc3NldEJha2luZ0Fzc2V0SWQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAABZhT3ZlckNvbGxhdGVyYWxQZXJjZW50CQEAAAAdZ2V0QXNzZXRPdmVyQ29sbGF0ZXJhbFBlcmNlbnQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAABBhTWluUmVxdWlyZWRQb29sCQEAAAAdZ2V0QXNzZXRNaW5SZXF1aXJlZFBvb2xBbW91bnQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAABNhUHJpY2VPcmFjbGVBZGRyZXNzCQEAAAAaZ2V0QXNzZXRQcmljZU9yYWNsZUFkZHJlc3MAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAA5hTWluQnV5UGF5bWVudAkBAAAAGGdldE1pbkJ1eVBheW1lbnRQZXJBc3NldAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAD2FNaW5TZWxsUGF5bWVudAkBAAAAGWdldE1pblNlbGxQYXltZW50UGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAABBhQnV5TG9ja0ludGVydmFsCQEAAAAaZ2V0QnV5TG9ja0ludGVydmFsUGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAABFhU2VsbExvY2tJbnRlcnZhbAkBAAAAG2dldFNlbGxMb2NrSW50ZXJ2YWxQZXJBc3NldAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAB2FCdXlGZWUJAQAAABFnZXRCdXlGZWVQZXJBc3NldAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAACGFTZWxsRmVlCQEAAAASZ2V0U2VsbEZlZVBlckFzc2V0AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAYYVJlZGVtcHRpb25UaW1lb3V0QmxvY2tzCQEAAAAaZ2V0UmVkZW1wdGlvblRpbWVvdXRCbG9ja3MAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAB53ZWVrZW5kc1ByaWNlQ2hhbmdlQ29lZmZpY2llbnQJAQAAACFnZXRXZWVrZW5kc1ByaWNlQ2hhbmdlQ29lZmZpY2llbnQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAAfY29tcG9zZUFzc2V0Q29uZmlndXJhdGlvblN0cmluZwAAABYFAAAABWFDb2RlBQAAAANhSUQFAAAACW5ld1N0YXR1cwUAAAAOYVByaWNlRGVjaW1hbHMFAAAADmFCYWtpbmdBc3NldElkBQAAABZhT3ZlckNvbGxhdGVyYWxQZXJjZW50BQAAABBhTWluUmVxdWlyZWRQb29sBQAAABNhUHJpY2VPcmFjbGVBZGRyZXNzBQAAAA5hTWluQnV5UGF5bWVudAUAAAAPYU1pblNlbGxQYXltZW50BQAAABBhQnV5TG9ja0ludGVydmFsBQAAABFhU2VsbExvY2tJbnRlcnZhbAUAAAAHYUJ1eUZlZQUAAAAIYVNlbGxGZWUFAAAAGGFSZWRlbXB0aW9uVGltZW91dEJsb2NrcwUAAAAed2Vla2VuZHNQcmljZUNoYW5nZUNvZWZmaWNpZW50CQABkQAAAAIFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QFAAAAGGtleUFzc2V0QWNjb3VudFB1YmxpY1N0cgkAAZEAAAACBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BQAAACBrZXlBc3NldFN0YWtpbmdSZWZlcnJhbFB1YmxpY1N0cgkAAZEAAAACBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BQAAABtrZXlDcm9zc0V4Y2hhbmdlQ29lZmZpY2llbnQJAAGRAAAAAgUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAUAAAAja2V5U3Rha2luZ01pbkFtdEZyb21TZWxsQ29lZmZpY2llbnQJAAGRAAAAAgUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAUAAAATa2V5UG9vbFN0YWJpbGl0eUZlZQkAAZEAAAACBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BQAAAA5rZXlQcm90b2NvbEZlZQEAAAAZY2FsY0FsbG93ZWRBbW91bnRUb1JlZGVlbQAAAAIAAAAJYXNzZXRDb2RlAAAAEHBvb2xNYWtlckFkZHJlc3MEAAAAD2Fzc2V0QWRkcmVzc1N0cgkBAAAAG2dldEFzc2V0QWRkcmVzc0J5Q29kZU9yRmFpbAAAAAEFAAAACWFzc2V0Q29kZQQAAAAMYXNzZXRBZGRyZXNzCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIEAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QJAQAAABNnZXRBc3NldENvbmZpZ0FycmF5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyBAAAAAphc3NldElkU3RyCQEAAAAKZ2V0QXNzZXRJRAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAB2Fzc2V0SWQJAAJZAAAAAQUAAAAKYXNzZXRJZFN0cgQAAAAOcG9vbEFjdHVhbFNpemUJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAHWdldEFzc2V0Q3VycnJlbnRQb29sQW1vdW50S2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyAAAAAAAAAAAABAAAAAtwb29sTWF4U2l6ZQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAYZ2V0QXNzZXRNYXhQb29sQW1vdW50S2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyAAAAAAAAAAAABAAAABhwb29sVG90YWxMb2NrZWRBbW91bnRLZXkJAQAAABtnZXRQb29sVG90YWxMb2NrZWRBbW91bnRLZXkAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIEAAAAD3Bvb2xUb3RhbExvY2tlZAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAABhwb29sVG90YWxMb2NrZWRBbW91bnRLZXkAAAAAAAAAAAAEAAAAFWFzc2V0VXNkblN0YWtlZEFtb3VudAkBAAAAFWdldE5ldXRyaW5vUnBkQmFsYW5jZQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgQAAAAWYXNzZXRVc2RuQmFsYW5jZUFtb3VudAkAA/AAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAAD25ldXRyaW5vQXNzZXRJZAQAAAASbGVuZGVkT3JEZWJ0QW1vdW50CQAAZQAAAAIFAAAAFmRlYnRUb2tlblJlaXNzdWVBbW91bnQJAAPwAAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAAlkZWJ0VG9rZW4EAAAAFGFzc2V0VG90YWxVc2RuQW1vdW50CQAAZAAAAAIJAABlAAAAAgkAAGQAAAACBQAAABVhc3NldFVzZG5TdGFrZWRBbW91bnQFAAAAFmFzc2V0VXNkbkJhbGFuY2VBbW91bnQFAAAAD3Bvb2xUb3RhbExvY2tlZAUAAAASbGVuZGVkT3JEZWJ0QW1vdW50BAAAAAt1Y29sbGF0ZXJhbAkAAGUAAAACBQAAABRhc3NldFRvdGFsVXNkbkFtb3VudAUAAAAOcG9vbEFjdHVhbFNpemUEAAAAEGRlZm9Bc3NldEJhbGFuY2UJAAPwAAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAAdhc3NldElkBAAAABJhc3NldEVtaXNzaW9uRGlydHkICQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAPsAAAAAQUAAAAHYXNzZXRJZAkAASwAAAACAgAAABhDYW5ub3QgZmluZCBhc3NldCBieSBpZCAFAAAACmFzc2V0SWRTdHIAAAAIcXVhbnRpdHkEAAAADWFzc2V0RW1pc3Npb24JAABlAAAAAgUAAAASYXNzZXRFbWlzc2lvbkRpcnR5BQAAABBkZWZvQXNzZXRCYWxhbmNlBAAAABJwcmljZU9yYWNsZUFkZHJlc3MJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABpnZXRBc3NldFByaWNlT3JhY2xlQWRkcmVzcwAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAADGN1cnJlbnRQcmljZQkBAAAADWdldEFzc2V0UHJpY2UAAAACBQAAABJwcmljZU9yYWNsZUFkZHJlc3MFAAAACWFzc2V0Q29kZQQAAAAfYXNzZXRFbWlzc2lvbk92ZXJjb2xsYXRlcmFsUmF0ZQkAAGsAAAADCQAAZAAAAAIFAAAADW11bHRpcGxpY2F0b3IJAQAAAB1nZXRBc3NldE92ZXJDb2xsYXRlcmFsUGVyY2VudAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QFAAAADWFzc2V0RW1pc3Npb24FAAAADW11bHRpcGxpY2F0b3IEAAAAGXVzZG5OZWVkZWRUb0NvdmVyRW1pc3Npb24JAABrAAAAAwUAAAAfYXNzZXRFbWlzc2lvbk92ZXJjb2xsYXRlcmFsUmF0ZQUAAAANbXVsdGlwbGljYXRvcgUAAAAMY3VycmVudFByaWNlBAAAABJwb29sTWFrZXJNYXhBbW91bnQJAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uTWF4QW1vdW50AAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABBwb29sTWFrZXJBZGRyZXNzBAAAAB9wb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50S2V5CQEAAAAiZ2V0UG9vbE1ha2VyUGFydGljaXBhdGlvbkFtb3VudEtleQAAAAIFAAAAD2Fzc2V0QWRkcmVzc1N0cgUAAAAQcG9vbE1ha2VyQWRkcmVzcwQAAAAVcG9vbE1ha2VyQWN0dWFsQW1vdW50CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAH3Bvb2xNYWtlclBhcnRpY2lwYXRpb25BbW91bnRLZXkAAAAAAAAAAAAEAAAAFXBvb2xNYWtlckxvY2tlZEFtb3VudAkBAAAAGGdldFBvb2xNYWtlckxvY2tlZEFtb3VudAAAAAIFAAAAD2Fzc2V0QWRkcmVzc1N0cgUAAAAQcG9vbE1ha2VyQWRkcmVzcwQAAAAHc3VycGx1cwkAAGUAAAACBQAAAAt1Y29sbGF0ZXJhbAUAAAAZdXNkbk5lZWRlZFRvQ292ZXJFbWlzc2lvbgQAAAAQcGVyY2VudFZpYUFjdHVhbAkAAGsAAAADBQAAABVwb29sTWFrZXJBY3R1YWxBbW91bnQFAAAADW11bHRpcGxpY2F0b3IFAAAADnBvb2xBY3R1YWxTaXplBAAAAA1wZXJjZW50VmlhTWF4CQAAawAAAAMFAAAAEnBvb2xNYWtlck1heEFtb3VudAUAAAANbXVsdGlwbGljYXRvcgUAAAALcG9vbE1heFNpemUEAAAACmZyb3plblBhcnQDCQAAZwAAAAIFAAAAB3N1cnBsdXMAAAAAAAAAAAAAAAAAAAAAAAAJAAGWAAAAAQkABEwAAAACBQAAABBwZXJjZW50VmlhQWN0dWFsCQAETAAAAAIFAAAADXBlcmNlbnRWaWFNYXgFAAAAA25pbAQAAAAVYWxsb3dlZEFtb3VudFRvUmVkZWVtAwkAAGcAAAACBQAAAAdzdXJwbHVzAAAAAAAAAAAABQAAABVwb29sTWFrZXJBY3R1YWxBbW91bnQJAABkAAAAAgkAAGsAAAADBQAAAApmcm96ZW5QYXJ0BQAAAAdzdXJwbHVzBQAAAA1tdWx0aXBsaWNhdG9yBQAAABVwb29sTWFrZXJBY3R1YWxBbW91bnQEAAAADndpdGhkcmF3SGVpZ2h0CQAAZAAAAAIFAAAABmhlaWdodAkBAAAAGmdldFJlZGVtcHRpb25UaW1lb3V0QmxvY2tzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAkABRoAAAAIBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAAFWFsbG93ZWRBbW91bnRUb1JlZGVlbQUAAAAPcG9vbFRvdGFsTG9ja2VkBQAAAA5wb29sQWN0dWFsU2l6ZQUAAAAVcG9vbE1ha2VyQWN0dWFsQW1vdW50BQAAAA53aXRoZHJhd0hlaWdodAUAAAAVcG9vbE1ha2VyTG9ja2VkQW1vdW50CQAEuQAAAAIJAARMAAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyCQAETAAAAAIFAAAACmFzc2V0SWRTdHIJAARMAAAAAgUAAAAQcG9vbE1ha2VyQWRkcmVzcwkABEwAAAACCQABpAAAAAEFAAAAFWFzc2V0VXNkblN0YWtlZEFtb3VudAkABEwAAAACCQABpAAAAAEFAAAAFmFzc2V0VXNkbkJhbGFuY2VBbW91bnQJAARMAAAAAgkAAaQAAAABBQAAABRhc3NldFRvdGFsVXNkbkFtb3VudAkABEwAAAACCQABpAAAAAEFAAAADnBvb2xBY3R1YWxTaXplCQAETAAAAAIJAAGkAAAAAQUAAAALcG9vbE1heFNpemUJAARMAAAAAgkAAaQAAAABBQAAAAt1Y29sbGF0ZXJhbAkABEwAAAACCQABpAAAAAEFAAAADWFzc2V0RW1pc3Npb24JAARMAAAAAgkAAaQAAAABBQAAAAxjdXJyZW50UHJpY2UJAARMAAAAAgkAAaQAAAABBQAAAB9hc3NldEVtaXNzaW9uT3ZlcmNvbGxhdGVyYWxSYXRlCQAETAAAAAIJAAGkAAAAAQUAAAAScG9vbE1ha2VyTWF4QW1vdW50CQAETAAAAAIJAAGkAAAAAQUAAAAVcG9vbE1ha2VyQWN0dWFsQW1vdW50CQAETAAAAAIJAAGkAAAAAQUAAAAVcG9vbE1ha2VyTG9ja2VkQW1vdW50CQAETAAAAAIJAAGkAAAAAQUAAAAHc3VycGx1cwkABEwAAAACCQABpAAAAAEFAAAAEHBlcmNlbnRWaWFBY3R1YWwJAARMAAAAAgkAAaQAAAABBQAAAA1wZXJjZW50VmlhTWF4CQAETAAAAAIJAAGkAAAAAQUAAAAKZnJvemVuUGFydAkABEwAAAACCQABpAAAAAEFAAAAFWFsbG93ZWRBbW91bnRUb1JlZGVlbQUAAAADbmlsBQAAAANTRVAAAAAHAAAAAWkBAAAABGluaXQAAAAGAAAAF25ldXRyaW5vQ29udHJhY3RBZGRyZXNzAAAAFm5ldXRyaW5vU3Rha2luZ0FkZHJlc3MAAAAYbWluaW11blBvb2xGdW5kaW5nQW1vdW50AAAAEmRlYnRFdGhhbG9uQmFsYW5jZQAAABJkZWZvU3Rha2luZ0FkZHJlc3MAAAAXZGVmb1N0YWtpbmdQYWNlbWFrZXJQdWIDCQEAAAACIT0AAAACCQACWAAAAAEIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAOYWRtaW5QdWJsaWNLZXkJAAACAAAAAQIAAAAqT25seSBBZG1pbiBjYW4gcGVyZm9ybSBjb250cmFjdCBvcGVyYXRpb24uAwkAAAAAAAACCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQUAAAAQaXNJbml0aWFsaXplZEtleQYJAAACAAAAAQIAAAAhQ29udHJhY3Qgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQuBAAAAAlpc3N1ZURlYnQJAARCAAAABQIAAAAJREVGT19ERUJUAgAAABBERUZPIERlYnQgVG9rZW4uAAAAAAAAAAABAAAAAAAAAAAGBgQAAAALZGVidFRva2VuSWQJAAQ4AAAAAQUAAAAJaXNzdWVEZWJ0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAGm5ldXRyaW5vQ29udHJhY3RBZGRyZXNzS2V5BQAAABduZXV0cmlub0NvbnRyYWN0QWRkcmVzcwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABluZXV0cmlub1N0YWtpbmdBZGRyZXNzS2V5BQAAABZuZXV0cmlub1N0YWtpbmdBZGRyZXNzCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABttaW5pbXVuUG9vbEZ1bmRpbmdBbW91bnRLZXkFAAAAGG1pbmltdW5Qb29sRnVuZGluZ0Ftb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAZZGVidFRva2VuRXRhbG9uQmFsYW5jZUtleQUAAAASZGVidEV0aGFsb25CYWxhbmNlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAADmRlYnRUb2tlbklkS2V5CQACWAAAAAEFAAAAC2RlYnRUb2tlbklkCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAFWRlZm9TdGFraW5nQWRkcmVzc0tleQUAAAASZGVmb1N0YWtpbmdBZGRyZXNzCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAGmRlZm9TdGFraW5nUGFjZW1ha2VyUHViS2V5BQAAABdkZWZvU3Rha2luZ1BhY2VtYWtlclB1YgkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAQaXNJbml0aWFsaXplZEtleQYJAARMAAAAAgUAAAAJaXNzdWVEZWJ0CQAETAAAAAIJAQAAAARCdXJuAAAAAgUAAAALZGVidFRva2VuSWQAAAAAAAAAAAEFAAAAA25pbAAAAAFpAQAAAAxwcm9wb3NlQXNzZXQAAAAEAAAACWFzc2V0Q29kZQAAAAdtaW5Qb29sAAAAEnByaWNlT3JhY2xlQWRkcmVzcwAAAA5taW5TZWxsUGF5bWVudAQAAAAOYmFja2luZ0Fzc2V0SWQFAAAAEm5ldXRyaW5vQXNzZXRJZFN0cgQAAAANcHJpY2VEZWNpbWFscwUAAAANbXVsdGlwbGljYXRvcgQAAAAPYnV5TG9ja0ludGVydmFsAAAAAAAAAAAABAAAABBzZWxsTG9ja0ludGVydmFsAAAAAAAAAAAABAAAAA1taW5CdXlQYXltZW50CQAAaAAAAAIAAAAAAAAAAAEFAAAADW11bHRpcGxpY2F0b3IEAAAAFXBvb2xSZWRlbXB0aW9uVGltZW91dAAAAAAAAAAAAAQAAAAGYnV5RmVlAAAAAAAAAAq+BAAAAAdzZWxsRmVlAAAAAAAAAAq+BAAAAB53ZWVrZW5kc1ByaWNlQ2hhbmdlQ29lZmZpY2llbnQAAAAAAAAAOpgEAAAAFW92ZXJDb2xsYXRlcmFsUGVyY2VudAAAAAAAAAAAAAQAAAAYY3Jvc3NFeGNoYW5nZUNvZWZmaWNpZW50AAAAAAAAB6EgBAAAACBzdGFraW5nTWluQW10RnJvbVNlbGxDb2VmZmljaWVudAkAAGgAAAACAAAAAAAAAAABBQAAAA1tdWx0aXBsaWNhdG9yBAAAABNtaW5Qb29sSW52ZXN0QW1vdW50CQAAaAAAAAIAAAAAAAAAAAoFAAAADW11bHRpcGxpY2F0b3IEAAAAE21pblBvb2xSZWRlZW1BbW91bnQJAABoAAAAAgAAAAAAAAAAAQUAAAANbXVsdGlwbGljYXRvcgQAAAAQcG9vbFN0YWJpbGl0eUZlZQAAAAAAAAAB9AQAAAALcHJvdG9jb2xGZWUAAAAAAAAACr4DCQEAAAACIT0AAAACCQACWAAAAAEIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAOYWRtaW5QdWJsaWNLZXkJAAACAAAAAQIAAAAqT25seSBBZG1pbiBjYW4gcGVyZm9ybSBjb250cmFjdCBvcGVyYXRpb24uAwkAAAAAAAACCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQUAAAAQaXNJbml0aWFsaXplZEtleQcJAAACAAAAAQIAAAAaQ29udHJhY3QgaXMgbm90IHlldCByZWFkeS4DCQEAAAACIT0AAAACCQACWQAAAAEFAAAADmJhY2tpbmdBc3NldElkBQAAAA9uZXV0cmlub0Fzc2V0SWQJAAACAAAAAQIAAAAjQmFraW5nIGFzc2V0IGlkIGNvdWxkIGJlIFVTRE4gb25seS4DCQEAAAACIT0AAAACCQEAAAAVZ2V0QXNzZXRBZGRyZXNzQnlDb2RlAAAAAQUAAAAJYXNzZXRDb2RlAgAAAAAJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAF0Fzc2V0IHdpdGggcGFzc2VkIGNvZGUgBQAAAAlhc3NldENvZGUCAAAAGyBoYXMgYWxyZWFkeSBiZWVuIHByb3Bvc2VkLgMJAABmAAAAAgUAAAASbWluaW11bVBvb2xGdW5kaW5nBQAAAAdtaW5Qb29sCQAAAgAAAAEJAAEsAAAAAgIAAAAzTWluaW11bSBwb29sIGFtb3VudCBzaG91bGQgYmUgZ3JlYXRlciBvciBlcXVhbHMgdG8gCQABpAAAAAEFAAAAEm1pbmltdW1Qb29sRnVuZGluZwMDAwMDAwMJAABmAAAAAgAAAAAAAAAAAAUAAAAVb3ZlckNvbGxhdGVyYWxQZXJjZW50BgkAAGYAAAACAAAAAAAAAAAABQAAAA1taW5CdXlQYXltZW50BgkAAGYAAAACAAAAAAAAAAAABQAAAA5taW5TZWxsUGF5bWVudAYJAABmAAAAAgAAAAAAAAAAAAUAAAAPYnV5TG9ja0ludGVydmFsBgkAAGYAAAACAAAAAAAAAAAABQAAABBzZWxsTG9ja0ludGVydmFsBgkAAGYAAAACAAAAAAAAAAAABQAAAAZidXlGZWUGCQAAZgAAAAIAAAAAAAAAAAAFAAAAB3NlbGxGZWUJAAACAAAAAQIAAAAoT25lIG9mIHRoZSBwYXNzZWQgcGFyYW1ldGVycyBpcyBpbnZhbGlkLgQAAAAXcHJpY2VPcmFjbGVBZGRyZXNzVmFsaWQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAScHJpY2VPcmFjbGVBZGRyZXNzAgAAAClQYXNzZWQgUHJpY2UgT3JhY2xlIEFkZHJlc3MgaXMgbm90IHZhbGlkLgQAAAAOcHJlSW5pdERhdGFTdHIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzCQEAAAAdZ2V0UHJlSW5pdGlhbGl6ZWRBc3NldERhdGFLZXkAAAABBQAAAAlhc3NldENvZGUJAAEsAAAAAgIAAAA7VW5zdXBwb3J0ZWQgY3VycmVuY3kgLSB0aGVyZSBpcyBubyBwcmVpbml0aWFsaXplZCBkYXRhIGZvciAFAAAACWFzc2V0Q29kZQQAAAAQcHJlSW5pdERhdGFBcnJheQkABLUAAAACBQAAAA5wcmVJbml0RGF0YVN0cgUAAAADU0VQBAAAABVwcmVJbml0QXNzZXRQdWJsaWNTdHIJAAGRAAAAAgUAAAAQcHJlSW5pdERhdGFBcnJheQUAAAAcSWR4UHJlSW5pdGlhbGl6ZWRBc3NldFB1YmxpYwQAAAAfcHJlSW5pdFN0YWtpbmdSZWZlcnJhbFB1YmxpY1N0cgkAAZEAAAACBQAAABBwcmVJbml0RGF0YUFycmF5BQAAACtJZHhQcmVJbml0aWFsaXplZEFzc2V0U3Rha2luZ1JlZmVycmFsUHVibGljBAAAABJwcmVJbml0RGVzY3JpcHRpb24JAAGRAAAAAgUAAAAQcHJlSW5pdERhdGFBcnJheQUAAAAhSWR4UHJlSW5pdGlhbGl6ZWRBc3NldERlc2NyaXB0aW9uBAAAAAxhc3NldEFkZHJlc3MJAQAAABRhZGRyZXNzRnJvbVB1YmxpY0tleQAAAAEJAAJZAAAAAQUAAAAVcHJlSW5pdEFzc2V0UHVibGljU3RyBAAAAA9hc3NldEFkZHJlc3NTdHIJAAQlAAAAAQUAAAAMYXNzZXRBZGRyZXNzBAAAAAtkZWZvQXNzZXRJZAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAAOZGVmb0Fzc2V0SWRLZXkCAAAAF05vIGRlZm8gYXNzZXQgSUQgZm91bmQuCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABFnZXRBc3NldENvbmZpZ0tleQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgkBAAAAH2NvbXBvc2VBc3NldENvbmZpZ3VyYXRpb25TdHJpbmcAAAAWBQAAAAlhc3NldENvZGUFAAAAC2RlZm9Bc3NldElkCAUAAAALYXNzZXRTdGF0dXMAAAACXzEFAAAADXByaWNlRGVjaW1hbHMFAAAADmJhY2tpbmdBc3NldElkBQAAABVvdmVyQ29sbGF0ZXJhbFBlcmNlbnQFAAAAB21pblBvb2wFAAAAEnByaWNlT3JhY2xlQWRkcmVzcwUAAAANbWluQnV5UGF5bWVudAUAAAAObWluU2VsbFBheW1lbnQFAAAAD2J1eUxvY2tJbnRlcnZhbAUAAAAQc2VsbExvY2tJbnRlcnZhbAUAAAAGYnV5RmVlBQAAAAdzZWxsRmVlBQAAABVwb29sUmVkZW1wdGlvblRpbWVvdXQFAAAAHndlZWtlbmRzUHJpY2VDaGFuZ2VDb2VmZmljaWVudAUAAAAVcHJlSW5pdEFzc2V0UHVibGljU3RyBQAAAB9wcmVJbml0U3Rha2luZ1JlZmVycmFsUHVibGljU3RyCQABpAAAAAEFAAAAGGNyb3NzRXhjaGFuZ2VDb2VmZmljaWVudAkAAaQAAAABBQAAACBzdGFraW5nTWluQW10RnJvbVNlbGxDb2VmZmljaWVudAkAAaQAAAABBQAAABBwb29sU3RhYmlsaXR5RmVlCQABpAAAAAEFAAAAC3Byb3RvY29sRmVlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABhnZXRBc3NldEFkZHJlc3NCeUNvZGVLZXkAAAABBQAAAAlhc3NldENvZGUFAAAAD2Fzc2V0QWRkcmVzc1N0cgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPZ2V0QXNzZXRNZXRhS2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABJwcmVJbml0RGVzY3JpcHRpb24JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABVnZXRBc3NldEluaXRIZWlnaHRLZXkAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAABmhlaWdodAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAbZ2V0QXNzZXRBZGRyZXNzQnlBc3NldElkS2V5AAAAAQUAAAALZGVmb0Fzc2V0SWQFAAAAD2Fzc2V0QWRkcmVzc1N0cgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAGWdldFBvb2xNaW5JbnZlc3RBbW91bnRLZXkAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAAE21pblBvb2xJbnZlc3RBbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABlnZXRQb29sTWluUmVkZWVtQW1vdW50S2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABNtaW5Qb29sUmVkZWVtQW1vdW50BQAAAANuaWwAAAABaQEAAAARZnVuZExpcXVpZGl0eVBvb2wAAAABAAAACWFzc2V0Q29kZQQAAAAPYXNzZXRBZGRyZXNzU3RyCQEAAAAbZ2V0QXNzZXRBZGRyZXNzQnlDb2RlT3JGYWlsAAAAAQUAAAAJYXNzZXRDb2RlBAAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgQAAAAPYXR0YWNoZWRQYXltZW50CQEAAAAFdmFsdWUAAAABCQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAABAAAABBwb29sTWFrZXJBZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAXY3VycmVudFBvb2xNYWtlckJhbGFuY2UJAQAAAB9nZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50AAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABBwb29sTWFrZXJBZGRyZXNzBAAAABNtaW5Qb29sSW52ZXN0QW1vdW50CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABlnZXRQb29sTWluSW52ZXN0QW1vdW50S2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyCQAAaAAAAAIAAAAAAAAAAAoFAAAADW11bHRpcGxpY2F0b3IDCQAAAAAAAAIJAQAAAAxnZXRCb29sQnlLZXkAAAABBQAAABBpc0luaXRpYWxpemVkS2V5BwkAAAIAAAABAgAAABpDb250cmFjdCBpcyBub3QgeWV0IHJlYWR5LgMJAQAAAAIhPQAAAAIIBQAAAA9hdHRhY2hlZFBheW1lbnQAAAAHYXNzZXRJZAUAAAAPbmV1dHJpbm9Bc3NldElkCQAAAgAAAAECAAAALkxpcXVpZGl0eSBwb29sIGNvdWxkIGJlIGZ1bmRlZCB3aXRoIFVTRE4gb25seS4DAwkAAGYAAAACBQAAABNtaW5Qb29sSW52ZXN0QW1vdW50BQAAABdjdXJyZW50UG9vbE1ha2VyQmFsYW5jZQkAAGYAAAACBQAAABNtaW5Qb29sSW52ZXN0QW1vdW50CAUAAAAPYXR0YWNoZWRQYXltZW50AAAABmFtb3VudAcJAAACAAAAAQkAASwAAAACAgAAADFBdHRhY2hlZCBwYXltZW50IGFtb3VudCBpcyBsZXNzIHRoYSBtaW4gYWxsb3dlZDogCQABpAAAAAEFAAAAE21pblBvb2xJbnZlc3RBbW91bnQEAAAAFG5ld0N1cnJlbnRQb29sQW1vdW50CQAAZAAAAAIIBQAAAA9hdHRhY2hlZFBheW1lbnQAAAAGYW1vdW50CQEAAAAZZ2V0QXNzZXRDdXJyZW50UG9vbEFtb3VudAAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgQAAAANbWF4UG9vbEFtb3VudAkBAAAAFWdldEFzc2V0TWF4UG9vbEFtb3VudAAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgQAAAATbWF4UG9vbE1ha2VyQmFsYW5jZQkBAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25NYXhBbW91bnQAAAACBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAAEHBvb2xNYWtlckFkZHJlc3MEAAAAEmN1cnJlbnRBc3NldFN0YXR1cwkBAAAADmdldEFzc2V0U3RhdHVzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAObmV3QXNzZXRTdGF0dXMDAwkAAAAAAAACBQAAABJjdXJyZW50QXNzZXRTdGF0dXMFAAAADUFTU0V0UFJPUE9TRUQJAABnAAAAAgUAAAAUbmV3Q3VycmVudFBvb2xBbW91bnQJAQAAAB1nZXRBc3NldE1pblJlcXVpcmVkUG9vbEFtb3VudAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QHBQAAAApBU1NFdFJFQURZBQAAABJjdXJyZW50QXNzZXRTdGF0dXMEAAAAE25ld1Bvb2xNYWtlckJhbGFuY2UJAABkAAAAAgUAAAAXY3VycmVudFBvb2xNYWtlckJhbGFuY2UIBQAAAA9hdHRhY2hlZFBheW1lbnQAAAAGYW1vdW50BAAAABlpbW1lZGlhdGVUcmFuc2ZlcklmSXNzdWVkAwkAAAAAAAACBQAAABJjdXJyZW50QXNzZXRTdGF0dXMFAAAAC0FTU0V0SVNTVUVECQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cggFAAAAD2F0dGFjaGVkUGF5bWVudAAAAAZhbW91bnQFAAAAD25ldXRyaW5vQXNzZXRJZAUAAAADbmlsBQAAAANuaWwJAAROAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25BbW91bnRLZXkAAAACBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAAEHBvb2xNYWtlckFkZHJlc3MFAAAAE25ld1Bvb2xNYWtlckJhbGFuY2UJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAACVnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uTWF4QW1vdW50S2V5AAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABBwb29sTWFrZXJBZGRyZXNzCQABlgAAAAEJAARMAAAAAgUAAAATbmV3UG9vbE1ha2VyQmFsYW5jZQkABEwAAAACBQAAABNtYXhQb29sTWFrZXJCYWxhbmNlBQAAAANuaWwJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAB1nZXRBc3NldEN1cnJyZW50UG9vbEFtb3VudEtleQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgUAAAAUbmV3Q3VycmVudFBvb2xBbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABhnZXRBc3NldE1heFBvb2xBbW91bnRLZXkAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIJAAGWAAAAAQkABEwAAAACBQAAAA1tYXhQb29sQW1vdW50CQAETAAAAAIFAAAAFG5ld0N1cnJlbnRQb29sQW1vdW50BQAAAANuaWwJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEWdldEFzc2V0Q29uZmlnS2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyCQEAAAAUdXBkYXRlQXNzZXRDZmdTdGF0dXMAAAACBQAAAA5uZXdBc3NldFN0YXR1cwUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAUAAAADbmlsBQAAABlpbW1lZGlhdGVUcmFuc2ZlcklmSXNzdWVkAAAAAWkBAAAADWFjdGl2YXRlQXNzZXQAAAABAAAACWFzc2V0Q29kZQQAAAAMYXNzZXRBZGRyZXNzCQEAAAAVZ2V0QXNzZXRBZGRyZXNzQnlDb2RlAAAAAQUAAAAJYXNzZXRDb2RlBAAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEFAAAADGFzc2V0QWRkcmVzcwQAAAAWYXNzZXRDdXJyZW50UG9vbEFtb3VudAkBAAAAGWdldEFzc2V0Q3VycmVudFBvb2xBbW91bnQAAAABBQAAAAxhc3NldEFkZHJlc3MEAAAADmFDdXJyZW50U3RhdHVzCQEAAAAOZ2V0QXNzZXRTdGF0dXMAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0AwkBAAAAAiE9AAAAAgkAAlgAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmFkbWluUHVibGljS2V5CQAAAgAAAAECAAAAKk9ubHkgQWRtaW4gY2FuIHBlcmZvcm0gY29udHJhY3Qgb3BlcmF0aW9uLgMJAAAAAAAAAgkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAAEGlzSW5pdGlhbGl6ZWRLZXkHCQAAAgAAAAECAAAAGkNvbnRyYWN0IGlzIG5vdCB5ZXQgcmVhZHkuAwkBAAAAAiE9AAAAAgUAAAAOYUN1cnJlbnRTdGF0dXMIBQAAAAthc3NldFN0YXR1cwAAAAJfMgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAwQXNzZXQgaXMgbm90IGluIFJFQURZIHN0YXR1cy4gQ3VycmVudCBzdGF0dXMgaXMgBQAAAA5hQ3VycmVudFN0YXR1cwIAAAABLgMJAAAAAAAAAgUAAAAMYXNzZXRBZGRyZXNzAgAAAAAJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAEkNhbm5vdCBmaW5kIGFzc2V0IAUAAAAJYXNzZXRDb2RlAgAAAAEuAwkAAGYAAAACBQAAABJtaW5pbXVtUG9vbEZ1bmRpbmcFAAAAFmFzc2V0Q3VycmVudFBvb2xBbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAC1DYW5ub3QgaXNzdWUgYXNzZXQgYXMgbGlxdWlkaXR5IHBvb2wgYW1vdW50ICgJAAGkAAAAAQUAAAAWYXNzZXRDdXJyZW50UG9vbEFtb3VudAIAAAAZKSBpcyBsZXNzIHRoYW4gcmVxdWlyZWQgKAkAAaQAAAABBQAAABJtaW5pbXVtUG9vbEZ1bmRpbmcCAAAAASkEAAAACWlzc3VlRGVidAkBAAAAB1JlaXNzdWUAAAADBQAAAAlkZWJ0VG9rZW4FAAAAFmRlYnRUb2tlblJlaXNzdWVBbW91bnQGCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAZZ2V0QXNzZXRBY3RpdmF0ZUhlaWdodEtleQAAAAEFAAAADGFzc2V0QWRkcmVzcwUAAAAGaGVpZ2h0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABFnZXRBc3NldENvbmZpZ0tleQAAAAEFAAAADGFzc2V0QWRkcmVzcwkBAAAAFHVwZGF0ZUFzc2V0Q2ZnU3RhdHVzAAAAAggFAAAAC2Fzc2V0U3RhdHVzAAAAAl8zBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQAETAAAAAIFAAAACWlzc3VlRGVidAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAAxhc3NldEFkZHJlc3MFAAAAFmFzc2V0Q3VycmVudFBvb2xBbW91bnQFAAAAD25ldXRyaW5vQXNzZXRJZAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAAxhc3NldEFkZHJlc3MFAAAAFmRlYnRUb2tlblJlaXNzdWVBbW91bnQFAAAACWRlYnRUb2tlbgUAAAADbmlsAAAAAWkBAAAADnJlZGVlbUZyb21Qb29sAAAAAgAAAAlhc3NldENvZGUAAAAGYW1vdW50BAAAAA1jYWxsZXJBZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAALcmVkZWVtVHVwbGUJAQAAABljYWxjQWxsb3dlZEFtb3VudFRvUmVkZWVtAAAAAgUAAAAJYXNzZXRDb2RlBQAAAA1jYWxsZXJBZGRyZXNzBAAAAA9hc3NldEFkZHJlc3NTdHIIBQAAAAtyZWRlZW1UdXBsZQAAAAJfMQQAAAAVYWxsb3dlZEFtb3VudFRvUmVkZWVtCAUAAAALcmVkZWVtVHVwbGUAAAACXzIEAAAAD3Bvb2xUb3RhbExvY2tlZAgFAAAAC3JlZGVlbVR1cGxlAAAAAl8zBAAAAA5wb29sQWN0dWFsU2l6ZQgFAAAAC3JlZGVlbVR1cGxlAAAAAl80BAAAABVwb29sTWFrZXJBY3R1YWxBbW91bnQIBQAAAAtyZWRlZW1UdXBsZQAAAAJfNQQAAAAOd2l0aGRyYXdIZWlnaHQIBQAAAAtyZWRlZW1UdXBsZQAAAAJfNgQAAAAVcG9vbE1ha2VyTG9ja2VkQW1vdW50CAUAAAALcmVkZWVtVHVwbGUAAAACXzcEAAAACXRyYWNlRGF0YQgFAAAAC3JlZGVlbVR1cGxlAAAAAl84BAAAABxwb29sTWFrZXJMaXF1aWRpdHlSZXF1ZXN0S2V5CQEAAAAfZ2V0UG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdEtleQAAAAMFAAAAD2Fzc2V0QWRkcmVzc1N0cgUAAAANY2FsbGVyQWRkcmVzcwUAAAAOd2l0aGRyYXdIZWlnaHQEAAAAE21pblBvb2xSZWRlZW1BbW91bnQJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAGWdldFBvb2xNaW5SZWRlZW1BbW91bnRLZXkAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIJAABoAAAAAgAAAAAAAAAAAQUAAAANbXVsdGlwbGljYXRvcgMJAAAAAAAAAgkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAAEGlzSW5pdGlhbGl6ZWRLZXkHCQAAAgAAAAECAAAAGkNvbnRyYWN0IGlzIG5vdCB5ZXQgcmVhZHkuAwkAAGcAAAACAAAAAAAAAAAABQAAAAZhbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAIkNhbm5vdCBmaW5kIHBvb2wgbWFrZXIgYnkgYWRkcmVzcyAFAAAADWNhbGxlckFkZHJlc3MCAAAAISBvciBhbW91bnQgcGFzc2VkIGlzIG5vdCBjb3JyZWN0LgMJAABnAAAAAgAAAAAAAAAAAAUAAAAVcG9vbE1ha2VyQWN0dWFsQW1vdW50CQAAAgAAAAECAAAAF1Bvb2wgbWFrZXIgaGFzIG5vIGZ1bmRzAwkAAGcAAAACAAAAAAAAAAAABQAAABVhbGxvd2VkQW1vdW50VG9SZWRlZW0JAAACAAAAAQIAAAAfQWxsIHBvb2wgbWFrZXIgZnVuZHMgYXJlIGxvY2tlZAMJAABmAAAAAgUAAAAGYW1vdW50BQAAABVhbGxvd2VkQW1vdW50VG9SZWRlZW0JAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAABHQWxsb3dlZCBhbW91bnQgdG8gcmVkZWVtIGlzIGxlc3MgdGhlbiByZXF1ZXN0ZWQ6IGFsbG93ZWRBbW91bnRUb1JlZGVlbT0JAAGkAAAAAQUAAAAVYWxsb3dlZEFtb3VudFRvUmVkZWVtAgAAAAsgcmVxdWVzdGVkPQkAAaQAAAABBQAAAAZhbW91bnQDCQAAZgAAAAIFAAAAE21pblBvb2xSZWRlZW1BbW91bnQFAAAABmFtb3VudAkAAAIAAAABAgAAACZSZWRlZW0gYW1vdW50IGlzIGxlc3MgdGhlbiBtaW4gYWxsb3dlZAMJAABmAAAAAgUAAAAVcG9vbE1ha2VyTG9ja2VkQW1vdW50AAAAAAAAAAAACQAAAgAAAAECAAAARlBvb2wgbWFrZXIgYWxyZWFkeSBoYXMgaW5pdGlhdGVkIHJlZGVtcHRpb24gdGhhdCBpcyBub3Qgd2l0aGRyYXduIHlldC4DCQEAAAAJaXNEZWZpbmVkAAAAAQkABBoAAAACBQAAAAR0aGlzBQAAABxwb29sTWFrZXJMaXF1aWRpdHlSZXF1ZXN0S2V5CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAADBQb29sIG1ha2VyIGhhcyBhbHJlYWR5IGluaXRpYXRlZCByZWRlbXB0aW9uIGZvciAJAAGkAAAAAQUAAAAGaGVpZ2h0AgAAAAcgaGVpZ2h0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAbZ2V0UG9vbFRvdGFsTG9ja2VkQW1vdW50S2V5AAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyCQAAZAAAAAIFAAAAD3Bvb2xUb3RhbExvY2tlZAUAAAAGYW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAdZ2V0QXNzZXRDdXJycmVudFBvb2xBbW91bnRLZXkAAAABBQAAAA9hc3NldEFkZHJlc3NTdHIJAABlAAAAAgUAAAAOcG9vbEFjdHVhbFNpemUFAAAABmFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25BbW91bnRLZXkAAAACBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAADWNhbGxlckFkZHJlc3MJAABlAAAAAgUAAAAVcG9vbE1ha2VyQWN0dWFsQW1vdW50BQAAAAZhbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAHHBvb2xNYWtlckxpcXVpZGl0eVJlcXVlc3RLZXkFAAAABmFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAG2dldFBvb2xNYWtlckxvY2tlZEFtb3VudEtleQAAAAIFAAAAD2Fzc2V0QWRkcmVzc1N0cgUAAAANY2FsbGVyQWRkcmVzcwUAAAAGYW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAbZ2V0UG9vbE1ha2VyVW5sb2NrSGVpZ2h0S2V5AAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAAA1jYWxsZXJBZGRyZXNzBQAAAA53aXRoZHJhd0hlaWdodAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAABklcyVzX3RyYWNlX3JlZGVlbUZyb21Qb29sBQAAAAl0cmFjZURhdGEFAAAAA25pbAAAAAFpAQAAABtnZXRNYXhBbGxvd2VkQW1vdW50VG9SZWRlZW0AAAACAAAACWFzc2V0Q29kZQAAABBwb29sTWFrZXJBZGRyZXNzBAAAAAtyZWRlZW1UdXBsZQkBAAAAGWNhbGNBbGxvd2VkQW1vdW50VG9SZWRlZW0AAAACBQAAAAlhc3NldENvZGUFAAAAEHBvb2xNYWtlckFkZHJlc3MEAAAAD2Fzc2V0QWRkcmVzc1N0cggFAAAAC3JlZGVlbVR1cGxlAAAAAl8xBAAAABVhbGxvd2VkQW1vdW50VG9SZWRlZW0IBQAAAAtyZWRlZW1UdXBsZQAAAAJfMgQAAAAPcG9vbFRvdGFsTG9ja2VkCAUAAAALcmVkZWVtVHVwbGUAAAACXzMEAAAADnBvb2xBY3R1YWxTaXplCAUAAAALcmVkZWVtVHVwbGUAAAACXzQEAAAAFXBvb2xNYWtlckFjdHVhbEFtb3VudAgFAAAAC3JlZGVlbVR1cGxlAAAAAl81BAAAAA53aXRoZHJhd0hlaWdodAgFAAAAC3JlZGVlbVR1cGxlAAAAAl82BAAAABVwb29sTWFrZXJMb2NrZWRBbW91bnQIBQAAAAtyZWRlZW1UdXBsZQAAAAJfNwQAAAAJdHJhY2VEYXRhCAUAAAALcmVkZWVtVHVwbGUAAAACXzgJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAABewIAAAAXYWxsb3dlZEFtb3VudFRvUmVkZWVtOiAJAAGkAAAAAQUAAAAVYWxsb3dlZEFtb3VudFRvUmVkZWVtAgAAAA0sIGFzc2V0Q29kZTogBQAAAAlhc3NldENvZGUCAAAADSwgcG9vbE1ha2VyOiAFAAAAEHBvb2xNYWtlckFkZHJlc3MCAAAACSwgdHJhY2U6IAUAAAAJdHJhY2VEYXRhAgAAAAF9AAAAAWkBAAAACHdpdGhkcmF3AAAAAgAAAAlhc3NldENvZGUAAAAQcG9vbE1ha2VyQWRkcmVzcwQAAAAPYXNzZXRBZGRyZXNzU3RyCQEAAAAbZ2V0QXNzZXRBZGRyZXNzQnlDb2RlT3JGYWlsAAAAAQUAAAAJYXNzZXRDb2RlBAAAAAxhc3NldEFkZHJlc3MJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgQAAAAYcG9vbE1ha2VyTG9ja2VkQW1vdW50S2V5CQEAAAAbZ2V0UG9vbE1ha2VyTG9ja2VkQW1vdW50S2V5AAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABBwb29sTWFrZXJBZGRyZXNzBAAAABlyZWdpc3RlcmVkQW1vdW50NFdpdGhkcmF3CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAGHBvb2xNYWtlckxvY2tlZEFtb3VudEtleQAAAAAAAAAAAAQAAAAYcG9vbE1ha2VyVW5sb2NrSGVpZ2h0S2V5CQEAAAAbZ2V0UG9vbE1ha2VyVW5sb2NrSGVpZ2h0S2V5AAAAAgUAAAAPYXNzZXRBZGRyZXNzU3RyBQAAABBwb29sTWFrZXJBZGRyZXNzBAAAAA53aXRoZHJhd0hlaWdodAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAABhwb29sTWFrZXJVbmxvY2tIZWlnaHRLZXkAAAAAAAAAAAAEAAAAGHBvb2xUb3RhbExvY2tlZEFtb3VudEtleQkBAAAAG2dldFBvb2xUb3RhbExvY2tlZEFtb3VudEtleQAAAAEFAAAAD2Fzc2V0QWRkcmVzc1N0cgQAAAAPcG9vbFRvdGFsTG9ja2VkCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAGHBvb2xUb3RhbExvY2tlZEFtb3VudEtleQAAAAAAAAAAAAQAAAAccG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdEtleQkBAAAAH2dldFBvb2xNYWtlckxpcXVpZGl0eVJlcXVlc3RLZXkAAAADBQAAAA9hc3NldEFkZHJlc3NTdHIFAAAAEHBvb2xNYWtlckFkZHJlc3MFAAAADndpdGhkcmF3SGVpZ2h0AwkAAAAAAAACCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQUAAAAQaXNJbml0aWFsaXplZEtleQcJAAACAAAAAQIAAAAaQ29udHJhY3QgaXMgbm90IHlldCByZWFkeS4DCQEAAAABIQAAAAEJAQAAAAlpc0RlZmluZWQAAAABCQAEGgAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAAccG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdEtleQkAAAIAAAABAgAAADNOZWVkIHRvIHRyYW5zZmVyIGxpcXVpZGl0eSBmcm9tIGFzc2V0IGFjY291bnQgZmlyc3QDCQAAZwAAAAIAAAAAAAAAAAAFAAAAGXJlZ2lzdGVyZWRBbW91bnQ0V2l0aGRyYXcJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAIkNhbm5vdCBmaW5kIHBvb2wgbWFrZXIgYnkgYWRkcmVzcyAFAAAAEHBvb2xNYWtlckFkZHJlc3MCAAAAFSBvciBubyBsb2NrZWQgYW1vdW50LgMJAABmAAAAAgUAAAAOd2l0aGRyYXdIZWlnaHQFAAAABmhlaWdodAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAMUGxlYXNlIHdhaXQgCQABpAAAAAEFAAAADndpdGhkcmF3SGVpZ2h0AgAAABEgYmVmb3JlIHdpdGhkcmF3LgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAYcG9vbE1ha2VyTG9ja2VkQW1vdW50S2V5AAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABhwb29sVG90YWxMb2NrZWRBbW91bnRLZXkJAABlAAAAAgUAAAAPcG9vbFRvdGFsTG9ja2VkBQAAABlyZWdpc3RlcmVkQW1vdW50NFdpdGhkcmF3CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABhwb29sTWFrZXJVbmxvY2tIZWlnaHRLZXkAAAAAAAAAAAAJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAQcG9vbE1ha2VyQWRkcmVzcwUAAAAZcmVnaXN0ZXJlZEFtb3VudDRXaXRoZHJhdwUAAAAPbmV1dHJpbm9Bc3NldElkBQAAAANuaWwAAAAA9rEDFw==", "height": 1603335, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 9ifMCGeongvtm8RhREVkMNCguT333zct6nGL8BTdvqdt Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 4 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | func getBoolByKey (key) = valueOrElse(getBoolean(this, key), false) | |
5 | + | ||
6 | + | ||
7 | + | let SEP = "__" | |
8 | + | ||
9 | + | let keyAssetCode = 1 | |
10 | + | ||
11 | + | let keyAssetId = 2 | |
12 | + | ||
13 | + | let keyAssetStatus = 3 | |
14 | + | ||
15 | + | let keyAssetPriceDecimals = 4 | |
16 | + | ||
17 | + | let keyAssetBakingAsset = 5 | |
18 | + | ||
19 | + | let keyOvercollateralPercentage = 6 | |
20 | + | ||
21 | + | let keyMinPool = 7 | |
22 | + | ||
23 | + | let keyPriceOracleAddress = 8 | |
24 | + | ||
25 | + | let keyMinBuyPayment = 9 | |
26 | + | ||
27 | + | let keyMinSellPayment = 10 | |
28 | + | ||
29 | + | let keyBuyLockInterval = 11 | |
30 | + | ||
31 | + | let keySellLockInterval = 12 | |
32 | + | ||
33 | + | let keyBuyFee = 13 | |
34 | + | ||
35 | + | let keySellFee = 14 | |
36 | + | ||
37 | + | let keyPoolRedemptionTimeout = 15 | |
38 | + | ||
39 | + | let keyWeekendsPriceChangeCoefficient = 16 | |
40 | + | ||
41 | + | let keyAssetAccountPublicStr = 17 | |
42 | + | ||
43 | + | let keyAssetStakingReferralPublicStr = 18 | |
44 | + | ||
45 | + | let keyCrossExchangeCoefficient = 19 | |
46 | + | ||
47 | + | let keyStakingMinAmtFromSellCoefficient = 20 | |
48 | + | ||
49 | + | let keyPoolStabilityFee = 21 | |
50 | + | ||
51 | + | let keyProtocolFee = 22 | |
52 | + | ||
53 | + | let adminPublicKey = "3YSMs2xX38575kQqyWtHEcydU3zfDXqcbiuELRhDhvB8" | |
54 | + | ||
55 | + | let neutrinoContractAddressKey = "%s%s__commonConfig__neutrinoContractAddress" | |
56 | + | ||
57 | + | let neutrinoStakingAddressKey = "%s%s__commonConfig__neutrinoStakingAddress" | |
58 | + | ||
59 | + | let minimunPoolFundingAmountKey = "%s%s__commonConfig__minimumPoolFundingAmount" | |
60 | + | ||
61 | + | let isInitializedKey = "%s%s__commonConfig__initialized" | |
62 | + | ||
63 | + | let debtTokenIdKey = "%s%s__commonConfig__debtAssetId" | |
64 | + | ||
65 | + | let debtTokenEtalonBalanceKey = "%s%s__commonConfig__debtAssetEtalonBalance" | |
66 | + | ||
67 | + | let defoStakingAddressKey = "%s%s__commonConfig__defoStakingAddress" | |
68 | + | ||
69 | + | let defoStakingPacemakerPubKey = "%s%s__commonConfig__defoStakingPacemakerPub" | |
70 | + | ||
71 | + | let neutrinoAssetIdKey = "neutrino_asset_id" | |
72 | + | ||
73 | + | let nsbtAssetIdKey = "bond_asset_id" | |
74 | + | ||
75 | + | let neutrinoRpdKey = "rpd_contract" | |
76 | + | ||
77 | + | let defoAssetIdKey = "%s__defoAssetId" | |
78 | + | ||
79 | + | let setAssetScriptTxIdKey = "%s__assetScriptTxId" | |
80 | + | ||
81 | + | func getAssetConfigKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__config") | |
82 | + | ||
83 | + | ||
84 | + | let IdxPreInitializedAssetPublic = 0 | |
85 | + | ||
86 | + | let IdxPreInitializedAssetStakingReferralPublic = 1 | |
87 | + | ||
88 | + | let IdxPreInitializedAssetDescription = 2 | |
89 | + | ||
90 | + | func getPreInitializedAssetDataKey (assetCode) = ("%s%s__preInitializedAssetData__" + assetCode) | |
91 | + | ||
92 | + | ||
93 | + | func getAssetPriceKey (assetCode) = ("%s%s__price__" + assetCode) | |
94 | + | ||
95 | + | ||
96 | + | func getAssetInitHeightKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__initHeight") | |
97 | + | ||
98 | + | ||
99 | + | func getAssetActivateHeightKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__activateHeight") | |
100 | + | ||
101 | + | ||
102 | + | func getAssetCurrrentPoolAmountKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__currentPool") | |
103 | + | ||
104 | + | ||
105 | + | func getAssetMaxPoolAmountKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__maxPool") | |
106 | + | ||
107 | + | ||
108 | + | func getAssetMetaKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__meta") | |
109 | + | ||
110 | + | ||
111 | + | func getAssetAddressByCodeKey (assetCode) = (("%s%s%s__defoAsset__" + assetCode) + "__addressByAssetCode") | |
112 | + | ||
113 | + | ||
114 | + | func getAssetAddressByAssetIdKey (assetId) = (("%s%s%s__defoAsset__" + assetId) + "__addressByAssetId") | |
115 | + | ||
116 | + | ||
117 | + | func getPoolMakerParticipationAmountKey (assetAddress,poolMakerAddress) = makeString(["%s%s%s%s__pool", assetAddress, poolMakerAddress, "amount"], SEP) | |
118 | + | ||
119 | + | ||
120 | + | func getPoolMakerParticipationMaxAmountKey (assetAddress,poolMakerAddress) = makeString(["%s%s%s%s__pool", assetAddress, poolMakerAddress, "maxAmount"], SEP) | |
121 | + | ||
122 | + | ||
123 | + | func getPoolMakerLockedAmountKey (assetAddress,poolMakerAddress) = makeString(["%s%s%s%s__pool", assetAddress, poolMakerAddress, "lockedAmount"], SEP) | |
124 | + | ||
125 | + | ||
126 | + | func getPoolMakerUnlockHeightKey (assetAddress,poolMakerAddress) = makeString(["%s%s%s%s__pool", assetAddress, poolMakerAddress, "unlockHeight"], SEP) | |
127 | + | ||
128 | + | ||
129 | + | func getPoolMakerLiquidityRequestKey (assetAddress,poolMakerAddress,h) = makeString(["%s%s%s%d%s__pool", assetAddress, poolMakerAddress, toString(h), "liquidityRequest"], SEP) | |
130 | + | ||
131 | + | ||
132 | + | func getPoolTotalLockedAmountKey (assetAddress) = makeString(["%s%s%s__pool", assetAddress, "totalLockedAmount"], SEP) | |
133 | + | ||
134 | + | ||
135 | + | func getPoolMinInvestAmountKey (assetAddress) = makeString(["%s%s%s__pool", assetAddress, "minInvestAmount"], SEP) | |
136 | + | ||
137 | + | ||
138 | + | func getPoolMinRedeemAmountKey (assetAddress) = makeString(["%s%s%s__pool", assetAddress, "minRedeemAmount"], SEP) | |
139 | + | ||
140 | + | ||
141 | + | func getAssetConfigArray (assetAddress) = split(valueOrErrorMessage(getString(this, getAssetConfigKey(assetAddress)), ("No DEFO Asset config present for " + assetAddress)), SEP) | |
142 | + | ||
143 | + | ||
144 | + | let multiplicator = 1000000 | |
145 | + | ||
146 | + | let neutrinoContract = addressFromStringValue(valueOrErrorMessage(getString(this, neutrinoContractAddressKey), "No neutrino contract specified.")) | |
147 | + | ||
148 | + | let neutrinoAssetIdStr = valueOrErrorMessage(getString(neutrinoContract, neutrinoAssetIdKey), "No USDN asset id found.") | |
149 | + | ||
150 | + | let neutrinoAssetId = fromBase58String(neutrinoAssetIdStr) | |
151 | + | ||
152 | + | let nsbtAssetId = fromBase58String(valueOrErrorMessage(getString(neutrinoContract, nsbtAssetIdKey), "No NSBT asset id found")) | |
153 | + | ||
154 | + | let minimumPoolFunding = valueOrErrorMessage(getInteger(this, minimunPoolFundingAmountKey), "Minimum pool funding amount is not specified.") | |
155 | + | ||
156 | + | let ASSEtPROPOSED = "PROPOSED" | |
157 | + | ||
158 | + | let ASSEtREADY = "READY" | |
159 | + | ||
160 | + | let ASSEtISSUED = "ISSUED" | |
161 | + | ||
162 | + | let assetStatus = $Tuple3(ASSEtPROPOSED, ASSEtREADY, ASSEtISSUED) | |
163 | + | ||
164 | + | let debtToken = fromBase58String(valueOrErrorMessage(getString(this, debtTokenIdKey), "No debt token found")) | |
165 | + | ||
166 | + | let debtTokenReissueAmount = valueOrElse(getInteger(this, debtTokenEtalonBalanceKey), 0) | |
167 | + | ||
168 | + | let neutrinoRpdContract = addressFromStringValue(getStringValue(neutrinoContract, neutrinoRpdKey)) | |
169 | + | ||
170 | + | func getNeutrinoRpdBalance (userAddress) = { | |
171 | + | let userNeutrinoRpdBalance = makeString(["rpd_balance", neutrinoAssetIdStr, userAddress], "_") | |
172 | + | valueOrElse(getInteger(neutrinoRpdContract, userNeutrinoRpdBalance), 0) | |
173 | + | } | |
174 | + | ||
175 | + | ||
176 | + | func getAssetAddressByCode (assetSymbol) = valueOrElse(getString(this, getAssetAddressByCodeKey(assetSymbol)), "") | |
177 | + | ||
178 | + | ||
179 | + | func getAssetAddressByCodeOrFail (assetSymbol) = valueOrErrorMessage(getString(this, getAssetAddressByCodeKey(assetSymbol)), (("Cannot find asset address by " + assetSymbol) + " code")) | |
180 | + | ||
181 | + | ||
182 | + | func getAssetCode (assetConfig) = assetConfig[keyAssetCode] | |
183 | + | ||
184 | + | ||
185 | + | func getAssetID (assetConfig) = assetConfig[keyAssetId] | |
186 | + | ||
187 | + | ||
188 | + | func getAssetStatus (assetConfig) = assetConfig[keyAssetStatus] | |
189 | + | ||
190 | + | ||
191 | + | func getAssetPriceDecimals (assetConfig) = parseIntValue(assetConfig[keyAssetPriceDecimals]) | |
192 | + | ||
193 | + | ||
194 | + | func getAssetBakingAssetId (assetConfig) = assetConfig[keyAssetBakingAsset] | |
195 | + | ||
196 | + | ||
197 | + | func getAssetOverCollateralPercent (assetConfig) = parseIntValue(assetConfig[keyOvercollateralPercentage]) | |
198 | + | ||
199 | + | ||
200 | + | func getAssetMinRequiredPoolAmount (assetConfig) = parseIntValue(assetConfig[keyMinPool]) | |
201 | + | ||
202 | + | ||
203 | + | func getAssetPriceOracleAddress (assetConfig) = assetConfig[keyPriceOracleAddress] | |
204 | + | ||
205 | + | ||
206 | + | func getMinBuyPaymentPerAsset (assetConfig) = parseIntValue(assetConfig[keyMinBuyPayment]) | |
207 | + | ||
208 | + | ||
209 | + | func getMinSellPaymentPerAsset (assetConfig) = parseIntValue(assetConfig[keyMinSellPayment]) | |
210 | + | ||
211 | + | ||
212 | + | func getBuyLockIntervalPerAsset (assetConfig) = parseIntValue(assetConfig[keyBuyLockInterval]) | |
213 | + | ||
214 | + | ||
215 | + | func getSellLockIntervalPerAsset (assetConfig) = parseIntValue(assetConfig[keySellLockInterval]) | |
216 | + | ||
217 | + | ||
218 | + | func getBuyFeePerAsset (assetConfig) = parseIntValue(assetConfig[keyBuyFee]) | |
219 | + | ||
220 | + | ||
221 | + | func getSellFeePerAsset (assetConfig) = parseIntValue(assetConfig[keySellFee]) | |
222 | + | ||
223 | + | ||
224 | + | func getRedemptionTimeoutBlocks (assetConfig) = parseIntValue(assetConfig[keyPoolRedemptionTimeout]) | |
225 | + | ||
226 | + | ||
227 | + | func getWeekendsPriceChangeCoefficient (assetConfig) = parseIntValue(assetConfig[keyWeekendsPriceChangeCoefficient]) | |
228 | + | ||
229 | + | ||
230 | + | func getProtocolFeePerAsset (assetConfig) = parseIntValue(assetConfig[keyProtocolFee]) | |
231 | + | ||
232 | + | ||
233 | + | func getAssetInitHeight (assetAddress) = valueOrElse(getInteger(this, getAssetInitHeightKey(assetAddress)), 0) | |
234 | + | ||
235 | + | ||
236 | + | func getAssetActivateHeight (assetAddress) = valueOrElse(getInteger(this, getAssetActivateHeightKey(assetAddress)), 0) | |
237 | + | ||
238 | + | ||
239 | + | func getAssetCurrentPoolAmount (assetAddress) = valueOrElse(getInteger(this, getAssetCurrrentPoolAmountKey(assetAddress)), 0) | |
240 | + | ||
241 | + | ||
242 | + | func getAssetMaxPoolAmount (assetAddress) = valueOrElse(getInteger(this, getAssetMaxPoolAmountKey(assetAddress)), 0) | |
243 | + | ||
244 | + | ||
245 | + | func getAssetMeta (assetAddress) = valueOrElse(getString(this, getAssetMetaKey(assetAddress)), "") | |
246 | + | ||
247 | + | ||
248 | + | func getPoolMakerParticipationAmount (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerParticipationAmountKey(assetAddress, poolMakerAddress)), 0) | |
249 | + | ||
250 | + | ||
251 | + | func getPoolMakerParticipationMaxAmount (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerParticipationMaxAmountKey(assetAddress, poolMakerAddress)), 0) | |
252 | + | ||
253 | + | ||
254 | + | func getPoolMakerLockedAmount (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerLockedAmountKey(assetAddress, poolMakerAddress)), 0) | |
255 | + | ||
256 | + | ||
257 | + | func getPoolMakerUnlockHeight (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerUnlockHeightKey(assetAddress, poolMakerAddress)), 0) | |
258 | + | ||
259 | + | ||
260 | + | func getAssetPrice (priceOracleAddress,assetCode) = valueOrErrorMessage(getInteger(priceOracleAddress, getAssetPriceKey(assetCode)), "No Asset price found") | |
261 | + | ||
262 | + | ||
263 | + | func getPoolTotalLockedAmount (assetAddress) = valueOrElse(getInteger(this, getPoolTotalLockedAmountKey(assetAddress)), 0) | |
264 | + | ||
265 | + | ||
266 | + | func composeAssetConfigurationString (assetCode,assetId,assetStatus,priceDecimals,backingAssetId,overCollateralPercent,minPool,priceOracleAddress,minBuyPayment,minSellPayment,buyLockInterval,sellLockInterval,buyFee,sellFee,poolRedemptionTimeout,weekendsPriceChangeCoefficient,assetAccountPublicStr,assetStakingReferralPublicStr,crossExchangeCoefficientStr,stakingMinAmtFromSellCoefficientStr,poolStabilityFeeStr,protocolFeeStr) = makeString(["%s%s%s%d%s%d%d%s%d%d%d%d%d%d%d%d%s%s%d%d%d", assetCode, assetId, assetStatus, toString(priceDecimals), backingAssetId, toString(overCollateralPercent), toString(minPool), priceOracleAddress, toString(minBuyPayment), toString(minSellPayment), toString(buyLockInterval), toString(sellLockInterval), toString(buyFee), toString(sellFee), toString(poolRedemptionTimeout), toString(weekendsPriceChangeCoefficient), assetAccountPublicStr, assetStakingReferralPublicStr, crossExchangeCoefficientStr, stakingMinAmtFromSellCoefficientStr, poolStabilityFeeStr, protocolFeeStr], "__") | |
267 | + | ||
268 | + | ||
269 | + | func updateAssetCfgStatus (newStatus,assetConfigurationList) = { | |
270 | + | let aCode = getAssetCode(assetConfigurationList) | |
271 | + | let aID = getAssetID(assetConfigurationList) | |
272 | + | let aPriceDecimals = getAssetPriceDecimals(assetConfigurationList) | |
273 | + | let aBakingAssetId = getAssetBakingAssetId(assetConfigurationList) | |
274 | + | let aOverCollateralPercent = getAssetOverCollateralPercent(assetConfigurationList) | |
275 | + | let aMinRequiredPool = getAssetMinRequiredPoolAmount(assetConfigurationList) | |
276 | + | let aPriceOracleAddress = getAssetPriceOracleAddress(assetConfigurationList) | |
277 | + | let aMinBuyPayment = getMinBuyPaymentPerAsset(assetConfigurationList) | |
278 | + | let aMinSellPayment = getMinSellPaymentPerAsset(assetConfigurationList) | |
279 | + | let aBuyLockInterval = getBuyLockIntervalPerAsset(assetConfigurationList) | |
280 | + | let aSellLockInterval = getSellLockIntervalPerAsset(assetConfigurationList) | |
281 | + | let aBuyFee = getBuyFeePerAsset(assetConfigurationList) | |
282 | + | let aSellFee = getSellFeePerAsset(assetConfigurationList) | |
283 | + | let aRedemptionTimeoutBlocks = getRedemptionTimeoutBlocks(assetConfigurationList) | |
284 | + | let weekendsPriceChangeCoefficient = getWeekendsPriceChangeCoefficient(assetConfigurationList) | |
285 | + | composeAssetConfigurationString(aCode, aID, newStatus, aPriceDecimals, aBakingAssetId, aOverCollateralPercent, aMinRequiredPool, aPriceOracleAddress, aMinBuyPayment, aMinSellPayment, aBuyLockInterval, aSellLockInterval, aBuyFee, aSellFee, aRedemptionTimeoutBlocks, weekendsPriceChangeCoefficient, assetConfigurationList[keyAssetAccountPublicStr], assetConfigurationList[keyAssetStakingReferralPublicStr], assetConfigurationList[keyCrossExchangeCoefficient], assetConfigurationList[keyStakingMinAmtFromSellCoefficient], assetConfigurationList[keyPoolStabilityFee], assetConfigurationList[keyProtocolFee]) | |
286 | + | } | |
287 | + | ||
288 | + | ||
289 | + | func calcAllowedAmountToRedeem (assetCode,poolMakerAddress) = { | |
290 | + | let assetAddressStr = getAssetAddressByCodeOrFail(assetCode) | |
291 | + | let assetAddress = addressFromStringValue(assetAddressStr) | |
292 | + | let assetConfigurationList = getAssetConfigArray(assetAddressStr) | |
293 | + | let assetIdStr = getAssetID(assetConfigurationList) | |
294 | + | let assetId = fromBase58String(assetIdStr) | |
295 | + | let poolActualSize = valueOrElse(getInteger(this, getAssetCurrrentPoolAmountKey(assetAddressStr)), 0) | |
296 | + | let poolMaxSize = valueOrElse(getInteger(this, getAssetMaxPoolAmountKey(assetAddressStr)), 0) | |
297 | + | let poolTotalLockedAmountKey = getPoolTotalLockedAmountKey(assetAddressStr) | |
298 | + | let poolTotalLocked = valueOrElse(getInteger(this, poolTotalLockedAmountKey), 0) | |
299 | + | let assetUsdnStakedAmount = getNeutrinoRpdBalance(assetAddressStr) | |
300 | + | let assetUsdnBalanceAmount = assetBalance(assetAddress, neutrinoAssetId) | |
301 | + | let lendedOrDebtAmount = (debtTokenReissueAmount - assetBalance(assetAddress, debtToken)) | |
302 | + | let assetTotalUsdnAmount = (((assetUsdnStakedAmount + assetUsdnBalanceAmount) - poolTotalLocked) + lendedOrDebtAmount) | |
303 | + | let ucollateral = (assetTotalUsdnAmount - poolActualSize) | |
304 | + | let defoAssetBalance = assetBalance(assetAddress, assetId) | |
305 | + | let assetEmissionDirty = valueOrErrorMessage(assetInfo(assetId), ("Cannot find asset by id " + assetIdStr)).quantity | |
306 | + | let assetEmission = (assetEmissionDirty - defoAssetBalance) | |
307 | + | let priceOracleAddress = addressFromStringValue(getAssetPriceOracleAddress(assetConfigurationList)) | |
308 | + | let currentPrice = getAssetPrice(priceOracleAddress, assetCode) | |
309 | + | let assetEmissionOvercollateralRate = fraction((multiplicator + getAssetOverCollateralPercent(assetConfigurationList)), assetEmission, multiplicator) | |
310 | + | let usdnNeededToCoverEmission = fraction(assetEmissionOvercollateralRate, multiplicator, currentPrice) | |
311 | + | let poolMakerMaxAmount = getPoolMakerParticipationMaxAmount(assetAddressStr, poolMakerAddress) | |
312 | + | let poolMakerParticipationAmountKey = getPoolMakerParticipationAmountKey(assetAddressStr, poolMakerAddress) | |
313 | + | let poolMakerActualAmount = valueOrElse(getInteger(this, poolMakerParticipationAmountKey), 0) | |
314 | + | let poolMakerLockedAmount = getPoolMakerLockedAmount(assetAddressStr, poolMakerAddress) | |
315 | + | let surplus = (ucollateral - usdnNeededToCoverEmission) | |
316 | + | let percentViaActual = fraction(poolMakerActualAmount, multiplicator, poolActualSize) | |
317 | + | let percentViaMax = fraction(poolMakerMaxAmount, multiplicator, poolMaxSize) | |
318 | + | let frozenPart = if ((surplus >= 0)) | |
319 | + | then 0 | |
320 | + | else max([percentViaActual, percentViaMax]) | |
321 | + | let allowedAmountToRedeem = if ((surplus >= 0)) | |
322 | + | then poolMakerActualAmount | |
323 | + | else (fraction(frozenPart, surplus, multiplicator) + poolMakerActualAmount) | |
324 | + | let withdrawHeight = (height + getRedemptionTimeoutBlocks(assetConfigurationList)) | |
325 | + | $Tuple8(assetAddressStr, allowedAmountToRedeem, poolTotalLocked, poolActualSize, poolMakerActualAmount, withdrawHeight, poolMakerLockedAmount, makeString([assetAddressStr, assetIdStr, poolMakerAddress, toString(assetUsdnStakedAmount), toString(assetUsdnBalanceAmount), toString(assetTotalUsdnAmount), toString(poolActualSize), toString(poolMaxSize), toString(ucollateral), toString(assetEmission), toString(currentPrice), toString(assetEmissionOvercollateralRate), toString(poolMakerMaxAmount), toString(poolMakerActualAmount), toString(poolMakerLockedAmount), toString(surplus), toString(percentViaActual), toString(percentViaMax), toString(frozenPart), toString(allowedAmountToRedeem)], SEP)) | |
326 | + | } | |
327 | + | ||
328 | + | ||
329 | + | @Callable(i) | |
330 | + | func init (neutrinoContractAddress,neutrinoStakingAddress,minimunPoolFundingAmount,debtEthalonBalance,defoStakingAddress,defoStakingPacemakerPub) = if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
331 | + | then throw("Only Admin can perform contract operation.") | |
332 | + | else if ((getBoolByKey(isInitializedKey) == true)) | |
333 | + | then throw("Contract was already initialized.") | |
334 | + | else { | |
335 | + | let issueDebt = Issue("DEFO_DEBT", "DEFO Debt Token.", 1, 6, true) | |
336 | + | let debtTokenId = calculateAssetId(issueDebt) | |
337 | + | [StringEntry(neutrinoContractAddressKey, neutrinoContractAddress), StringEntry(neutrinoStakingAddressKey, neutrinoStakingAddress), IntegerEntry(minimunPoolFundingAmountKey, minimunPoolFundingAmount), IntegerEntry(debtTokenEtalonBalanceKey, debtEthalonBalance), StringEntry(debtTokenIdKey, toBase58String(debtTokenId)), StringEntry(defoStakingAddressKey, defoStakingAddress), StringEntry(defoStakingPacemakerPubKey, defoStakingPacemakerPub), BooleanEntry(isInitializedKey, true), issueDebt, Burn(debtTokenId, 1)] | |
338 | + | } | |
339 | + | ||
340 | + | ||
341 | + | ||
342 | + | @Callable(i) | |
343 | + | func proposeAsset (assetCode,minPool,priceOracleAddress,minSellPayment) = { | |
344 | + | let backingAssetId = neutrinoAssetIdStr | |
345 | + | let priceDecimals = multiplicator | |
346 | + | let buyLockInterval = 0 | |
347 | + | let sellLockInterval = 0 | |
348 | + | let minBuyPayment = (1 * multiplicator) | |
349 | + | let poolRedemptionTimeout = 0 | |
350 | + | let buyFee = 2750 | |
351 | + | let sellFee = 2750 | |
352 | + | let weekendsPriceChangeCoefficient = 15000 | |
353 | + | let overCollateralPercent = 0 | |
354 | + | let crossExchangeCoefficient = 500000 | |
355 | + | let stakingMinAmtFromSellCoefficient = (1 * multiplicator) | |
356 | + | let minPoolInvestAmount = (10 * multiplicator) | |
357 | + | let minPoolRedeemAmount = (1 * multiplicator) | |
358 | + | let poolStabilityFee = 500 | |
359 | + | let protocolFee = 2750 | |
360 | + | if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
361 | + | then throw("Only Admin can perform contract operation.") | |
362 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
363 | + | then throw("Contract is not yet ready.") | |
364 | + | else if ((fromBase58String(backingAssetId) != neutrinoAssetId)) | |
365 | + | then throw("Baking asset id could be USDN only.") | |
366 | + | else if ((getAssetAddressByCode(assetCode) != "")) | |
367 | + | then throw((("Asset with passed code " + assetCode) + " has already been proposed.")) | |
368 | + | else if ((minimumPoolFunding > minPool)) | |
369 | + | then throw(("Minimum pool amount should be greater or equals to " + toString(minimumPoolFunding))) | |
370 | + | else if (if (if (if (if (if (if ((0 > overCollateralPercent)) | |
371 | + | then true | |
372 | + | else (0 > minBuyPayment)) | |
373 | + | then true | |
374 | + | else (0 > minSellPayment)) | |
375 | + | then true | |
376 | + | else (0 > buyLockInterval)) | |
377 | + | then true | |
378 | + | else (0 > sellLockInterval)) | |
379 | + | then true | |
380 | + | else (0 > buyFee)) | |
381 | + | then true | |
382 | + | else (0 > sellFee)) | |
383 | + | then throw("One of the passed parameters is invalid.") | |
384 | + | else { | |
385 | + | let priceOracleAddressValid = valueOrErrorMessage(addressFromStringValue(priceOracleAddress), "Passed Price Oracle Address is not valid.") | |
386 | + | let preInitDataStr = valueOrErrorMessage(getString(this, getPreInitializedAssetDataKey(assetCode)), ("Unsupported currency - there is no preinitialized data for " + assetCode)) | |
387 | + | let preInitDataArray = split(preInitDataStr, SEP) | |
388 | + | let preInitAssetPublicStr = preInitDataArray[IdxPreInitializedAssetPublic] | |
389 | + | let preInitStakingReferralPublicStr = preInitDataArray[IdxPreInitializedAssetStakingReferralPublic] | |
390 | + | let preInitDescription = preInitDataArray[IdxPreInitializedAssetDescription] | |
391 | + | let assetAddress = addressFromPublicKey(fromBase58String(preInitAssetPublicStr)) | |
392 | + | let assetAddressStr = toString(assetAddress) | |
393 | + | let defoAssetId = valueOrErrorMessage(getString(assetAddress, defoAssetIdKey), "No defo asset ID found.") | |
394 | + | [StringEntry(getAssetConfigKey(assetAddressStr), composeAssetConfigurationString(assetCode, defoAssetId, assetStatus._1, priceDecimals, backingAssetId, overCollateralPercent, minPool, priceOracleAddress, minBuyPayment, minSellPayment, buyLockInterval, sellLockInterval, buyFee, sellFee, poolRedemptionTimeout, weekendsPriceChangeCoefficient, preInitAssetPublicStr, preInitStakingReferralPublicStr, toString(crossExchangeCoefficient), toString(stakingMinAmtFromSellCoefficient), toString(poolStabilityFee), toString(protocolFee))), StringEntry(getAssetAddressByCodeKey(assetCode), assetAddressStr), StringEntry(getAssetMetaKey(assetAddressStr), preInitDescription), IntegerEntry(getAssetInitHeightKey(assetAddressStr), height), StringEntry(getAssetAddressByAssetIdKey(defoAssetId), assetAddressStr), IntegerEntry(getPoolMinInvestAmountKey(assetAddressStr), minPoolInvestAmount), IntegerEntry(getPoolMinRedeemAmountKey(assetAddressStr), minPoolRedeemAmount)] | |
395 | + | } | |
396 | + | } | |
397 | + | ||
398 | + | ||
399 | + | ||
400 | + | @Callable(i) | |
401 | + | func fundLiquidityPool (assetCode) = { | |
402 | + | let assetAddressStr = getAssetAddressByCodeOrFail(assetCode) | |
403 | + | let assetConfigurationList = getAssetConfigArray(assetAddressStr) | |
404 | + | let attachedPayment = value(i.payments[0]) | |
405 | + | let poolMakerAddress = toString(i.caller) | |
406 | + | let currentPoolMakerBalance = getPoolMakerParticipationAmount(assetAddressStr, poolMakerAddress) | |
407 | + | let minPoolInvestAmount = valueOrElse(getInteger(this, getPoolMinInvestAmountKey(assetAddressStr)), (10 * multiplicator)) | |
408 | + | if ((getBoolByKey(isInitializedKey) == false)) | |
409 | + | then throw("Contract is not yet ready.") | |
410 | + | else if ((attachedPayment.assetId != neutrinoAssetId)) | |
411 | + | then throw("Liquidity pool could be funded with USDN only.") | |
412 | + | else if (if ((minPoolInvestAmount > currentPoolMakerBalance)) | |
413 | + | then (minPoolInvestAmount > attachedPayment.amount) | |
414 | + | else false) | |
415 | + | then throw(("Attached payment amount is less tha min allowed: " + toString(minPoolInvestAmount))) | |
416 | + | else { | |
417 | + | let newCurrentPoolAmount = (attachedPayment.amount + getAssetCurrentPoolAmount(assetAddressStr)) | |
418 | + | let maxPoolAmount = getAssetMaxPoolAmount(assetAddressStr) | |
419 | + | let maxPoolMakerBalance = getPoolMakerParticipationMaxAmount(assetAddressStr, poolMakerAddress) | |
420 | + | let currentAssetStatus = getAssetStatus(assetConfigurationList) | |
421 | + | let newAssetStatus = if (if ((currentAssetStatus == ASSEtPROPOSED)) | |
422 | + | then (newCurrentPoolAmount >= getAssetMinRequiredPoolAmount(assetConfigurationList)) | |
423 | + | else false) | |
424 | + | then ASSEtREADY | |
425 | + | else currentAssetStatus | |
426 | + | let newPoolMakerBalance = (currentPoolMakerBalance + attachedPayment.amount) | |
427 | + | let immediateTransferIfIssued = if ((currentAssetStatus == ASSEtISSUED)) | |
428 | + | then [ScriptTransfer(addressFromStringValue(assetAddressStr), attachedPayment.amount, neutrinoAssetId)] | |
429 | + | else nil | |
430 | + | ([IntegerEntry(getPoolMakerParticipationAmountKey(assetAddressStr, poolMakerAddress), newPoolMakerBalance), IntegerEntry(getPoolMakerParticipationMaxAmountKey(assetAddressStr, poolMakerAddress), max([newPoolMakerBalance, maxPoolMakerBalance])), IntegerEntry(getAssetCurrrentPoolAmountKey(assetAddressStr), newCurrentPoolAmount), IntegerEntry(getAssetMaxPoolAmountKey(assetAddressStr), max([maxPoolAmount, newCurrentPoolAmount])), StringEntry(getAssetConfigKey(assetAddressStr), updateAssetCfgStatus(newAssetStatus, assetConfigurationList))] ++ immediateTransferIfIssued) | |
431 | + | } | |
432 | + | } | |
433 | + | ||
434 | + | ||
435 | + | ||
436 | + | @Callable(i) | |
437 | + | func activateAsset (assetCode) = { | |
438 | + | let assetAddress = getAssetAddressByCode(assetCode) | |
439 | + | let assetConfigurationList = getAssetConfigArray(assetAddress) | |
440 | + | let assetCurrentPoolAmount = getAssetCurrentPoolAmount(assetAddress) | |
441 | + | let aCurrentStatus = getAssetStatus(assetConfigurationList) | |
442 | + | if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
443 | + | then throw("Only Admin can perform contract operation.") | |
444 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
445 | + | then throw("Contract is not yet ready.") | |
446 | + | else if ((aCurrentStatus != assetStatus._2)) | |
447 | + | then throw((("Asset is not in READY status. Current status is " + aCurrentStatus) + ".")) | |
448 | + | else if ((assetAddress == "")) | |
449 | + | then throw((("Cannot find asset " + assetCode) + ".")) | |
450 | + | else if ((minimumPoolFunding > assetCurrentPoolAmount)) | |
451 | + | then throw((((("Cannot issue asset as liquidity pool amount (" + toString(assetCurrentPoolAmount)) + ") is less than required (") + toString(minimumPoolFunding)) + ")")) | |
452 | + | else { | |
453 | + | let issueDebt = Reissue(debtToken, debtTokenReissueAmount, true) | |
454 | + | [IntegerEntry(getAssetActivateHeightKey(assetAddress), height), StringEntry(getAssetConfigKey(assetAddress), updateAssetCfgStatus(assetStatus._3, assetConfigurationList)), issueDebt, ScriptTransfer(addressFromStringValue(assetAddress), assetCurrentPoolAmount, neutrinoAssetId), ScriptTransfer(addressFromStringValue(assetAddress), debtTokenReissueAmount, debtToken)] | |
455 | + | } | |
456 | + | } | |
457 | + | ||
458 | + | ||
459 | + | ||
460 | + | @Callable(i) | |
461 | + | func redeemFromPool (assetCode,amount) = { | |
462 | + | let callerAddress = toString(i.caller) | |
463 | + | let redeemTuple = calcAllowedAmountToRedeem(assetCode, callerAddress) | |
464 | + | let assetAddressStr = redeemTuple._1 | |
465 | + | let allowedAmountToRedeem = redeemTuple._2 | |
466 | + | let poolTotalLocked = redeemTuple._3 | |
467 | + | let poolActualSize = redeemTuple._4 | |
468 | + | let poolMakerActualAmount = redeemTuple._5 | |
469 | + | let withdrawHeight = redeemTuple._6 | |
470 | + | let poolMakerLockedAmount = redeemTuple._7 | |
471 | + | let traceData = redeemTuple._8 | |
472 | + | let poolMakerLiquidityRequestKey = getPoolMakerLiquidityRequestKey(assetAddressStr, callerAddress, withdrawHeight) | |
473 | + | let minPoolRedeemAmount = valueOrElse(getInteger(this, getPoolMinRedeemAmountKey(assetAddressStr)), (1 * multiplicator)) | |
474 | + | if ((getBoolByKey(isInitializedKey) == false)) | |
475 | + | then throw("Contract is not yet ready.") | |
476 | + | else if ((0 >= amount)) | |
477 | + | then throw((("Cannot find pool maker by address " + callerAddress) + " or amount passed is not correct.")) | |
478 | + | else if ((0 >= poolMakerActualAmount)) | |
479 | + | then throw("Pool maker has no funds") | |
480 | + | else if ((0 >= allowedAmountToRedeem)) | |
481 | + | then throw("All pool maker funds are locked") | |
482 | + | else if ((amount > allowedAmountToRedeem)) | |
483 | + | then throw(((("Allowed amount to redeem is less then requested: allowedAmountToRedeem=" + toString(allowedAmountToRedeem)) + " requested=") + toString(amount))) | |
484 | + | else if ((minPoolRedeemAmount > amount)) | |
485 | + | then throw("Redeem amount is less then min allowed") | |
486 | + | else if ((poolMakerLockedAmount > 0)) | |
487 | + | then throw("Pool maker already has initiated redemption that is not withdrawn yet.") | |
488 | + | else if (isDefined(getInteger(this, poolMakerLiquidityRequestKey))) | |
489 | + | then throw((("Pool maker has already initiated redemption for " + toString(height)) + " height")) | |
490 | + | else [IntegerEntry(getPoolTotalLockedAmountKey(assetAddressStr), (poolTotalLocked + amount)), IntegerEntry(getAssetCurrrentPoolAmountKey(assetAddressStr), (poolActualSize - amount)), IntegerEntry(getPoolMakerParticipationAmountKey(assetAddressStr, callerAddress), (poolMakerActualAmount - amount)), IntegerEntry(poolMakerLiquidityRequestKey, amount), IntegerEntry(getPoolMakerLockedAmountKey(assetAddressStr, callerAddress), amount), IntegerEntry(getPoolMakerUnlockHeightKey(assetAddressStr, callerAddress), withdrawHeight), StringEntry("%s%s_trace_redeemFromPool", traceData)] | |
491 | + | } | |
492 | + | ||
493 | + | ||
494 | + | ||
495 | + | @Callable(i) | |
496 | + | func getMaxAllowedAmountToRedeem (assetCode,poolMakerAddress) = { | |
497 | + | let redeemTuple = calcAllowedAmountToRedeem(assetCode, poolMakerAddress) | |
498 | + | let assetAddressStr = redeemTuple._1 | |
499 | + | let allowedAmountToRedeem = redeemTuple._2 | |
500 | + | let poolTotalLocked = redeemTuple._3 | |
501 | + | let poolActualSize = redeemTuple._4 | |
502 | + | let poolMakerActualAmount = redeemTuple._5 | |
503 | + | let withdrawHeight = redeemTuple._6 | |
504 | + | let poolMakerLockedAmount = redeemTuple._7 | |
505 | + | let traceData = redeemTuple._8 | |
506 | + | throw(((((((((("{" + "allowedAmountToRedeem: ") + toString(allowedAmountToRedeem)) + ", assetCode: ") + assetCode) + ", poolMaker: ") + poolMakerAddress) + ", trace: ") + traceData) + "}")) | |
507 | + | } | |
508 | + | ||
509 | + | ||
510 | + | ||
511 | + | @Callable(i) | |
512 | + | func withdraw (assetCode,poolMakerAddress) = { | |
513 | + | let assetAddressStr = getAssetAddressByCodeOrFail(assetCode) | |
514 | + | let assetAddress = addressFromStringValue(assetAddressStr) | |
515 | + | let poolMakerLockedAmountKey = getPoolMakerLockedAmountKey(assetAddressStr, poolMakerAddress) | |
516 | + | let registeredAmount4Withdraw = valueOrElse(getInteger(this, poolMakerLockedAmountKey), 0) | |
517 | + | let poolMakerUnlockHeightKey = getPoolMakerUnlockHeightKey(assetAddressStr, poolMakerAddress) | |
518 | + | let withdrawHeight = valueOrElse(getInteger(this, poolMakerUnlockHeightKey), 0) | |
519 | + | let poolTotalLockedAmountKey = getPoolTotalLockedAmountKey(assetAddressStr) | |
520 | + | let poolTotalLocked = valueOrElse(getInteger(this, poolTotalLockedAmountKey), 0) | |
521 | + | let poolMakerLiquidityRequestKey = getPoolMakerLiquidityRequestKey(assetAddressStr, poolMakerAddress, withdrawHeight) | |
522 | + | if ((getBoolByKey(isInitializedKey) == false)) | |
523 | + | then throw("Contract is not yet ready.") | |
524 | + | else if (!(isDefined(getInteger(assetAddress, poolMakerLiquidityRequestKey)))) | |
525 | + | then throw("Need to transfer liquidity from asset account first") | |
526 | + | else if ((0 >= registeredAmount4Withdraw)) | |
527 | + | then throw((("Cannot find pool maker by address " + poolMakerAddress) + " or no locked amount.")) | |
528 | + | else if ((withdrawHeight > height)) | |
529 | + | then throw((("Please wait " + toString(withdrawHeight)) + " before withdraw.")) | |
530 | + | else [IntegerEntry(poolMakerLockedAmountKey, 0), IntegerEntry(poolTotalLockedAmountKey, (poolTotalLocked - registeredAmount4Withdraw)), IntegerEntry(poolMakerUnlockHeightKey, 0), ScriptTransfer(addressFromStringValue(poolMakerAddress), registeredAmount4Withdraw, neutrinoAssetId)] | |
531 | + | } | |
532 | + | ||
533 | + |
github/deemru/w8io/026f985 72.69 ms ◑