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