tx · 9qvnTDCo7SHVuE2tNK5z7p2cjh3FXFSpXv5PUu1nevgY 3MykWs5Yp82nCxxcUAYZgdgUxvdVRQdsFG9: -0.01000000 Waves 2020.09.22 21:07 [1188851] smart account 3MykWs5Yp82nCxxcUAYZgdgUxvdVRQdsFG9 > SELF 0.00000000 Waves
{ "type": 13, "id": "9qvnTDCo7SHVuE2tNK5z7p2cjh3FXFSpXv5PUu1nevgY", "fee": 1000000, "feeAssetId": null, "timestamp": 1600798065851, "version": 1, "sender": "3MykWs5Yp82nCxxcUAYZgdgUxvdVRQdsFG9", "senderPublicKey": "2si3zs1hTCND9cN6noH8qviNZVbbkTvwyT7WDFnEte4L", "proofs": [ "21Yxo9CkyJrDN4QRHCG3ycx7BvFTCx1vp738UoswQkYipmrMebZUdpJMpcpUqX3RGrjekNRZpu8JhDtuEYbcEPMu" ], "script": "base64:AAIEAAAAAAAAADEIAhIGCgQIAQgBEhAKDggIAQgBCAEBAQEBAQEBEgMKAQgSAwoBCBIECgIIARIDCgEIAAAAUwEAAAAWY29udmVydEpzb25BcnJheVRvTGlzdAAAAAIAAAAJanNvbkFycmF5AAAAC3NwbGl0U3ltYm9sCQAEtQAAAAIFAAAACWpzb25BcnJheQUAAAALc3BsaXRTeW1ib2wBAAAAGGdldFN0cmluZ0J5QWRkcmVzc0FuZEtleQAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAHYWRkcmVzcwUAAAADa2V5AgAAAAABAAAADGdldEJvb2xCeUtleQAAAAEAAAADa2V5CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGwAAAAIFAAAABHRoaXMFAAAAA2tleQcAAAAADGtleUFzc2V0Q29kZQAAAAAAAAAAAQAAAAAKa2V5QXNzZXRJZAAAAAAAAAAAAgAAAAAOa2V5QXNzZXRTdGF0dXMAAAAAAAAAAAMAAAAAFWtleUFzc2V0UHJpY2VEZWNpbWFscwAAAAAAAAAABAAAAAATa2V5QXNzZXRCYWtpbmdBc3NldAAAAAAAAAAABQAAAAAba2V5T3ZlcmNvbGxhdGVyYWxQZXJjZW50YWdlAAAAAAAAAAAGAAAAAAprZXlNaW5Qb29sAAAAAAAAAAAHAAAAABVrZXlQcmljZU9yYWNsZUFkZHJlc3MAAAAAAAAAAAgAAAAAEGtleU1pbkJ1eVBheW1lbnQAAAAAAAAAAAkAAAAAEWtleU1pblNlbGxQYXltZW50AAAAAAAAAAAKAAAAABJrZXlCdXlMb2NrSW50ZXJ2YWwAAAAAAAAAAAsAAAAAE2tleVNlbGxMb2NrSW50ZXJ2YWwAAAAAAAAAAAwAAAAACWtleUJ1eUZlZQAAAAAAAAAADQAAAAAKa2V5U2VsbEZlZQAAAAAAAAAADgAAAAAYa2V5UG9vbFJlZGVtcHRpb25UaW1lb3V0AAAAAAAAAAAPAAAAAAlTRVBBUkFUT1ICAAAAAl9fAAAAAAxDT01NT05DT05GSUcCAAAADGNvbW1vbkNvbmZpZwAAAAAOYWRtaW5QdWJsaWNLZXkCAAAALEJISGdFb2VoY25oc25tQ1JjZ29hc2NYVXh0bVd4bTVvNDF0QUNRNHpSdFdIAAAAABpuZXV0cmlub0NvbnRyYWN0QWRkcmVzc0tleQIAAAArJXMlc19fY29tbW9uQ29uZmlnX19uZXV0cmlub0NvbnRyYWN0QWRkcmVzcwAAAAAbbWluaW11blBvb2xGdW5kaW5nQW1vdW50S2V5AgAAACwlcyVzX19jb21tb25Db25maWdfX21pbmltdW1Qb29sRnVuZGluZ0Ftb3VudAAAAAAQaXNJbml0aWFsaXplZEtleQIAAAAfJXMlc19fY29tbW9uQ29uZmlnX19pbml0aWFsaXplZAAAAAAUY3VycmVudEFzc2V0SW5kZXhLZXkCAAAALyVzJXNfX2NvbW1vbkNvbmZpZ19fcHJlZGVmaW5lZEFzc2V0c0FjdGl2ZUluZGV4AAAAABRhc3NldHNBZGRyZXNzTGlzdEtleQIAAAAoJXMlc19fY29tbW9uQ29uZmlnX19wcmVkZWZpbmVkQXNzZXRzTGlzdAAAAAAOZGVidFRva2VuSWRLZXkCAAAAHyVzJXNfX2NvbW1vbkNvbmZpZ19fZGVidEFzc2V0SWQAAAAAEm5ldXRyaW5vQXNzZXRJZEtleQIAAAARbmV1dHJpbm9fYXNzZXRfaWQAAAAADm5zYnRBc3NldElkS2V5AgAAAA1ib25kX2Fzc2V0X2lkAAAAAA5kZWZvQXNzZXRJZEtleQIAAAAPJXNfX2RlZm9Bc3NldElkAAAAAA1hc3NldFByaWNlS2V5AgAAAAphc3NldFByaWNlAAAAABVzZXRBc3NldFNjcmlwdFR4SWRLZXkCAAAAEyVzX19hc3NldFNjcmlwdFR4SWQBAAAAEWdldEFzc2V0Q29uZmlnS2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAxhc3NldEFkZHJlc3MCAAAACF9fY29uZmlnAQAAABVnZXRBc3NldEluaXRIZWlnaHRLZXkAAAABAAAADGFzc2V0QWRkcmVzcwkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAADGFzc2V0QWRkcmVzcwIAAAAMX19pbml0SGVpZ2h0AQAAABlnZXRBc3NldEFjdGl2YXRlSGVpZ2h0S2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAxhc3NldEFkZHJlc3MCAAAAEF9fYWN0aXZhdGVIZWlnaHQBAAAAHWdldEFzc2V0Q3VycnJlbnRQb29sQW1vdW50S2V5AAAAAQAAAAxhc3NldEFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fBQAAAAxhc3NldEFkZHJlc3MCAAAADV9fY3VycmVudFBvb2wBAAAAGGdldEFzc2V0TWF4UG9vbEFtb3VudEtleQAAAAEAAAAMYXNzZXRBZGRyZXNzCQABLAAAAAIJAAEsAAAAAgIAAAATJXMlcyVzX19kZWZvQXNzZXRfXwUAAAAMYXNzZXRBZGRyZXNzAgAAAAlfX21heFBvb2wBAAAAD2dldEFzc2V0TWV0YUtleQAAAAEAAAAMYXNzZXRBZGRyZXNzCQABLAAAAAIJAAEsAAAAAgIAAAATJXMlcyVzX19kZWZvQXNzZXRfXwUAAAAMYXNzZXRBZGRyZXNzAgAAAAZfX21ldGEBAAAAGGdldEFzc2V0QWRkcmVzc0J5Q29kZUtleQAAAAEAAAAJYXNzZXRDb2RlCQABLAAAAAIJAAEsAAAAAgIAAAATJXMlcyVzX19kZWZvQXNzZXRfXwUAAAAJYXNzZXRDb2RlAgAAABRfX2FkZHJlc3NCeUFzc2V0Q29kZQEAAAAbZ2V0QXNzZXRBZGRyZXNzQnlBc3NldElkS2V5AAAAAQAAAAdhc3NldElkCQABLAAAAAIJAAEsAAAAAgIAAAATJXMlcyVzX19kZWZvQXNzZXRfXwUAAAAHYXNzZXRJZAIAAAASX19hZGRyZXNzQnlBc3NldElkAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50S2V5AAAAAgAAAAxhc3NldEFkZHJlc3MAAAAQcG9vbE1ha2VyQWRkcmVzcwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACCVzJXMlcyVzBQAAAAlTRVBBUkFUT1ICAAAABHBvb2wFAAAACVNFUEFSQVRPUgUAAAAMYXNzZXRBZGRyZXNzBQAAAAlTRVBBUkFUT1IFAAAAEHBvb2xNYWtlckFkZHJlc3MFAAAACVNFUEFSQVRPUgIAAAAGYW1vdW50AQAAACVnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uTWF4QW1vdW50S2V5AAAAAgAAAAxhc3NldEFkZHJlc3MAAAAQcG9vbE1ha2VyQWRkcmVzcwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACCVzJXMlcyVzBQAAAAlTRVBBUkFUT1ICAAAABHBvb2wFAAAACVNFUEFSQVRPUgUAAAAMYXNzZXRBZGRyZXNzBQAAAAlTRVBBUkFUT1IFAAAAEHBvb2xNYWtlckFkZHJlc3MFAAAACVNFUEFSQVRPUgIAAAAJbWF4QW1vdW50AQAAABtnZXRQb29sTWFrZXJMb2NrZWRBbW91bnRLZXkAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIJXMlcyVzJXMFAAAACVNFUEFSQVRPUgIAAAAEcG9vbAUAAAAJU0VQQVJBVE9SBQAAAAxhc3NldEFkZHJlc3MFAAAACVNFUEFSQVRPUgUAAAAQcG9vbE1ha2VyQWRkcmVzcwUAAAAJU0VQQVJBVE9SAgAAAAxsb2NrZWRBbW91bnQBAAAAG2dldFBvb2xNYWtlclVubG9ja0hlaWdodEtleQAAAAIAAAAMYXNzZXRBZGRyZXNzAAAAEHBvb2xNYWtlckFkZHJlc3MJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAglcyVzJXMlcwUAAAAJU0VQQVJBVE9SAgAAAARwb29sBQAAAAlTRVBBUkFUT1IFAAAADGFzc2V0QWRkcmVzcwUAAAAJU0VQQVJBVE9SBQAAABBwb29sTWFrZXJBZGRyZXNzBQAAAAlTRVBBUkFUT1ICAAAADHVubG9ja0hlaWdodAEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEAAAAMYXNzZXRBZGRyZXNzCQEAAAAWY29udmVydEpzb25BcnJheVRvTGlzdAAAAAIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkBAAAAGGdldFN0cmluZ0J5QWRkcmVzc0FuZEtleQAAAAIFAAAABHRoaXMJAQAAABFnZXRBc3NldENvbmZpZ0tleQAAAAEFAAAADGFzc2V0QWRkcmVzcwkAASwAAAACCQABLAAAAAICAAAADk5vIERFRk8gQXNzZXQgBQAAAAxhc3NldEFkZHJlc3MCAAAADmNvbmZpZyBwcmVzZW50BQAAAAlTRVBBUkFUT1IAAAAAEG5ldXRyaW5vQ29udHJhY3QJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAABpuZXV0cmlub0NvbnRyYWN0QWRkcmVzc0tleQIAAAAfTm8gbmV1dHJpbm8gY29udHJhY3Qgc3BlY2lmaWVkLgAAAAAPbmV1dHJpbm9Bc3NldElkCQACWQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAABBuZXV0cmlub0NvbnRyYWN0BQAAABJuZXV0cmlub0Fzc2V0SWRLZXkCAAAAF05vIFVTRE4gYXNzZXQgaWQgZm91bmQuAAAAAAtuc2J0QXNzZXRJZAkAAlkAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAQbmV1dHJpbm9Db250cmFjdAUAAAAObnNidEFzc2V0SWRLZXkCAAAAFk5vIE5TQlQgYXNzZXQgaWQgZm91bmQAAAAAEm1pbmltdW1Qb29sRnVuZGluZwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAG21pbmltdW5Qb29sRnVuZGluZ0Ftb3VudEtleQIAAAAtTWluaW11bSBwb29sIGZ1bmRpbmcgYW1vdW50IGlzIG5vdCBzcGVjaWZpZWQuAAAAAAthc3NldFN0YXR1cwkABRUAAAADAgAAAAhQUk9QT1NFRAIAAAAFUkVBRFkCAAAABklTU1VFRAAAAAAYcHJlZGVmaW5lZEFzc2V0Q29udHJhY3RzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAAUYXNzZXRzQWRkcmVzc0xpc3RLZXkCAAAALU5vIHBvb2wgb2YgcHJlZGVwbG95ZWQgYXNzZXQgY29udHJhY3RzIGZvdW5kLgAAAAAUcHJlZGVmaW5lZEFzc2V0c0xpc3QJAQAAABZjb252ZXJ0SnNvbkFycmF5VG9MaXN0AAAAAgUAAAAYcHJlZGVmaW5lZEFzc2V0Q29udHJhY3RzAgAAAAEsAAAAABFjdXJyZW50QXNzZXRJbmRleAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAABRjdXJyZW50QXNzZXRJbmRleEtleQAAAAAAAAAAAAAAAAAJZGVidFRva2VuCQACWQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAAA5kZWJ0VG9rZW5JZEtleQIAAAATTm8gZGVidCB0b2tlbiBmb3VuZAAAAAANbXVsdGlwbGljYXRvcgAAAAAAAA9CQAAAAAAWZGVidFRva2VuUmVpc3N1ZUFtb3VudAkAAGgAAAACAAAAAAAAmJaABQAAAA1tdWx0aXBsaWNhdG9yAQAAABVnZXRBc3NldEFkZHJlc3NCeUNvZGUAAAABAAAAC2Fzc2V0U3ltYm9sCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMJAQAAABhnZXRBc3NldEFkZHJlc3NCeUNvZGVLZXkAAAABBQAAAAthc3NldFN5bWJvbAIAAAAAAQAAAAxnZXRBc3NldENvZGUAAAABAAAAC2Fzc2V0Q29uZmlnCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAAAxrZXlBc3NldENvZGUBAAAACmdldEFzc2V0SUQAAAABAAAAC2Fzc2V0Q29uZmlnCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAAAprZXlBc3NldElkAQAAAA5nZXRBc3NldFN0YXR1cwAAAAEAAAALYXNzZXRDb25maWcJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAADmtleUFzc2V0U3RhdHVzAQAAABVnZXRBc3NldFByaWNlRGVjaW1hbHMAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAFWtleUFzc2V0UHJpY2VEZWNpbWFscwEAAAAVZ2V0QXNzZXRCYWtpbmdBc3NldElkAAAAAQAAAAthc3NldENvbmZpZwkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAATa2V5QXNzZXRCYWtpbmdBc3NldAEAAAAdZ2V0QXNzZXRPdmVyQ29sbGF0ZXJhbFBlcmNlbnQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAG2tleU92ZXJjb2xsYXRlcmFsUGVyY2VudGFnZQEAAAAdZ2V0QXNzZXRNaW5SZXF1aXJlZFBvb2xBbW91bnQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAACmtleU1pblBvb2wBAAAAGmdldEFzc2V0UHJpY2VPcmFjbGVBZGRyZXNzAAAAAQAAAAthc3NldENvbmZpZwkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAAVa2V5UHJpY2VPcmFjbGVBZGRyZXNzAQAAABhnZXRNaW5CdXlQYXltZW50UGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAEGtleU1pbkJ1eVBheW1lbnQBAAAAGWdldE1pblNlbGxQYXltZW50UGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAEWtleU1pblNlbGxQYXltZW50AQAAABpnZXRCdXlMb2NrSW50ZXJ2YWxQZXJBc3NldAAAAAEAAAALYXNzZXRDb25maWcJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAASa2V5QnV5TG9ja0ludGVydmFsAQAAABtnZXRTZWxsTG9ja0ludGVydmFsUGVyQXNzZXQAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAE2tleVNlbGxMb2NrSW50ZXJ2YWwBAAAAEWdldEJ1eUZlZVBlckFzc2V0AAAAAQAAAAthc3NldENvbmZpZwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAC2Fzc2V0Q29uZmlnBQAAAAlrZXlCdXlGZWUBAAAAEmdldFNlbGxGZWVQZXJBc3NldAAAAAEAAAALYXNzZXRDb25maWcJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAthc3NldENvbmZpZwUAAAAKa2V5U2VsbEZlZQEAAAAaZ2V0UmVkZW1wdGlvblRpbWVvdXRCbG9ja3MAAAABAAAAC2Fzc2V0Q29uZmlnCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAALYXNzZXRDb25maWcFAAAAGGtleVBvb2xSZWRlbXB0aW9uVGltZW91dAEAAAASZ2V0QXNzZXRJbml0SGVpZ2h0AAAAAQAAAAxhc3NldEFkZHJlc3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAFWdldEFzc2V0SW5pdEhlaWdodEtleQAAAAEFAAAADGFzc2V0QWRkcmVzcwAAAAAAAAAAAAEAAAAWZ2V0QXNzZXRBY3RpdmF0ZUhlaWdodAAAAAEAAAAMYXNzZXRBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABlnZXRBc3NldEFjdGl2YXRlSGVpZ2h0S2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzAAAAAAAAAAAAAQAAABlnZXRBc3NldEN1cnJlbnRQb29sQW1vdW50AAAAAQAAAAxhc3NldEFkZHJlc3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAHWdldEFzc2V0Q3VycnJlbnRQb29sQW1vdW50S2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzAAAAAAAAAAAAAQAAABVnZXRBc3NldE1heFBvb2xBbW91bnQAAAABAAAADGFzc2V0QWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAYZ2V0QXNzZXRNYXhQb29sQW1vdW50S2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzAAAAAAAAAAAAAQAAAAxnZXRBc3NldE1ldGEAAAABAAAADGFzc2V0QWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACBQAAAAR0aGlzCQEAAAAPZ2V0QXNzZXRNZXRhS2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzAgAAAAABAAAAH2dldFBvb2xNYWtlclBhcnRpY2lwYXRpb25BbW91bnQAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50S2V5AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAABBwb29sTWFrZXJBZGRyZXNzAAAAAAAAAAAAAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uTWF4QW1vdW50AAAAAgAAAAxhc3NldEFkZHJlc3MAAAAQcG9vbE1ha2VyQWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAlZ2V0UG9vbE1ha2VyUGFydGljaXBhdGlvbk1heEFtb3VudEtleQAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAAQcG9vbE1ha2VyQWRkcmVzcwAAAAAAAAAAAAEAAAAYZ2V0UG9vbE1ha2VyTG9ja2VkQW1vdW50AAAAAgAAAAxhc3NldEFkZHJlc3MAAAAQcG9vbE1ha2VyQWRkcmVzcwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzCQEAAAAbZ2V0UG9vbE1ha2VyTG9ja2VkQW1vdW50S2V5AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAABBwb29sTWFrZXJBZGRyZXNzAAAAAAAAAAAAAQAAABhnZXRQb29sTWFrZXJVbmxvY2tIZWlnaHQAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABtnZXRQb29sTWFrZXJVbmxvY2tIZWlnaHRLZXkAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAAEHBvb2xNYWtlckFkZHJlc3MAAAAAAAAAAAABAAAADWdldEFzc2V0UHJpY2UAAAABAAAAEnByaWNlT3JhY2xlQWRkcmVzcwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAAEnByaWNlT3JhY2xlQWRkcmVzcwUAAAANYXNzZXRQcmljZUtleQIAAAAUTm8gQXNzZXQgcHJpY2UgZm91bmQBAAAAH2NvbXBvc2VBc3NldENvbmZpZ3VyYXRpb25TdHJpbmcAAAAPAAAACWFzc2V0Q29kZQAAAAdhc3NldElkAAAAC2Fzc2V0U3RhdHVzAAAADXByaWNlRGVjaW1hbHMAAAAOYmFja2luZ0Fzc2V0SWQAAAAVb3ZlckNvbGxhdGVyYWxQZXJjZW50AAAAB21pblBvb2wAAAAScHJpY2VPcmFjbGVBZGRyZXNzAAAADW1pbkJ1eVBheW1lbnQAAAAObWluU2VsbFBheW1lbnQAAAAPYnV5TG9ja0ludGVydmFsAAAAEHNlbGxMb2NrSW50ZXJ2YWwAAAAGYnV5RmVlAAAAB3NlbGxGZWUAAAAVcG9vbFJlZGVtcHRpb25UaW1lb3V0CQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAB4lcyVzJXMlZCVzJWQlZCVzJWQlZCVkJWQlZCVkJWQFAAAACVNFUEFSQVRPUgUAAAAJYXNzZXRDb2RlBQAAAAlTRVBBUkFUT1IFAAAAB2Fzc2V0SWQFAAAACVNFUEFSQVRPUgUAAAALYXNzZXRTdGF0dXMFAAAACVNFUEFSQVRPUgkAAaQAAAABBQAAAA1wcmljZURlY2ltYWxzBQAAAAlTRVBBUkFUT1IFAAAADmJhY2tpbmdBc3NldElkBQAAAAlTRVBBUkFUT1IJAAGkAAAAAQUAAAAVb3ZlckNvbGxhdGVyYWxQZXJjZW50BQAAAAlTRVBBUkFUT1IJAAGkAAAAAQUAAAAHbWluUG9vbAUAAAAJU0VQQVJBVE9SBQAAABJwcmljZU9yYWNsZUFkZHJlc3MFAAAACVNFUEFSQVRPUgkAAaQAAAABBQAAAA1taW5CdXlQYXltZW50BQAAAAlTRVBBUkFUT1IJAAGkAAAAAQUAAAAObWluU2VsbFBheW1lbnQFAAAACVNFUEFSQVRPUgkAAaQAAAABBQAAAA9idXlMb2NrSW50ZXJ2YWwFAAAACVNFUEFSQVRPUgkAAaQAAAABBQAAABBzZWxsTG9ja0ludGVydmFsBQAAAAlTRVBBUkFUT1IJAAGkAAAAAQUAAAAGYnV5RmVlBQAAAAlTRVBBUkFUT1IJAAGkAAAAAQUAAAAHc2VsbEZlZQUAAAAJU0VQQVJBVE9SCQABpAAAAAEFAAAAFXBvb2xSZWRlbXB0aW9uVGltZW91dAAAAAYAAAABaQEAAAAEaW5pdAAAAAQAAAAXbmV1dHJpbm9Db250cmFjdEFkZHJlc3MAAAAYbWluaW11blBvb2xGdW5kaW5nQW1vdW50AAAAE3ByZWRlZmluZWRBc3NldExpc3QAAAARY3VycmVudEFzc2V0SW5kZXgDCQEAAAACIT0AAAACCQACWAAAAAEIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQUAAAAOYWRtaW5QdWJsaWNLZXkJAAACAAAAAQIAAAAqT25seSBBZG1pbiBjYW4gcGVyZm9ybSBjb250cmFjdCBvcGVyYXRpb24uAwkAAAAAAAACCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQUAAAAQaXNJbml0aWFsaXplZEtleQYJAAACAAAAAQIAAAAhQ29udHJhY3Qgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQuBAAAAAlpc3N1ZURlYnQJAARCAAAABQIAAAAJREVGT19ERUJUAgAAABBERUZPIERlYnQgVG9rZW4uAAAAAAAAAAABAAAAAAAAAAAGBgQAAAALZGVidFRva2VuSWQJAAQ4AAAAAQUAAAAJaXNzdWVEZWJ0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAGm5ldXRyaW5vQ29udHJhY3RBZGRyZXNzS2V5BQAAABduZXV0cmlub0NvbnRyYWN0QWRkcmVzcwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAbbWluaW11blBvb2xGdW5kaW5nQW1vdW50S2V5BQAAABhtaW5pbXVuUG9vbEZ1bmRpbmdBbW91bnQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAUYXNzZXRzQWRkcmVzc0xpc3RLZXkFAAAAE3ByZWRlZmluZWRBc3NldExpc3QJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFGN1cnJlbnRBc3NldEluZGV4S2V5BQAAABFjdXJyZW50QXNzZXRJbmRleAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA5kZWJ0VG9rZW5JZEtleQkAAlgAAAABBQAAAAtkZWJ0VG9rZW5JZAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAQaXNJbml0aWFsaXplZEtleQYJAARMAAAAAgUAAAAJaXNzdWVEZWJ0CQAETAAAAAIJAQAAAARCdXJuAAAAAgUAAAALZGVidFRva2VuSWQAAAAAAAAAAAEFAAAAA25pbAAAAAFpAQAAAAxwcm9wb3NlQXNzZXQAAAAOAAAACWFzc2V0Q29kZQAAAARtZXRhAAAAB21pblBvb2wAAAAScHJpY2VPcmFjbGVBZGRyZXNzAAAAFW92ZXJDb2xsYXRlcmFsUGVyY2VudAAAAA5iYWNraW5nQXNzZXRJZAAAAA1wcmljZURlY2ltYWxzAAAADW1pbkJ1eVBheW1lbnQAAAAObWluU2VsbFBheW1lbnQAAAAPYnV5TG9ja0ludGVydmFsAAAAEHNlbGxMb2NrSW50ZXJ2YWwAAAAGYnV5RmVlAAAAB3NlbGxGZWUAAAAVcG9vbFJlZGVtcHRpb25UaW1lb3V0AwkBAAAAAiE9AAAAAgkAAlgAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmFkbWluUHVibGljS2V5CQAAAgAAAAECAAAAKk9ubHkgQWRtaW4gY2FuIHBlcmZvcm0gY29udHJhY3Qgb3BlcmF0aW9uLgMJAAAAAAAAAgkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAAEGlzSW5pdGlhbGl6ZWRLZXkHCQAAAgAAAAECAAAAGkNvbnRyYWN0IGlzIG5vdCB5ZXQgcmVhZHkuAwkBAAAAAiE9AAAAAgkAAlkAAAABBQAAAA5iYWNraW5nQXNzZXRJZAUAAAAPbmV1dHJpbm9Bc3NldElkCQAAAgAAAAECAAAAI0Jha2luZyBhc3NldCBpZCBjb3VsZCBiZSBVU0ROIG9ubHkuAwkBAAAAAiE9AAAAAgkBAAAAFWdldEFzc2V0QWRkcmVzc0J5Q29kZQAAAAEFAAAACWFzc2V0Q29kZQIAAAAACQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAABdBc3NldCB3aXRoIHBhc3NlZCBjb2RlIAUAAAAJYXNzZXRDb2RlAgAAABsgaGFzIGFscmVhZHkgYmVlbiBwcm9wb3NlZC4DCQAAZgAAAAIFAAAAEm1pbmltdW1Qb29sRnVuZGluZwUAAAAHbWluUG9vbAkAAAIAAAABCQABLAAAAAICAAAAM01pbmltdW0gcG9vbCBhbW91bnQgc2hvdWxkIGJlIGdyZWF0ZXIgb3IgZXF1YWxzIHRvIAkAAaQAAAABBQAAABJtaW5pbXVtUG9vbEZ1bmRpbmcDAwMDAwMDAwkAAGYAAAACAAAAAAAAAAAABQAAABVvdmVyQ29sbGF0ZXJhbFBlcmNlbnQGCQEAAAACIT0AAAACBQAAAA1wcmljZURlY2ltYWxzAAAAAAAAD0JABgkAAGYAAAACAAAAAAAAAAAABQAAAA1taW5CdXlQYXltZW50BgkAAGYAAAACAAAAAAAAAAAABQAAAA5taW5TZWxsUGF5bWVudAYJAABmAAAAAgAAAAAAAAAAAAUAAAAPYnV5TG9ja0ludGVydmFsBgkAAGYAAAACAAAAAAAAAAAABQAAABBzZWxsTG9ja0ludGVydmFsBgkAAGYAAAACAAAAAAAAAAAABQAAAAZidXlGZWUGCQAAZgAAAAIAAAAAAAAAAAAFAAAAB3NlbGxGZWUJAAACAAAAAQIAAAAoT25lIG9mIHRoZSBwYXNzZWQgcGFyYW1ldGVycyBpcyBpbnZhbGlkLgQAAAAXcHJpY2VPcmFjbGVBZGRyZXNzVmFsaWQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAScHJpY2VPcmFjbGVBZGRyZXNzAgAAAClQYXNzZWQgUHJpY2UgT3JhY2xlIEFkZHJlc3MgaXMgbm90IHZhbGlkLgQAAAAMYXNzZXRBZGRyZXNzCQABkQAAAAIFAAAAFHByZWRlZmluZWRBc3NldHNMaXN0BQAAABFjdXJyZW50QXNzZXRJbmRleAQAAAALZGVmb0Fzc2V0SWQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQmAAAAAQUAAAAMYXNzZXRBZGRyZXNzAgAAAAAFAAAADmRlZm9Bc3NldElkS2V5AgAAABdObyBkZWZvIGFzc2V0IElEIGZvdW5kLgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAARZ2V0QXNzZXRDb25maWdLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MJAQAAAB9jb21wb3NlQXNzZXRDb25maWd1cmF0aW9uU3RyaW5nAAAADwUAAAAJYXNzZXRDb2RlBQAAAAtkZWZvQXNzZXRJZAgFAAAAC2Fzc2V0U3RhdHVzAAAAAl8xBQAAAA1wcmljZURlY2ltYWxzBQAAAA5iYWNraW5nQXNzZXRJZAUAAAAVb3ZlckNvbGxhdGVyYWxQZXJjZW50BQAAAAdtaW5Qb29sBQAAABJwcmljZU9yYWNsZUFkZHJlc3MFAAAADW1pbkJ1eVBheW1lbnQFAAAADm1pblNlbGxQYXltZW50BQAAAA9idXlMb2NrSW50ZXJ2YWwFAAAAEHNlbGxMb2NrSW50ZXJ2YWwFAAAABmJ1eUZlZQUAAAAHc2VsbEZlZQUAAAAVcG9vbFJlZGVtcHRpb25UaW1lb3V0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABhnZXRBc3NldEFkZHJlc3NCeUNvZGVLZXkAAAABBQAAAAlhc3NldENvZGUFAAAADGFzc2V0QWRkcmVzcwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPZ2V0QXNzZXRNZXRhS2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzBQAAAARtZXRhCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAVZ2V0QXNzZXRJbml0SGVpZ2h0S2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzBQAAAAZoZWlnaHQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFGN1cnJlbnRBc3NldEluZGV4S2V5CQAAZAAAAAIFAAAAEWN1cnJlbnRBc3NldEluZGV4AAAAAAAAAAABCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABtnZXRBc3NldEFkZHJlc3NCeUFzc2V0SWRLZXkAAAABBQAAAAtkZWZvQXNzZXRJZAUAAAAMYXNzZXRBZGRyZXNzBQAAAANuaWwAAAABaQEAAAARZnVuZExpcXVpZGl0eVBvb2wAAAABAAAACWFzc2V0Q29kZQQAAAAMYXNzZXRBZGRyZXNzCQEAAAAVZ2V0QXNzZXRBZGRyZXNzQnlDb2RlAAAAAQUAAAAJYXNzZXRDb2RlBAAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEFAAAADGFzc2V0QWRkcmVzcwQAAAAPYXR0YWNoZWRQYXltZW50CQEAAAAFdmFsdWUAAAABCQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAwkBAAAAAiE9AAAAAgkAAlgAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmFkbWluUHVibGljS2V5CQAAAgAAAAECAAAAKk9ubHkgQWRtaW4gY2FuIHBlcmZvcm0gY29udHJhY3Qgb3BlcmF0aW9uLgMJAAAAAAAAAgkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAAEGlzSW5pdGlhbGl6ZWRLZXkHCQAAAgAAAAECAAAAGkNvbnRyYWN0IGlzIG5vdCB5ZXQgcmVhZHkuAwkBAAAAAiE9AAAAAggFAAAAD2F0dGFjaGVkUGF5bWVudAAAAAdhc3NldElkBQAAAA9uZXV0cmlub0Fzc2V0SWQJAAACAAAAAQIAAAAuTGlxdWlkaXR5IHBvb2wgY291bGQgYmUgZnVuZGVkIHdpdGggVVNETiBvbmx5LgMJAAAAAAAAAggFAAAAD2F0dGFjaGVkUGF5bWVudAAAAAZhbW91bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAiSW5jb3JyZWN0IGF0dGFjaGVkIHBheW1lbnQgYW1vdW50LgMJAAAAAAAAAgUAAAAMYXNzZXRBZGRyZXNzAgAAAAAJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAJUNhbm5vdCBmaW5kIGxpcXVpZGl0eSBwb29sIGZvciBhc3NldCAFAAAACWFzc2V0Q29kZQIAAAABLgQAAAAPZmluYWxQb29sQW1vdW50CQAAZAAAAAIIBQAAAA9hdHRhY2hlZFBheW1lbnQAAAAGYW1vdW50CQEAAAAZZ2V0QXNzZXRDdXJyZW50UG9vbEFtb3VudAAAAAEFAAAADGFzc2V0QWRkcmVzcwQAAAANbWF4UG9vbEFtb3VudAkBAAAAFWdldEFzc2V0TWF4UG9vbEFtb3VudAAAAAEFAAAADGFzc2V0QWRkcmVzcwQAAAAXY3VycmVudFBvb2xNYWtlckJhbGFuY2UJAQAAAB9nZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50AAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAATbWF4UG9vbE1ha2VyQmFsYW5jZQkBAAAAImdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25NYXhBbW91bnQAAAACBQAAAAxhc3NldEFkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAABFjdXJyZW50UG9vbFN0YXR1cwkBAAAADmdldEFzc2V0U3RhdHVzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAPZmluYWxQb29sU3RhdHVzAwMJAABnAAAAAgUAAAAPZmluYWxQb29sQW1vdW50CQEAAAAdZ2V0QXNzZXRNaW5SZXF1aXJlZFBvb2xBbW91bnQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQAAAAAAAAIFAAAAEWN1cnJlbnRQb29sU3RhdHVzCAUAAAALYXNzZXRTdGF0dXMAAAACXzEHCAUAAAALYXNzZXRTdGF0dXMAAAACXzIFAAAAEWN1cnJlbnRQb29sU3RhdHVzBAAAAAVhQ29kZQkBAAAADGdldEFzc2V0Q29kZQAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAA2FJRAkBAAAACmdldEFzc2V0SUQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAA5hUHJpY2VEZWNpbWFscwkBAAAAFWdldEFzc2V0UHJpY2VEZWNpbWFscwAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAADmFCYWtpbmdBc3NldElkCQEAAAAVZ2V0QXNzZXRCYWtpbmdBc3NldElkAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAWYU92ZXJDb2xsYXRlcmFsUGVyY2VudAkBAAAAHWdldEFzc2V0T3ZlckNvbGxhdGVyYWxQZXJjZW50AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAQYU1pblJlcXVpcmVkUG9vbAkBAAAAHWdldEFzc2V0TWluUmVxdWlyZWRQb29sQW1vdW50AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAATYVByaWNlT3JhY2xlQWRkcmVzcwkBAAAAGmdldEFzc2V0UHJpY2VPcmFjbGVBZGRyZXNzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAOYU1pbkJ1eVBheW1lbnQJAQAAABhnZXRNaW5CdXlQYXltZW50UGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAA9hTWluU2VsbFBheW1lbnQJAQAAABlnZXRNaW5TZWxsUGF5bWVudFBlckFzc2V0AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAQYUJ1eUxvY2tJbnRlcnZhbAkBAAAAGmdldEJ1eUxvY2tJbnRlcnZhbFBlckFzc2V0AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAARYVNlbGxMb2NrSW50ZXJ2YWwJAQAAABtnZXRTZWxsTG9ja0ludGVydmFsUGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAAdhQnV5RmVlCQEAAAARZ2V0QnV5RmVlUGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAAhhU2VsbEZlZQkBAAAAEmdldFNlbGxGZWVQZXJBc3NldAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAGGFSZWRlbXB0aW9uVGltZW91dEJsb2NrcwkBAAAAGmdldFJlZGVtcHRpb25UaW1lb3V0QmxvY2tzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAATbmV3UG9vbE1ha2VyQmFsYW5jZQkAAGQAAAACBQAAABdjdXJyZW50UG9vbE1ha2VyQmFsYW5jZQgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BAAAAAZyZXN1bHQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50S2V5AAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgUAAAATbmV3UG9vbE1ha2VyQmFsYW5jZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAJWdldFBvb2xNYWtlclBhcnRpY2lwYXRpb25NYXhBbW91bnRLZXkAAAACBQAAAAxhc3NldEFkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyAwkAAGYAAAACBQAAABNuZXdQb29sTWFrZXJCYWxhbmNlBQAAABNtYXhQb29sTWFrZXJCYWxhbmNlBQAAABNuZXdQb29sTWFrZXJCYWxhbmNlBQAAABNtYXhQb29sTWFrZXJCYWxhbmNlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAdZ2V0QXNzZXRDdXJycmVudFBvb2xBbW91bnRLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MFAAAAD2ZpbmFsUG9vbEFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAGGdldEFzc2V0TWF4UG9vbEFtb3VudEtleQAAAAEFAAAADGFzc2V0QWRkcmVzcwMJAABmAAAAAgUAAAAPZmluYWxQb29sQW1vdW50BQAAAA1tYXhQb29sQW1vdW50BQAAAA9maW5hbFBvb2xBbW91bnQFAAAADW1heFBvb2xBbW91bnQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAAEWdldEFzc2V0Q29uZmlnS2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABFnZXRBc3NldENvbmZpZ0tleQAAAAEFAAAADGFzc2V0QWRkcmVzcwkBAAAAH2NvbXBvc2VBc3NldENvbmZpZ3VyYXRpb25TdHJpbmcAAAAPBQAAAAVhQ29kZQUAAAADYUlEBQAAAA9maW5hbFBvb2xTdGF0dXMFAAAADmFQcmljZURlY2ltYWxzBQAAAA5hQmFraW5nQXNzZXRJZAUAAAAWYU92ZXJDb2xsYXRlcmFsUGVyY2VudAUAAAAQYU1pblJlcXVpcmVkUG9vbAUAAAATYVByaWNlT3JhY2xlQWRkcmVzcwUAAAAOYU1pbkJ1eVBheW1lbnQFAAAAD2FNaW5TZWxsUGF5bWVudAUAAAAQYUJ1eUxvY2tJbnRlcnZhbAUAAAARYVNlbGxMb2NrSW50ZXJ2YWwFAAAAB2FCdXlGZWUFAAAACGFTZWxsRmVlBQAAABhhUmVkZW1wdGlvblRpbWVvdXRCbG9ja3MFAAAAA25pbAMJAAAAAAAAAgUAAAARY3VycmVudFBvb2xTdGF0dXMIBQAAAAthc3NldFN0YXR1cwAAAAJfMwkABE0AAAACBQAAAAZyZXN1bHQJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAADGFzc2V0QWRkcmVzcwgFAAAAD2F0dGFjaGVkUGF5bWVudAAAAAZhbW91bnQFAAAAD25ldXRyaW5vQXNzZXRJZAUAAAAGcmVzdWx0AAAAAWkBAAAADWFjdGl2YXRlQXNzZXQAAAABAAAACWFzc2V0Q29kZQQAAAAMYXNzZXRBZGRyZXNzCQEAAAAVZ2V0QXNzZXRBZGRyZXNzQnlDb2RlAAAAAQUAAAAJYXNzZXRDb2RlBAAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEFAAAADGFzc2V0QWRkcmVzcwQAAAAWY3VycmVudEFzc2V0UG9vbEFtb3VudAkBAAAAGWdldEFzc2V0Q3VycmVudFBvb2xBbW91bnQAAAABBQAAAAxhc3NldEFkZHJlc3MEAAAABWFDb2RlCQEAAAAMZ2V0QXNzZXRDb2RlAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAOYUN1cnJlbnRTdGF0dXMJAQAAAA5nZXRBc3NldFN0YXR1cwAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAA2FJRAkBAAAACmdldEFzc2V0SUQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAA5hUHJpY2VEZWNpbWFscwkBAAAAFWdldEFzc2V0UHJpY2VEZWNpbWFscwAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAADmFCYWtpbmdBc3NldElkCQEAAAAVZ2V0QXNzZXRCYWtpbmdBc3NldElkAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAWYU92ZXJDb2xsYXRlcmFsUGVyY2VudAkBAAAAHWdldEFzc2V0T3ZlckNvbGxhdGVyYWxQZXJjZW50AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAQYU1pblJlcXVpcmVkUG9vbAkBAAAAHWdldEFzc2V0TWluUmVxdWlyZWRQb29sQW1vdW50AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAATYVByaWNlT3JhY2xlQWRkcmVzcwkBAAAAGmdldEFzc2V0UHJpY2VPcmFjbGVBZGRyZXNzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAOYU1pbkJ1eVBheW1lbnQJAQAAABhnZXRNaW5CdXlQYXltZW50UGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAA9hTWluU2VsbFBheW1lbnQJAQAAABlnZXRNaW5TZWxsUGF5bWVudFBlckFzc2V0AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAAQYUJ1eUxvY2tJbnRlcnZhbAkBAAAAGmdldEJ1eUxvY2tJbnRlcnZhbFBlckFzc2V0AAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAQAAAARYVNlbGxMb2NrSW50ZXJ2YWwJAQAAABtnZXRTZWxsTG9ja0ludGVydmFsUGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAAdhQnV5RmVlCQEAAAARZ2V0QnV5RmVlUGVyQXNzZXQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BAAAAAhhU2VsbEZlZQkBAAAAEmdldFNlbGxGZWVQZXJBc3NldAAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAAGGFSZWRlbXB0aW9uVGltZW91dEJsb2NrcwkBAAAAGmdldFJlZGVtcHRpb25UaW1lb3V0QmxvY2tzAAAAAQUAAAAWYXNzZXRDb25maWd1cmF0aW9uTGlzdAMJAQAAAAIhPQAAAAIJAAJYAAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BQAAAA5hZG1pblB1YmxpY0tleQkAAAIAAAABAgAAACpPbmx5IEFkbWluIGNhbiBwZXJmb3JtIGNvbnRyYWN0IG9wZXJhdGlvbi4DCQAAAAAAAAIJAQAAAAxnZXRCb29sQnlLZXkAAAABBQAAABBpc0luaXRpYWxpemVkS2V5BwkAAAIAAAABAgAAABpDb250cmFjdCBpcyBub3QgeWV0IHJlYWR5LgMJAQAAAAIhPQAAAAIFAAAADmFDdXJyZW50U3RhdHVzCAUAAAALYXNzZXRTdGF0dXMAAAACXzIJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAMEFzc2V0IGlzIG5vdCBpbiBSRUFEWSBzdGF0dXMuIEN1cnJlbnQgc3RhdHVzIGlzIAUAAAAOYUN1cnJlbnRTdGF0dXMCAAAAAS4DCQAAAAAAAAIFAAAADGFzc2V0QWRkcmVzcwIAAAAACQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAABJDYW5ub3QgZmluZCBhc3NldCAFAAAACWFzc2V0Q29kZQIAAAABLgMJAABmAAAAAgUAAAASbWluaW11bVBvb2xGdW5kaW5nBQAAABZjdXJyZW50QXNzZXRQb29sQW1vdW50CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAtQ2Fubm90IGlzc3VlIGFzc2V0IGFzIGxpcXVpZGl0eSBwb29sIGFtb3VudCAoCQABpAAAAAEFAAAAFmN1cnJlbnRBc3NldFBvb2xBbW91bnQCAAAAGSkgaXMgbGVzcyB0aGFuIHJlcXVpcmVkICgJAAGkAAAAAQUAAAASbWluaW11bVBvb2xGdW5kaW5nAgAAAAEpBAAAAAlpc3N1ZURlYnQJAQAAAAdSZWlzc3VlAAAAAwUAAAAJZGVidFRva2VuBQAAABZkZWJ0VG9rZW5SZWlzc3VlQW1vdW50BgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAGWdldEFzc2V0QWN0aXZhdGVIZWlnaHRLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MFAAAABmhlaWdodAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAARZ2V0QXNzZXRDb25maWdLZXkAAAABBQAAAAxhc3NldEFkZHJlc3MJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEWdldEFzc2V0Q29uZmlnS2V5AAAAAQUAAAAMYXNzZXRBZGRyZXNzCQEAAAAfY29tcG9zZUFzc2V0Q29uZmlndXJhdGlvblN0cmluZwAAAA8FAAAABWFDb2RlBQAAAANhSUQIBQAAAAthc3NldFN0YXR1cwAAAAJfMwUAAAAOYVByaWNlRGVjaW1hbHMFAAAADmFCYWtpbmdBc3NldElkBQAAABZhT3ZlckNvbGxhdGVyYWxQZXJjZW50BQAAABBhTWluUmVxdWlyZWRQb29sBQAAABNhUHJpY2VPcmFjbGVBZGRyZXNzBQAAAA5hTWluQnV5UGF5bWVudAUAAAAPYU1pblNlbGxQYXltZW50BQAAABBhQnV5TG9ja0ludGVydmFsBQAAABFhU2VsbExvY2tJbnRlcnZhbAUAAAAHYUJ1eUZlZQUAAAAIYVNlbGxGZWUFAAAAGGFSZWRlbXB0aW9uVGltZW91dEJsb2NrcwkABEwAAAACBQAAAAlpc3N1ZURlYnQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAMYXNzZXRBZGRyZXNzBQAAABZjdXJyZW50QXNzZXRQb29sQW1vdW50BQAAAA9uZXV0cmlub0Fzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAMYXNzZXRBZGRyZXNzBQAAABZkZWJ0VG9rZW5SZWlzc3VlQW1vdW50BQAAAAlkZWJ0VG9rZW4FAAAAA25pbAAAAAFpAQAAAA5yZWRlZW1Gcm9tUG9vbAAAAAIAAAAJYXNzZXRDb2RlAAAABmFtb3VudAQAAAAMYXNzZXRBZGRyZXNzCQEAAAAVZ2V0QXNzZXRBZGRyZXNzQnlDb2RlAAAAAQUAAAAJYXNzZXRDb2RlBAAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEFAAAADGFzc2V0QWRkcmVzcwQAAAANY2FsbGVyQWRkcmVzcwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAAGXRvdGFsQW1vdW50SW5Qb29sQnlDYWxsZXIJAQAAAB9nZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAA1jYWxsZXJBZGRyZXNzBAAAABdsb2NrZWRBbW91bnRCeVBvb2xNYWtlcgkBAAAAGGdldFBvb2xNYWtlckxvY2tlZEFtb3VudAAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAANY2FsbGVyQWRkcmVzcwMJAQAAAAIhPQAAAAIJAAJYAAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BQAAAA5hZG1pblB1YmxpY0tleQkAAAIAAAABAgAAACpPbmx5IEFkbWluIGNhbiBwZXJmb3JtIGNvbnRyYWN0IG9wZXJhdGlvbi4DCQAAAAAAAAIJAQAAAAxnZXRCb29sQnlLZXkAAAABBQAAABBpc0luaXRpYWxpemVkS2V5BwkAAAIAAAABAgAAABpDb250cmFjdCBpcyBub3QgeWV0IHJlYWR5LgMJAAAAAAAAAgUAAAAMYXNzZXRBZGRyZXNzAgAAAAAJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAEkNhbm5vdCBmaW5kIGFzc2V0IAUAAAAJYXNzZXRDb2RlAgAAAAEuAwMDCQAAZgAAAAIAAAAAAAAAAAAFAAAABmFtb3VudAYJAAAAAAAAAgUAAAAZdG90YWxBbW91bnRJblBvb2xCeUNhbGxlcgAAAAAAAAAAAAYJAABmAAAAAgUAAAAGYW1vdW50BQAAABl0b3RhbEFtb3VudEluUG9vbEJ5Q2FsbGVyCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAACJDYW5ub3QgZmluZCBwb29sIG1ha2VyIGJ5IGFkZHJlc3MgBQAAAA1jYWxsZXJBZGRyZXNzAgAAACEgb3IgYW1vdW50IHBhc3NlZCBpcyBub3QgY29ycmVjdC4DCQAAZgAAAAIFAAAAF2xvY2tlZEFtb3VudEJ5UG9vbE1ha2VyAAAAAAAAAAAACQAAAgAAAAECAAAARlBvb2wgbWFrZXIgYWxyZWFkeSBoYXMgaW5pdGlhdGVkIHJlZGVtcHRpb24gdGhhdCBpcyBub3Qgd2l0aGRyYXduIHlldC4JAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABtnZXRQb29sTWFrZXJMb2NrZWRBbW91bnRLZXkAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAADWNhbGxlckFkZHJlc3MFAAAABmFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAG2dldFBvb2xNYWtlclVubG9ja0hlaWdodEtleQAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAANY2FsbGVyQWRkcmVzcwkAAGQAAAACBQAAAAZoZWlnaHQJAQAAABpnZXRSZWRlbXB0aW9uVGltZW91dEJsb2NrcwAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QFAAAAA25pbAAAAAFpAQAAAAh3aXRoZHJhdwAAAAEAAAAJYXNzZXRDb2RlBAAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0CQEAAAATZ2V0QXNzZXRDb25maWdBcnJheQAAAAEFAAAACWFzc2V0Q29kZQQAAAAMYXNzZXRBZGRyZXNzCQEAAAAVZ2V0QXNzZXRBZGRyZXNzQnlDb2RlAAAAAQUAAAAJYXNzZXRDb2RlBAAAABJwcmljZU9yYWNsZUFkZHJlc3MJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABpnZXRBc3NldFByaWNlT3JhY2xlQWRkcmVzcwAAAAEFAAAAFmFzc2V0Q29uZmlndXJhdGlvbkxpc3QEAAAADWNhbGxlckFkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAABJzeW50aGV0aWNBc3NldEluZm8JAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkAA+wAAAABCQACWQAAAAEFAAAADGFzc2V0QWRkcmVzcwkAASwAAAACAgAAABhDYW5ub3QgZmluZCBhc3NldCBieSBpZCAFAAAADGFzc2V0QWRkcmVzcwQAAAAadG90YWxVU0ROQmFsYW5jZU9uQ29udHJhY3QJAAPwAAAAAgUAAAAEdGhpcwUAAAAPbmV1dHJpbm9Bc3NldElkBAAAABx0b3RhbEFtb3VudEluUG9vbEJ5UG9vbE1ha2VyCQEAAAAfZ2V0UG9vbE1ha2VyUGFydGljaXBhdGlvbkFtb3VudAAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAANY2FsbGVyQWRkcmVzcwQAAAAXbG9ja2VkQW1vdW50QnlQb29sTWFrZXIJAQAAABhnZXRQb29sTWFrZXJMb2NrZWRBbW91bnQAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAADWNhbGxlckFkZHJlc3MEAAAAEW1pbldpdGhkcmF3SGVpZ2h0CQEAAAAYZ2V0UG9vbE1ha2VyVW5sb2NrSGVpZ2h0AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAA1jYWxsZXJBZGRyZXNzBAAAABNwb29sTWFrZXRQcm9wb3J0aW9uCQAAaQAAAAIJAQAAABVnZXRBc3NldE1heFBvb2xBbW91bnQAAAABBQAAAAxhc3NldEFkZHJlc3MJAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uTWF4QW1vdW50AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAA1jYWxsZXJBZGRyZXNzAwkBAAAAAiE9AAAAAgkAAlgAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAADmFkbWluUHVibGljS2V5CQAAAgAAAAECAAAAKk9ubHkgQWRtaW4gY2FuIHBlcmZvcm0gY29udHJhY3Qgb3BlcmF0aW9uLgMJAAAAAAAAAgkBAAAADGdldEJvb2xCeUtleQAAAAEFAAAAEGlzSW5pdGlhbGl6ZWRLZXkHCQAAAgAAAAECAAAAGkNvbnRyYWN0IGlzIG5vdCB5ZXQgcmVhZHkuAwkAAAAAAAACCQEAAAAMZ2V0Qm9vbEJ5S2V5AAAAAQUAAAAQaXNJbml0aWFsaXplZEtleQcJAAACAAAAAQIAAAAaQ29udHJhY3QgaXMgbm90IHlldCByZWFkeS4DCQAAAAAAAAIFAAAADGFzc2V0QWRkcmVzcwIAAAAACQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAABJDYW5ub3QgZmluZCBhc3NldCAFAAAACWFzc2V0Q29kZQIAAAABLgMJAAAAAAAAAgUAAAAcdG90YWxBbW91bnRJblBvb2xCeVBvb2xNYWtlcgAAAAAAAAAAAAkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAiQ2Fubm90IGZpbmQgcG9vbCBtYWtlciBieSBhZGRyZXNzIAUAAAANY2FsbGVyQWRkcmVzcwIAAAAVIG9yIG5vIGxvY2tlZCBhbW91bnQuAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAEW1pbldpdGhkcmF3SGVpZ2h0CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAxQbGVhc2Ugd2FpdCAJAAGkAAAAAQUAAAARbWluV2l0aGRyYXdIZWlnaHQCAAAAESBiZWZvcmUgd2l0aGRyYXcuBAAAAA1hc3NldEVtaXNzaW9uCAUAAAASc3ludGhldGljQXNzZXRJbmZvAAAACHF1YW50aXR5BAAAAAxjdXJyZW50UHJpY2UJAQAAAA1nZXRBc3NldFByaWNlAAAAAQUAAAAScHJpY2VPcmFjbGVBZGRyZXNzBAAAABVwb29sTWFrZXJMb2NrZWRBbW91bnQJAQAAABhnZXRQb29sTWFrZXJMb2NrZWRBbW91bnQAAAACBQAAAAxhc3NldEFkZHJlc3MFAAAADWNhbGxlckFkZHJlc3MEAAAAG3ByaWNlV2l0aE92ZXJjb2xsYXRlcmFsUmF0ZQkAAGgAAAACCQEAAAAdZ2V0QXNzZXRPdmVyQ29sbGF0ZXJhbFBlcmNlbnQAAAABBQAAABZhc3NldENvbmZpZ3VyYXRpb25MaXN0BQAAAAxjdXJyZW50UHJpY2UEAAAAGXVzZG5OZWVkZWRUb0NvdmVyRW1pc3Npb24JAABoAAAAAgUAAAAbcHJpY2VXaXRoT3ZlcmNvbGxhdGVyYWxSYXRlBQAAAA1hc3NldEVtaXNzaW9uAwkAAGYAAAACBQAAABp0b3RhbFVTRE5CYWxhbmNlT25Db250cmFjdAUAAAAZdXNkbk5lZWRlZFRvQ292ZXJFbWlzc2lvbgQAAAAcYW1vdXRBdmFpbGFibGVUb0V4aXRGcm9tUG9vbAkAAGUAAAACBQAAABp0b3RhbFVTRE5CYWxhbmNlT25Db250cmFjdAUAAAAZdXNkbk5lZWRlZFRvQ292ZXJFbWlzc2lvbgQAAAARYW1vdW50Rm9yV2l0aGRyYXcJAABoAAAAAgUAAAATcG9vbE1ha2V0UHJvcG9ydGlvbgUAAAAcYW1vdXRBdmFpbGFibGVUb0V4aXRGcm9tUG9vbAQAAAARZmluYWxMb2NrZWRBbW91bnQJAABlAAAAAgkBAAAAGGdldFBvb2xNYWtlckxvY2tlZEFtb3VudAAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAANY2FsbGVyQWRkcmVzcwUAAAARYW1vdW50Rm9yV2l0aGRyYXcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAB1nZXRBc3NldEN1cnJyZW50UG9vbEFtb3VudEtleQAAAAEFAAAADGFzc2V0QWRkcmVzcwkAAGUAAAACCQEAAAAZZ2V0QXNzZXRDdXJyZW50UG9vbEFtb3VudAAAAAEFAAAADGFzc2V0QWRkcmVzcwUAAAARYW1vdW50Rm9yV2l0aGRyYXcJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAACJnZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50S2V5AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAA1jYWxsZXJBZGRyZXNzCQAAZQAAAAIJAQAAAB9nZXRQb29sTWFrZXJQYXJ0aWNpcGF0aW9uQW1vdW50AAAAAgUAAAAMYXNzZXRBZGRyZXNzBQAAAA1jYWxsZXJBZGRyZXNzBQAAABFhbW91bnRGb3JXaXRoZHJhdwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAG2dldFBvb2xNYWtlckxvY2tlZEFtb3VudEtleQAAAAIFAAAADGFzc2V0QWRkcmVzcwUAAAANY2FsbGVyQWRkcmVzcwUAAAARZmluYWxMb2NrZWRBbW91bnQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAANY2FsbGVyQWRkcmVzcwUAAAARYW1vdW50Rm9yV2l0aGRyYXcFAAAAD25ldXRyaW5vQXNzZXRJZAUAAAADbmlsBQAAAANuaWwAAAAA5pVIVQ==", "chainId": 84, "height": 1188851, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 4 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | func convertJsonArrayToList (jsonArray,splitSymbol) = split(jsonArray, splitSymbol) | |
5 | + | ||
6 | + | ||
7 | + | func getStringByAddressAndKey (address,key) = valueOrElse(getString(address, key), "") | |
8 | + | ||
9 | + | ||
10 | + | func getBoolByKey (key) = valueOrElse(getBoolean(this, key), false) | |
11 | + | ||
12 | + | ||
13 | + | let keyAssetCode = 1 | |
14 | + | ||
15 | + | let keyAssetId = 2 | |
16 | + | ||
17 | + | let keyAssetStatus = 3 | |
18 | + | ||
19 | + | let keyAssetPriceDecimals = 4 | |
20 | + | ||
21 | + | let keyAssetBakingAsset = 5 | |
22 | + | ||
23 | + | let keyOvercollateralPercentage = 6 | |
24 | + | ||
25 | + | let keyMinPool = 7 | |
26 | + | ||
27 | + | let keyPriceOracleAddress = 8 | |
28 | + | ||
29 | + | let keyMinBuyPayment = 9 | |
30 | + | ||
31 | + | let keyMinSellPayment = 10 | |
32 | + | ||
33 | + | let keyBuyLockInterval = 11 | |
34 | + | ||
35 | + | let keySellLockInterval = 12 | |
36 | + | ||
37 | + | let keyBuyFee = 13 | |
38 | + | ||
39 | + | let keySellFee = 14 | |
40 | + | ||
41 | + | let keyPoolRedemptionTimeout = 15 | |
42 | + | ||
43 | + | let SEPARATOR = "__" | |
44 | + | ||
45 | + | let COMMONCONFIG = "commonConfig" | |
46 | + | ||
47 | + | let adminPublicKey = "BHHgEoehcnhsnmCRcgoascXUxtmWxm5o41tACQ4zRtWH" | |
48 | + | ||
49 | + | let neutrinoContractAddressKey = "%s%s__commonConfig__neutrinoContractAddress" | |
50 | + | ||
51 | + | let minimunPoolFundingAmountKey = "%s%s__commonConfig__minimumPoolFundingAmount" | |
52 | + | ||
53 | + | let isInitializedKey = "%s%s__commonConfig__initialized" | |
54 | + | ||
55 | + | let currentAssetIndexKey = "%s%s__commonConfig__predefinedAssetsActiveIndex" | |
56 | + | ||
57 | + | let assetsAddressListKey = "%s%s__commonConfig__predefinedAssetsList" | |
58 | + | ||
59 | + | let debtTokenIdKey = "%s%s__commonConfig__debtAssetId" | |
60 | + | ||
61 | + | let neutrinoAssetIdKey = "neutrino_asset_id" | |
62 | + | ||
63 | + | let nsbtAssetIdKey = "bond_asset_id" | |
64 | + | ||
65 | + | let defoAssetIdKey = "%s__defoAssetId" | |
66 | + | ||
67 | + | let assetPriceKey = "assetPrice" | |
68 | + | ||
69 | + | let setAssetScriptTxIdKey = "%s__assetScriptTxId" | |
70 | + | ||
71 | + | func getAssetConfigKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__config") | |
72 | + | ||
73 | + | ||
74 | + | func getAssetInitHeightKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__initHeight") | |
75 | + | ||
76 | + | ||
77 | + | func getAssetActivateHeightKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__activateHeight") | |
78 | + | ||
79 | + | ||
80 | + | func getAssetCurrrentPoolAmountKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__currentPool") | |
81 | + | ||
82 | + | ||
83 | + | func getAssetMaxPoolAmountKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__maxPool") | |
84 | + | ||
85 | + | ||
86 | + | func getAssetMetaKey (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__meta") | |
87 | + | ||
88 | + | ||
89 | + | func getAssetAddressByCodeKey (assetCode) = (("%s%s%s__defoAsset__" + assetCode) + "__addressByAssetCode") | |
90 | + | ||
91 | + | ||
92 | + | func getAssetAddressByAssetIdKey (assetId) = (("%s%s%s__defoAsset__" + assetId) + "__addressByAssetId") | |
93 | + | ||
94 | + | ||
95 | + | func getPoolMakerParticipationAmountKey (assetAddress,poolMakerAddress) = (((((((("%s%s%s%s" + SEPARATOR) + "pool") + SEPARATOR) + assetAddress) + SEPARATOR) + poolMakerAddress) + SEPARATOR) + "amount") | |
96 | + | ||
97 | + | ||
98 | + | func getPoolMakerParticipationMaxAmountKey (assetAddress,poolMakerAddress) = (((((((("%s%s%s%s" + SEPARATOR) + "pool") + SEPARATOR) + assetAddress) + SEPARATOR) + poolMakerAddress) + SEPARATOR) + "maxAmount") | |
99 | + | ||
100 | + | ||
101 | + | func getPoolMakerLockedAmountKey (assetAddress,poolMakerAddress) = (((((((("%s%s%s%s" + SEPARATOR) + "pool") + SEPARATOR) + assetAddress) + SEPARATOR) + poolMakerAddress) + SEPARATOR) + "lockedAmount") | |
102 | + | ||
103 | + | ||
104 | + | func getPoolMakerUnlockHeightKey (assetAddress,poolMakerAddress) = (((((((("%s%s%s%s" + SEPARATOR) + "pool") + SEPARATOR) + assetAddress) + SEPARATOR) + poolMakerAddress) + SEPARATOR) + "unlockHeight") | |
105 | + | ||
106 | + | ||
107 | + | func getAssetConfigArray (assetAddress) = convertJsonArrayToList(valueOrErrorMessage(getStringByAddressAndKey(this, getAssetConfigKey(assetAddress)), (("No DEFO Asset " + assetAddress) + "config present")), SEPARATOR) | |
108 | + | ||
109 | + | ||
110 | + | let neutrinoContract = addressFromStringValue(valueOrErrorMessage(getString(this, neutrinoContractAddressKey), "No neutrino contract specified.")) | |
111 | + | ||
112 | + | let neutrinoAssetId = fromBase58String(valueOrErrorMessage(getString(neutrinoContract, neutrinoAssetIdKey), "No USDN asset id found.")) | |
113 | + | ||
114 | + | let nsbtAssetId = fromBase58String(valueOrErrorMessage(getString(neutrinoContract, nsbtAssetIdKey), "No NSBT asset id found")) | |
115 | + | ||
116 | + | let minimumPoolFunding = valueOrErrorMessage(getInteger(this, minimunPoolFundingAmountKey), "Minimum pool funding amount is not specified.") | |
117 | + | ||
118 | + | let assetStatus = $Tuple3("PROPOSED", "READY", "ISSUED") | |
119 | + | ||
120 | + | let predefinedAssetContracts = valueOrErrorMessage(getString(this, assetsAddressListKey), "No pool of predeployed asset contracts found.") | |
121 | + | ||
122 | + | let predefinedAssetsList = convertJsonArrayToList(predefinedAssetContracts, ",") | |
123 | + | ||
124 | + | let currentAssetIndex = valueOrElse(getInteger(this, currentAssetIndexKey), 0) | |
125 | + | ||
126 | + | let debtToken = fromBase58String(valueOrErrorMessage(getString(this, debtTokenIdKey), "No debt token found")) | |
127 | + | ||
128 | + | let multiplicator = 1000000 | |
129 | + | ||
130 | + | let debtTokenReissueAmount = (10000000 * multiplicator) | |
131 | + | ||
132 | + | func getAssetAddressByCode (assetSymbol) = valueOrElse(getString(this, getAssetAddressByCodeKey(assetSymbol)), "") | |
133 | + | ||
134 | + | ||
135 | + | func getAssetCode (assetConfig) = assetConfig[keyAssetCode] | |
136 | + | ||
137 | + | ||
138 | + | func getAssetID (assetConfig) = assetConfig[keyAssetId] | |
139 | + | ||
140 | + | ||
141 | + | func getAssetStatus (assetConfig) = assetConfig[keyAssetStatus] | |
142 | + | ||
143 | + | ||
144 | + | func getAssetPriceDecimals (assetConfig) = parseIntValue(assetConfig[keyAssetPriceDecimals]) | |
145 | + | ||
146 | + | ||
147 | + | func getAssetBakingAssetId (assetConfig) = assetConfig[keyAssetBakingAsset] | |
148 | + | ||
149 | + | ||
150 | + | func getAssetOverCollateralPercent (assetConfig) = parseIntValue(assetConfig[keyOvercollateralPercentage]) | |
151 | + | ||
152 | + | ||
153 | + | func getAssetMinRequiredPoolAmount (assetConfig) = parseIntValue(assetConfig[keyMinPool]) | |
154 | + | ||
155 | + | ||
156 | + | func getAssetPriceOracleAddress (assetConfig) = assetConfig[keyPriceOracleAddress] | |
157 | + | ||
158 | + | ||
159 | + | func getMinBuyPaymentPerAsset (assetConfig) = parseIntValue(assetConfig[keyMinBuyPayment]) | |
160 | + | ||
161 | + | ||
162 | + | func getMinSellPaymentPerAsset (assetConfig) = parseIntValue(assetConfig[keyMinSellPayment]) | |
163 | + | ||
164 | + | ||
165 | + | func getBuyLockIntervalPerAsset (assetConfig) = parseIntValue(assetConfig[keyBuyLockInterval]) | |
166 | + | ||
167 | + | ||
168 | + | func getSellLockIntervalPerAsset (assetConfig) = parseIntValue(assetConfig[keySellLockInterval]) | |
169 | + | ||
170 | + | ||
171 | + | func getBuyFeePerAsset (assetConfig) = parseIntValue(assetConfig[keyBuyFee]) | |
172 | + | ||
173 | + | ||
174 | + | func getSellFeePerAsset (assetConfig) = parseIntValue(assetConfig[keySellFee]) | |
175 | + | ||
176 | + | ||
177 | + | func getRedemptionTimeoutBlocks (assetConfig) = parseIntValue(assetConfig[keyPoolRedemptionTimeout]) | |
178 | + | ||
179 | + | ||
180 | + | func getAssetInitHeight (assetAddress) = valueOrElse(getInteger(this, getAssetInitHeightKey(assetAddress)), 0) | |
181 | + | ||
182 | + | ||
183 | + | func getAssetActivateHeight (assetAddress) = valueOrElse(getInteger(this, getAssetActivateHeightKey(assetAddress)), 0) | |
184 | + | ||
185 | + | ||
186 | + | func getAssetCurrentPoolAmount (assetAddress) = valueOrElse(getInteger(this, getAssetCurrrentPoolAmountKey(assetAddress)), 0) | |
187 | + | ||
188 | + | ||
189 | + | func getAssetMaxPoolAmount (assetAddress) = valueOrElse(getInteger(this, getAssetMaxPoolAmountKey(assetAddress)), 0) | |
190 | + | ||
191 | + | ||
192 | + | func getAssetMeta (assetAddress) = valueOrElse(getString(this, getAssetMetaKey(assetAddress)), "") | |
193 | + | ||
194 | + | ||
195 | + | func getPoolMakerParticipationAmount (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerParticipationAmountKey(assetAddress, poolMakerAddress)), 0) | |
196 | + | ||
197 | + | ||
198 | + | func getPoolMakerParticipationMaxAmount (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerParticipationMaxAmountKey(assetAddress, poolMakerAddress)), 0) | |
199 | + | ||
200 | + | ||
201 | + | func getPoolMakerLockedAmount (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerLockedAmountKey(assetAddress, poolMakerAddress)), 0) | |
202 | + | ||
203 | + | ||
204 | + | func getPoolMakerUnlockHeight (assetAddress,poolMakerAddress) = valueOrElse(getInteger(this, getPoolMakerUnlockHeightKey(assetAddress, poolMakerAddress)), 0) | |
205 | + | ||
206 | + | ||
207 | + | func getAssetPrice (priceOracleAddress) = valueOrErrorMessage(getInteger(priceOracleAddress, assetPriceKey), "No Asset price found") | |
208 | + | ||
209 | + | ||
210 | + | func composeAssetConfigurationString (assetCode,assetId,assetStatus,priceDecimals,backingAssetId,overCollateralPercent,minPool,priceOracleAddress,minBuyPayment,minSellPayment,buyLockInterval,sellLockInterval,buyFee,sellFee,poolRedemptionTimeout) = (((((((((((((((((((((((((((((("%s%s%s%d%s%d%d%s%d%d%d%d%d%d%d" + SEPARATOR) + assetCode) + SEPARATOR) + assetId) + SEPARATOR) + assetStatus) + SEPARATOR) + toString(priceDecimals)) + SEPARATOR) + backingAssetId) + SEPARATOR) + toString(overCollateralPercent)) + SEPARATOR) + toString(minPool)) + SEPARATOR) + priceOracleAddress) + SEPARATOR) + toString(minBuyPayment)) + SEPARATOR) + toString(minSellPayment)) + SEPARATOR) + toString(buyLockInterval)) + SEPARATOR) + toString(sellLockInterval)) + SEPARATOR) + toString(buyFee)) + SEPARATOR) + toString(sellFee)) + SEPARATOR) + toString(poolRedemptionTimeout)) | |
211 | + | ||
212 | + | ||
213 | + | @Callable(i) | |
214 | + | func init (neutrinoContractAddress,minimunPoolFundingAmount,predefinedAssetList,currentAssetIndex) = if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
215 | + | then throw("Only Admin can perform contract operation.") | |
216 | + | else if ((getBoolByKey(isInitializedKey) == true)) | |
217 | + | then throw("Contract was already initialized.") | |
218 | + | else { | |
219 | + | let issueDebt = Issue("DEFO_DEBT", "DEFO Debt Token.", 1, 6, true) | |
220 | + | let debtTokenId = calculateAssetId(issueDebt) | |
221 | + | [StringEntry(neutrinoContractAddressKey, neutrinoContractAddress), IntegerEntry(minimunPoolFundingAmountKey, minimunPoolFundingAmount), StringEntry(assetsAddressListKey, predefinedAssetList), IntegerEntry(currentAssetIndexKey, currentAssetIndex), StringEntry(debtTokenIdKey, toBase58String(debtTokenId)), BooleanEntry(isInitializedKey, true), issueDebt, Burn(debtTokenId, 1)] | |
222 | + | } | |
223 | + | ||
224 | + | ||
225 | + | ||
226 | + | @Callable(i) | |
227 | + | func proposeAsset (assetCode,meta,minPool,priceOracleAddress,overCollateralPercent,backingAssetId,priceDecimals,minBuyPayment,minSellPayment,buyLockInterval,sellLockInterval,buyFee,sellFee,poolRedemptionTimeout) = if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
228 | + | then throw("Only Admin can perform contract operation.") | |
229 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
230 | + | then throw("Contract is not yet ready.") | |
231 | + | else if ((fromBase58String(backingAssetId) != neutrinoAssetId)) | |
232 | + | then throw("Baking asset id could be USDN only.") | |
233 | + | else if ((getAssetAddressByCode(assetCode) != "")) | |
234 | + | then throw((("Asset with passed code " + assetCode) + " has already been proposed.")) | |
235 | + | else if ((minimumPoolFunding > minPool)) | |
236 | + | then throw(("Minimum pool amount should be greater or equals to " + toString(minimumPoolFunding))) | |
237 | + | else if (if (if (if (if (if (if (if ((0 > overCollateralPercent)) | |
238 | + | then true | |
239 | + | else (priceDecimals != 1000000)) | |
240 | + | then true | |
241 | + | else (0 > minBuyPayment)) | |
242 | + | then true | |
243 | + | else (0 > minSellPayment)) | |
244 | + | then true | |
245 | + | else (0 > buyLockInterval)) | |
246 | + | then true | |
247 | + | else (0 > sellLockInterval)) | |
248 | + | then true | |
249 | + | else (0 > buyFee)) | |
250 | + | then true | |
251 | + | else (0 > sellFee)) | |
252 | + | then throw("One of the passed parameters is invalid.") | |
253 | + | else { | |
254 | + | let priceOracleAddressValid = valueOrErrorMessage(addressFromStringValue(priceOracleAddress), "Passed Price Oracle Address is not valid.") | |
255 | + | let assetAddress = predefinedAssetsList[currentAssetIndex] | |
256 | + | let defoAssetId = valueOrErrorMessage(getString(valueOrErrorMessage(addressFromString(assetAddress), ""), defoAssetIdKey), "No defo asset ID found.") | |
257 | + | [StringEntry(getAssetConfigKey(assetAddress), composeAssetConfigurationString(assetCode, defoAssetId, assetStatus._1, priceDecimals, backingAssetId, overCollateralPercent, minPool, priceOracleAddress, minBuyPayment, minSellPayment, buyLockInterval, sellLockInterval, buyFee, sellFee, poolRedemptionTimeout)), StringEntry(getAssetAddressByCodeKey(assetCode), assetAddress), StringEntry(getAssetMetaKey(assetAddress), meta), IntegerEntry(getAssetInitHeightKey(assetAddress), height), IntegerEntry(currentAssetIndexKey, (currentAssetIndex + 1)), StringEntry(getAssetAddressByAssetIdKey(defoAssetId), assetAddress)] | |
258 | + | } | |
259 | + | ||
260 | + | ||
261 | + | ||
262 | + | @Callable(i) | |
263 | + | func fundLiquidityPool (assetCode) = { | |
264 | + | let assetAddress = getAssetAddressByCode(assetCode) | |
265 | + | let assetConfigurationList = getAssetConfigArray(assetAddress) | |
266 | + | let attachedPayment = value(i.payments[0]) | |
267 | + | if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
268 | + | then throw("Only Admin can perform contract operation.") | |
269 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
270 | + | then throw("Contract is not yet ready.") | |
271 | + | else if ((attachedPayment.assetId != neutrinoAssetId)) | |
272 | + | then throw("Liquidity pool could be funded with USDN only.") | |
273 | + | else if ((attachedPayment.amount == 0)) | |
274 | + | then throw("Incorrect attached payment amount.") | |
275 | + | else if ((assetAddress == "")) | |
276 | + | then throw((("Cannot find liquidity pool for asset " + assetCode) + ".")) | |
277 | + | else { | |
278 | + | let finalPoolAmount = (attachedPayment.amount + getAssetCurrentPoolAmount(assetAddress)) | |
279 | + | let maxPoolAmount = getAssetMaxPoolAmount(assetAddress) | |
280 | + | let currentPoolMakerBalance = getPoolMakerParticipationAmount(assetAddress, toString(i.caller)) | |
281 | + | let maxPoolMakerBalance = getPoolMakerParticipationMaxAmount(assetAddress, toString(i.caller)) | |
282 | + | let currentPoolStatus = getAssetStatus(assetConfigurationList) | |
283 | + | let finalPoolStatus = if (if ((finalPoolAmount >= getAssetMinRequiredPoolAmount(assetConfigurationList))) | |
284 | + | then (currentPoolStatus == assetStatus._1) | |
285 | + | else false) | |
286 | + | then assetStatus._2 | |
287 | + | else currentPoolStatus | |
288 | + | let aCode = getAssetCode(assetConfigurationList) | |
289 | + | let aID = getAssetID(assetConfigurationList) | |
290 | + | let aPriceDecimals = getAssetPriceDecimals(assetConfigurationList) | |
291 | + | let aBakingAssetId = getAssetBakingAssetId(assetConfigurationList) | |
292 | + | let aOverCollateralPercent = getAssetOverCollateralPercent(assetConfigurationList) | |
293 | + | let aMinRequiredPool = getAssetMinRequiredPoolAmount(assetConfigurationList) | |
294 | + | let aPriceOracleAddress = getAssetPriceOracleAddress(assetConfigurationList) | |
295 | + | let aMinBuyPayment = getMinBuyPaymentPerAsset(assetConfigurationList) | |
296 | + | let aMinSellPayment = getMinSellPaymentPerAsset(assetConfigurationList) | |
297 | + | let aBuyLockInterval = getBuyLockIntervalPerAsset(assetConfigurationList) | |
298 | + | let aSellLockInterval = getSellLockIntervalPerAsset(assetConfigurationList) | |
299 | + | let aBuyFee = getBuyFeePerAsset(assetConfigurationList) | |
300 | + | let aSellFee = getSellFeePerAsset(assetConfigurationList) | |
301 | + | let aRedemptionTimeoutBlocks = getRedemptionTimeoutBlocks(assetConfigurationList) | |
302 | + | let newPoolMakerBalance = (currentPoolMakerBalance + i.payments[0].amount) | |
303 | + | let result = [IntegerEntry(getPoolMakerParticipationAmountKey(assetAddress, toString(i.caller)), newPoolMakerBalance), IntegerEntry(getPoolMakerParticipationMaxAmountKey(assetAddress, toString(i.caller)), if ((newPoolMakerBalance > maxPoolMakerBalance)) | |
304 | + | then newPoolMakerBalance | |
305 | + | else maxPoolMakerBalance), IntegerEntry(getAssetCurrrentPoolAmountKey(assetAddress), finalPoolAmount), IntegerEntry(getAssetMaxPoolAmountKey(assetAddress), if ((finalPoolAmount > maxPoolAmount)) | |
306 | + | then finalPoolAmount | |
307 | + | else maxPoolAmount), DeleteEntry(getAssetConfigKey(assetAddress)), StringEntry(getAssetConfigKey(assetAddress), composeAssetConfigurationString(aCode, aID, finalPoolStatus, aPriceDecimals, aBakingAssetId, aOverCollateralPercent, aMinRequiredPool, aPriceOracleAddress, aMinBuyPayment, aMinSellPayment, aBuyLockInterval, aSellLockInterval, aBuyFee, aSellFee, aRedemptionTimeoutBlocks))] | |
308 | + | if ((currentPoolStatus == assetStatus._3)) | |
309 | + | then (result :+ ScriptTransfer(addressFromStringValue(assetAddress), attachedPayment.amount, neutrinoAssetId)) | |
310 | + | else result | |
311 | + | } | |
312 | + | } | |
313 | + | ||
314 | + | ||
315 | + | ||
316 | + | @Callable(i) | |
317 | + | func activateAsset (assetCode) = { | |
318 | + | let assetAddress = getAssetAddressByCode(assetCode) | |
319 | + | let assetConfigurationList = getAssetConfigArray(assetAddress) | |
320 | + | let currentAssetPoolAmount = getAssetCurrentPoolAmount(assetAddress) | |
321 | + | let aCode = getAssetCode(assetConfigurationList) | |
322 | + | let aCurrentStatus = getAssetStatus(assetConfigurationList) | |
323 | + | let aID = getAssetID(assetConfigurationList) | |
324 | + | let aPriceDecimals = getAssetPriceDecimals(assetConfigurationList) | |
325 | + | let aBakingAssetId = getAssetBakingAssetId(assetConfigurationList) | |
326 | + | let aOverCollateralPercent = getAssetOverCollateralPercent(assetConfigurationList) | |
327 | + | let aMinRequiredPool = getAssetMinRequiredPoolAmount(assetConfigurationList) | |
328 | + | let aPriceOracleAddress = getAssetPriceOracleAddress(assetConfigurationList) | |
329 | + | let aMinBuyPayment = getMinBuyPaymentPerAsset(assetConfigurationList) | |
330 | + | let aMinSellPayment = getMinSellPaymentPerAsset(assetConfigurationList) | |
331 | + | let aBuyLockInterval = getBuyLockIntervalPerAsset(assetConfigurationList) | |
332 | + | let aSellLockInterval = getSellLockIntervalPerAsset(assetConfigurationList) | |
333 | + | let aBuyFee = getBuyFeePerAsset(assetConfigurationList) | |
334 | + | let aSellFee = getSellFeePerAsset(assetConfigurationList) | |
335 | + | let aRedemptionTimeoutBlocks = getRedemptionTimeoutBlocks(assetConfigurationList) | |
336 | + | if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
337 | + | then throw("Only Admin can perform contract operation.") | |
338 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
339 | + | then throw("Contract is not yet ready.") | |
340 | + | else if ((aCurrentStatus != assetStatus._2)) | |
341 | + | then throw((("Asset is not in READY status. Current status is " + aCurrentStatus) + ".")) | |
342 | + | else if ((assetAddress == "")) | |
343 | + | then throw((("Cannot find asset " + assetCode) + ".")) | |
344 | + | else if ((minimumPoolFunding > currentAssetPoolAmount)) | |
345 | + | then throw((((("Cannot issue asset as liquidity pool amount (" + toString(currentAssetPoolAmount)) + ") is less than required (") + toString(minimumPoolFunding)) + ")")) | |
346 | + | else { | |
347 | + | let issueDebt = Reissue(debtToken, debtTokenReissueAmount, true) | |
348 | + | [IntegerEntry(getAssetActivateHeightKey(assetAddress), height), DeleteEntry(getAssetConfigKey(assetAddress)), StringEntry(getAssetConfigKey(assetAddress), composeAssetConfigurationString(aCode, aID, assetStatus._3, aPriceDecimals, aBakingAssetId, aOverCollateralPercent, aMinRequiredPool, aPriceOracleAddress, aMinBuyPayment, aMinSellPayment, aBuyLockInterval, aSellLockInterval, aBuyFee, aSellFee, aRedemptionTimeoutBlocks)), issueDebt, ScriptTransfer(addressFromStringValue(assetAddress), currentAssetPoolAmount, neutrinoAssetId), ScriptTransfer(addressFromStringValue(assetAddress), debtTokenReissueAmount, debtToken)] | |
349 | + | } | |
350 | + | } | |
351 | + | ||
352 | + | ||
353 | + | ||
354 | + | @Callable(i) | |
355 | + | func redeemFromPool (assetCode,amount) = { | |
356 | + | let assetAddress = getAssetAddressByCode(assetCode) | |
357 | + | let assetConfigurationList = getAssetConfigArray(assetAddress) | |
358 | + | let callerAddress = toString(i.caller) | |
359 | + | let totalAmountInPoolByCaller = getPoolMakerParticipationAmount(assetAddress, callerAddress) | |
360 | + | let lockedAmountByPoolMaker = getPoolMakerLockedAmount(assetAddress, callerAddress) | |
361 | + | if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
362 | + | then throw("Only Admin can perform contract operation.") | |
363 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
364 | + | then throw("Contract is not yet ready.") | |
365 | + | else if ((assetAddress == "")) | |
366 | + | then throw((("Cannot find asset " + assetCode) + ".")) | |
367 | + | else if (if (if ((0 > amount)) | |
368 | + | then true | |
369 | + | else (totalAmountInPoolByCaller == 0)) | |
370 | + | then true | |
371 | + | else (amount > totalAmountInPoolByCaller)) | |
372 | + | then throw((("Cannot find pool maker by address " + callerAddress) + " or amount passed is not correct.")) | |
373 | + | else if ((lockedAmountByPoolMaker > 0)) | |
374 | + | then throw("Pool maker already has initiated redemption that is not withdrawn yet.") | |
375 | + | else [IntegerEntry(getPoolMakerLockedAmountKey(assetAddress, callerAddress), amount), IntegerEntry(getPoolMakerUnlockHeightKey(assetAddress, callerAddress), (height + getRedemptionTimeoutBlocks(assetConfigurationList)))] | |
376 | + | } | |
377 | + | ||
378 | + | ||
379 | + | ||
380 | + | @Callable(i) | |
381 | + | func withdraw (assetCode) = { | |
382 | + | let assetConfigurationList = getAssetConfigArray(assetCode) | |
383 | + | let assetAddress = getAssetAddressByCode(assetCode) | |
384 | + | let priceOracleAddress = addressFromStringValue(getAssetPriceOracleAddress(assetConfigurationList)) | |
385 | + | let callerAddress = toString(i.caller) | |
386 | + | let syntheticAssetInfo = valueOrErrorMessage(assetInfo(fromBase58String(assetAddress)), ("Cannot find asset by id " + assetAddress)) | |
387 | + | let totalUSDNBalanceOnContract = assetBalance(this, neutrinoAssetId) | |
388 | + | let totalAmountInPoolByPoolMaker = getPoolMakerParticipationAmount(assetAddress, callerAddress) | |
389 | + | let lockedAmountByPoolMaker = getPoolMakerLockedAmount(assetAddress, callerAddress) | |
390 | + | let minWithdrawHeight = getPoolMakerUnlockHeight(assetAddress, callerAddress) | |
391 | + | let poolMaketProportion = (getAssetMaxPoolAmount(assetAddress) / getPoolMakerParticipationMaxAmount(assetAddress, callerAddress)) | |
392 | + | if ((toBase58String(i.callerPublicKey) != adminPublicKey)) | |
393 | + | then throw("Only Admin can perform contract operation.") | |
394 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
395 | + | then throw("Contract is not yet ready.") | |
396 | + | else if ((getBoolByKey(isInitializedKey) == false)) | |
397 | + | then throw("Contract is not yet ready.") | |
398 | + | else if ((assetAddress == "")) | |
399 | + | then throw((("Cannot find asset " + assetCode) + ".")) | |
400 | + | else if ((totalAmountInPoolByPoolMaker == 0)) | |
401 | + | then throw((("Cannot find pool maker by address " + callerAddress) + " or no locked amount.")) | |
402 | + | else if ((height > minWithdrawHeight)) | |
403 | + | then throw((("Please wait " + toString(minWithdrawHeight)) + " before withdraw.")) | |
404 | + | else { | |
405 | + | let assetEmission = syntheticAssetInfo.quantity | |
406 | + | let currentPrice = getAssetPrice(priceOracleAddress) | |
407 | + | let poolMakerLockedAmount = getPoolMakerLockedAmount(assetAddress, callerAddress) | |
408 | + | let priceWithOvercollateralRate = (getAssetOverCollateralPercent(assetConfigurationList) * currentPrice) | |
409 | + | let usdnNeededToCoverEmission = (priceWithOvercollateralRate * assetEmission) | |
410 | + | if ((totalUSDNBalanceOnContract > usdnNeededToCoverEmission)) | |
411 | + | then { | |
412 | + | let amoutAvailableToExitFromPool = (totalUSDNBalanceOnContract - usdnNeededToCoverEmission) | |
413 | + | let amountForWithdraw = (poolMaketProportion * amoutAvailableToExitFromPool) | |
414 | + | let finalLockedAmount = (getPoolMakerLockedAmount(assetAddress, callerAddress) - amountForWithdraw) | |
415 | + | [IntegerEntry(getAssetCurrrentPoolAmountKey(assetAddress), (getAssetCurrentPoolAmount(assetAddress) - amountForWithdraw)), IntegerEntry(getPoolMakerParticipationAmountKey(assetAddress, callerAddress), (getPoolMakerParticipationAmount(assetAddress, callerAddress) - amountForWithdraw)), IntegerEntry(getPoolMakerLockedAmountKey(assetAddress, callerAddress), finalLockedAmount), ScriptTransfer(addressFromStringValue(callerAddress), amountForWithdraw, neutrinoAssetId)] | |
416 | + | } | |
417 | + | else nil | |
418 | + | } | |
419 | + | } | |
420 | + | ||
421 | + |
github/deemru/w8io/169f3d6 35.87 ms ◑