tx · 7sG4spNo6XVM5fQScJpRYsvV4js3Q7jWHL1m75xvL1e2

3NC1z7rSjmjRbrab3ja4DcnCw1xZkauKhSo:  -0.01400000 Waves

2021.04.09 12:03 [1474710] smart account 3NC1z7rSjmjRbrab3ja4DcnCw1xZkauKhSo > SELF 0.00000000 Waves

{ "type": 13, "id": "7sG4spNo6XVM5fQScJpRYsvV4js3Q7jWHL1m75xvL1e2", "fee": 1400000, "feeAssetId": null, "timestamp": 1617959052198, "version": 1, "sender": "3NC1z7rSjmjRbrab3ja4DcnCw1xZkauKhSo", "senderPublicKey": "FyXgaE6rRdPKPgcSheVHX7SMhDdiGGdcq2vD3HCazAwC", "proofs": [ "62poWHZ9wW9cMSp5Z3TXrYwUVRuNabXBjS37SUPtcBPf5VogmKMfe7H2zwfgBwjEPjEucaZk79nK45XJdJXeR6Hj" ], "script": "base64:AAIEAAAAAAAAABMIAhIAEgASBAoCCAgSABIDCgEIAAAAbgEAAAARa2V5QWNjdW11bGF0ZWRGZWUAAAAAAgAAABIlc19fYWNjdW11bGF0ZWRGZWUBAAAADmtleVVjb2xsYXRlcmFsAAAAAAIAAAAPJXNfX3Vjb2xsYXRlcmFsAQAAABlrZXlUb3RhbExlbmRlZEF0T3RoZXJBY2NzAAAAAAIAAAAaJXNfX3RvdGFsTGVuZGVkQXRPdGhlckFjY3MBAAAAE2tleUFzc2V0TG9ja2VkVG90YWwAAAABAAAAB2Fzc2V0SWQJAAEsAAAAAgIAAAAYJXMlc19fYXNzZXRMb2NrZWRUb3RhbF9fBQAAAAdhc3NldElkAQAAABNrZXlBY2NvdW50T3BlcmF0aW9uAAAAAwAAAAx1bmxvY2tIZWlnaHQAAAAHYWRkcmVzcwAAAAZzdGF0dXMJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAB4lcyVzJWQlc19fZGVmb0Fzc2V0T3BlcmF0aW9uX18FAAAAB2FkZHJlc3MCAAAAAl9fCQABpAAAAAEFAAAADHVubG9ja0hlaWdodAIAAAACX18FAAAABnN0YXR1cwEAAAAKa2V5RmFjdG9yeQAAAAACAAAACyVzX19mYWN0b3J5AQAAABprZXlMZW5kZWRBbW91bnRCeUFzc2V0Q29kZQAAAAEAAAAJYXNzZXRDb2RlCQABLAAAAAICAAAAHSVzJXNfX2xlbmRlZEJhc2VBc3NldEFtb3VudF9fBQAAAAlhc3NldENvZGUBAAAACGtleVByaWNlAAAAAQAAAAlhc3NldENvZGUJAAEsAAAAAgIAAAANJXMlc19fcHJpY2VfXwUAAAAJYXNzZXRDb2RlAQAAABRrZXlDb250cm9sTGFzdEhlaWdodAAAAAEAAAAJYXNzZXRDb2RlCQABLAAAAAICAAAAEiVzJXNfX2xhc3RIZWlnaHRfXwUAAAAJYXNzZXRDb2RlAAAAABRJZHhPcGVyYXRpb25BbW91bnRJbgAAAAAAAAAAAQAAAAATSWR4T3BlcmF0aW9uQXNzZXRJbgAAAAAAAAAAAgAAAAARSWR4T3BlcmF0aW9uUHJpY2UAAAAAAAAAAAMAAAAAFUlkeE9wZXJhdGlvbkFtb3VudE91dAAAAAAAAAAABAAAAAAUSWR4T3BlcmF0aW9uQXNzZXRPdXQAAAAAAAAAAAUBAAAAFmFzc2V0RGF0YVN3YXBPcGVyYXRpb24AAAAHAAAACGFtb3VudEluAAAAB2Fzc2V0SW4AAAAFcHJpY2UAAAAJYW1vdW50T3V0AAAACGFzc2V0T3V0AAAADGJydXR0b0Ftb3VudAAAAAlmZWVBbW91bnQJAAS5AAAAAgkABEwAAAACAgAAAA4lZCVzJWQlcyVkJWQlZAkABEwAAAACCQABpAAAAAEFAAAACGFtb3VudEluCQAETAAAAAIFAAAAB2Fzc2V0SW4JAARMAAAAAgkAAaQAAAABBQAAAAlhbW91bnRPdXQJAARMAAAAAgUAAAAIYXNzZXRPdXQJAARMAAAAAgkAAaQAAAABBQAAAAVwcmljZQkABEwAAAACCQABpAAAAAEFAAAADGJydXR0b0Ftb3VudAkABEwAAAACCQABpAAAAAEFAAAACWZlZUFtb3VudAUAAAADbmlsAgAAAAJfXwEAAAAXYXNzZXREYXRhUmViYWxhbmNlVHJhY2UAAAAFAAAAD2RlYnRvckFzc2V0Q29kZQAAAAdkZWJ0UG10AAAAB2Jhc2VQbXQAAAAPbGVuZGVkQW10QmVmb3JlAAAADmxlbmRlZEFtdEFmdGVyCQAEuQAAAAIJAARMAAAAAgIAAAAOJXMlcyVkJXMlZCVkJWQJAARMAAAAAgUAAAAPZGVidG9yQXNzZXRDb2RlCQAETAAAAAIJAAJYAAAAAQkBAAAABXZhbHVlAAAAAQgFAAAAB2RlYnRQbXQAAAAHYXNzZXRJZAkABEwAAAACCQABpAAAAAEIBQAAAAdkZWJ0UG10AAAABmFtb3VudAkABEwAAAACCQACWAAAAAEJAQAAAAV2YWx1ZQAAAAEIBQAAAAdiYXNlUG10AAAAB2Fzc2V0SWQJAARMAAAAAgkAAaQAAAABCAUAAAAHYmFzZVBtdAAAAAZhbW91bnQJAARMAAAAAgkAAaQAAAABBQAAAA9sZW5kZWRBbXRCZWZvcmUJAARMAAAAAgkAAaQAAAABBQAAAA5sZW5kZWRBbXRBZnRlcgUAAAADbmlsAgAAAAJfXwEAAAAcYXNzZXRSZWFkU3dhcERhdGFBcnJheU9yRmFpbAAAAAEAAAAPYWNjT3BlcmF0aW9uS2V5BAAAABNhY2NPcGVyYXRpb25EYXRhU3RyCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAAPYWNjT3BlcmF0aW9uS2V5CQABLAAAAAICAAAAKlRoZXJlIGlzIG5vIHJlcXVlc3QgZm9yIHBhc3NlZCBhcmd1bWVudHM6IAUAAAAPYWNjT3BlcmF0aW9uS2V5CQAEtQAAAAIFAAAAE2FjY09wZXJhdGlvbkRhdGFTdHICAAAAAl9fAAAAAAdudWxsSW50AP//////////AAAAAAdudWxsU3RyAgAAAAROVUxMAAAAAApmYWN0b3J5QWNjCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwkBAAAACmtleUZhY3RvcnkAAAAACQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABJObyBjb25maWcgYXQgdGhpcz0JAAQlAAAAAQUAAAAEdGhpcwIAAAAJIGZvciBrZXk9CQEAAAAKa2V5RmFjdG9yeQAAAAABAAAAFWtleUZhY3RvcnlEZWJ0QXNzZXRJZAAAAAACAAAAHyVzJXNfX2NvbW1vbkNvbmZpZ19fZGVidEFzc2V0SWQBAAAAIGtleUZhY3RvcnlEZWJ0QXNzZXRFdGFsb25CYWxhbmNlAAAAAAIAAAAqJXMlc19fY29tbW9uQ29uZmlnX19kZWJ0QXNzZXRFdGFsb25CYWxhbmNlAQAAABJrZXlGYWN0b3J5QXNzZXRDZmcAAAABAAAAD2Fzc2V0QWRkcmVzc1N0cgkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAAD2Fzc2V0QWRkcmVzc1N0cgIAAAAIX19jb25maWcBAAAAGmtleUZhY3RvcnlBc3NldEN1cnJlbnRQb29sAAAAAQAAAA9hc3NldEFjY0FkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAABMlcyVzJXNfX2RlZm9Bc3NldF9fCQAEJQAAAAEFAAAAD2Fzc2V0QWNjQWRkcmVzcwIAAAANX19jdXJyZW50UG9vbAEAAAAga2V5RmFjdG9yeURlZm9BZGRyZXNzQnlBc3NldENvZGUAAAABAAAACWFzc2V0Q29kZQkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAACWFzc2V0Q29kZQIAAAAUX19hZGRyZXNzQnlBc3NldENvZGUBAAAAGWtleUZhY3RvcnlBc3NldFBvb2xNYWtlcnMAAAABAAAADGFzc2V0QWRkcmVzcwkAASwAAAACCQABLAAAAAICAAAAEyVzJXMlc19fZGVmb0Fzc2V0X18FAAAADGFzc2V0QWRkcmVzcwIAAAAMX19wb29sTWFrZXJzAQAAACFrZXlGYWN0b3J5RGVmb1N0YWtpbmdQYWNlbWFrZXJQdWIAAAAAAgAAACslcyVzX19jb21tb25Db25maWdfX2RlZm9TdGFraW5nUGFjZW1ha2VyUHViAQAAACNrZXlGYWN0b3J5UG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdAAAAAMAAAAMYXNzZXRBZGRyZXNzAAAAEHBvb2xNYWtlckFkZHJlc3MAAAABaAkABLkAAAACCQAETAAAAAICAAAAECVzJXMlcyVkJXNfX3Bvb2wJAARMAAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAIFAAAAEHBvb2xNYWtlckFkZHJlc3MJAARMAAAAAgkAAaQAAAABBQAAAAFoCQAETAAAAAICAAAAEGxpcXVpZGl0eVJlcXVlc3QFAAAAA25pbAIAAAACX18BAAAAH2tleUZhY3RvcnlQb29sTWFrZXJVbmxvY2tIZWlnaHQAAAACAAAADGFzc2V0QWRkcmVzcwAAABBwb29sTWFrZXJBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAOJXMlcyVzJXNfX3Bvb2wJAARMAAAAAgUAAAAMYXNzZXRBZGRyZXNzCQAETAAAAAIFAAAAEHBvb2xNYWtlckFkZHJlc3MJAARMAAAAAgIAAAAMdW5sb2NrSGVpZ2h0BQAAAANuaWwCAAAAAl9fAQAAABZmYWN0b3J5UmVhZERlYnRBc3NldElkAAAAAAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAACmZhY3RvcnlBY2MJAQAAABVrZXlGYWN0b3J5RGVidEFzc2V0SWQAAAAACQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABVObyBjb25maWcgYXQgZmFjdG9yeT0JAAQlAAAAAQUAAAAKZmFjdG9yeUFjYwIAAAAJIGZvciBrZXk9CQEAAAAVa2V5RmFjdG9yeURlYnRBc3NldElkAAAAAAEAAAAcZmFjdG9yeVJlYWRBc3NldENmZ0J5QWRkcmVzcwAAAAEAAAAPYXNzZXRBZGRyZXNzU3RyCQAEtQAAAAIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAApmYWN0b3J5QWNjCQEAAAASa2V5RmFjdG9yeUFzc2V0Q2ZnAAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABVObyBjb25maWcgYXQgZmFjdG9yeT0JAAQlAAAAAQUAAAAKZmFjdG9yeUFjYwIAAAAJIGZvciBrZXk9CQEAAAASa2V5RmFjdG9yeUFzc2V0Q2ZnAAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyAgAAAAJfXwEAAAAZZmFjdG9yeVJlYWRBc3NldENmZ0J5Q29kZQAAAAEAAAAJYXNzZXRDb2RlBAAAAA9hc3NldEFkZHJlc3NTdHIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAApmYWN0b3J5QWNjCQEAAAAga2V5RmFjdG9yeURlZm9BZGRyZXNzQnlBc3NldENvZGUAAAABBQAAAAlhc3NldENvZGUJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAFU5vIGNvbmZpZyBhdCBmYWN0b3J5PQkABCUAAAABBQAAAApmYWN0b3J5QWNjAgAAAAkgZm9yIGtleT0JAQAAACBrZXlGYWN0b3J5RGVmb0FkZHJlc3NCeUFzc2V0Q29kZQAAAAEFAAAACWFzc2V0Q29kZQkABRQAAAACBQAAAA9hc3NldEFkZHJlc3NTdHIJAQAAABxmYWN0b3J5UmVhZEFzc2V0Q2ZnQnlBZGRyZXNzAAAAAQUAAAAPYXNzZXRBZGRyZXNzU3RyAQAAACdmYWN0b3J5UmVhZE5leHRQb29sTWFrZXJUb0Rpc3RyaWJ1dGVGZWUAAAABAAAAD2Fzc2V0QWRkcmVzc1N0cgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQIAAAAjM01zYkZNc3R3bTNGSFBKWG1NZlRneWF3N3pRcnBaZmt3bngBAAAAImZhY3RvcnlSZWFkRGVmb1N0YWtpbmdQYWNlbWFrZXJQdWIAAAAACQACWQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAApmYWN0b3J5QWNjCQEAAAAha2V5RmFjdG9yeURlZm9TdGFraW5nUGFjZW1ha2VyUHViAAAAAAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAVTm8gY29uZmlnIGF0IGZhY3Rvcnk9CQAEJQAAAAEFAAAACmZhY3RvcnlBY2MCAAAACSBmb3Iga2V5PQkBAAAAIWtleUZhY3RvcnlEZWZvU3Rha2luZ1BhY2VtYWtlclB1YgAAAAAAAAAAEElkeERlZm9Bc3NldENvZGUAAAAAAAAAAAEAAAAADklkeERlZm9Bc3NldElkAAAAAAAAAAACAAAAABJJZHhEZWZvQXNzZXRTdGF0dXMAAAAAAAAAAAMAAAAAEElkeFByaWNlRGVjaW1hbHMAAAAAAAAAAAQAAAAADklkeEJhc2VBc3NldElkAAAAAAAAAAAFAAAAABhJZHhPdmVyQ29sbGF0ZXJhbFBlcmNlbnQAAAAAAAAAAAYAAAAADklkeE1pbkluaXRQb29sAAAAAAAAAAAHAAAAABVJZHhQcmljZU9yYWNsZUFkZHJlc3MAAAAAAAAAAAgAAAAAEElkeE1pbkJ1eVBheW1lbnQAAAAAAAAAAAkAAAAAEUlkeE1pblNlbGxQYXltZW50AAAAAAAAAAAKAAAAABJJZHhCdXlMb2NrSW50ZXJ2YWwAAAAAAAAAAAsAAAAAE0lkeFNlbGxMb2NrSW50ZXJ2YWwAAAAAAAAAAAwAAAAAEElkeEJ1eUZlZVBlcmNlbnQAAAAAAAAAAA0AAAAAEUlkeFNlbGxGZWVQZXJjZW50AAAAAAAAAAAOAAAAABhJZHhQb29sUmVkZW1wdGlvblRpbWVvdXQAAAAAAAAAAA8AAAAAIUlkeFdlZWtlbmRzUHJpY2VDaGFuZ2VDb2VmZmljaWVudAAAAAAAAAAAEAAAAAAYSWR4QXNzZXRBY2NvdW50UHVibGljU3RyAAAAAAAAAAARAAAAACBJZHhBc3NldFN0YWtpbmdSZWZlcnJhbFB1YmxpY1N0cgAAAAAAAAAAEgAAAAAbSWR4Q3Jvc3NFeGNoYW5nZUNvZWZmaWNpZW50AAAAAAAAAAATAAAAACNJZHhTdGFraW5nTWluQW10RnJvbVNlbGxDb2VmZmljaWVudAAAAAAAAAAAFAAAAAAXSWR4UG9vbFN0YWJpbGl0eUZlZVBhcnQAAAAAAAAAABUAAAAADHRoaXNDZmdBcnJheQkBAAAAHGZhY3RvcnlSZWFkQXNzZXRDZmdCeUFkZHJlc3MAAAABCQAEJQAAAAEFAAAABHRoaXMAAAAADWRlZm9Bc3NldENvZGUJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABBJZHhEZWZvQXNzZXRDb2RlAAAAAA5kZWZvQXNzZXRJZFN0cgkAAZEAAAACBQAAAAx0aGlzQ2ZnQXJyYXkFAAAADklkeERlZm9Bc3NldElkAAAAAAtkZWZvQXNzZXRJZAkAAlkAAAABBQAAAA5kZWZvQXNzZXRJZFN0cgAAAAAOcHJpY2VPcmFjbGVBY2MJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABVJZHhQcmljZU9yYWNsZUFkZHJlc3MAAAAAFW92ZXJDb2xsYXRlcmFsUGVyY2VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAAYSWR4T3ZlckNvbGxhdGVyYWxQZXJjZW50AAAAAA5iYXNlQXNzZXRJZFN0cgkAAZEAAAACBQAAAAx0aGlzQ2ZnQXJyYXkFAAAADklkeEJhc2VBc3NldElkAAAAAAtiYXNlQXNzZXRJZAkAAlkAAAABBQAAAA5iYXNlQXNzZXRJZFN0cgAAAAANcHJpY2VEZWNpbWFscwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAAQSWR4UHJpY2VEZWNpbWFscwAAAAARbWluQmFzaWNCdXlBbW91bnQJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAx0aGlzQ2ZnQXJyYXkFAAAAEElkeE1pbkJ1eVBheW1lbnQAAAAAEm1pblN5bnRoU2VsbEFtb3VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAARSWR4TWluU2VsbFBheW1lbnQAAAAAD2J1eUxvY2tJbnRlcnZhbAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAASSWR4QnV5TG9ja0ludGVydmFsAAAAABBzZWxsTG9ja0ludGVydmFsCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABNJZHhTZWxsTG9ja0ludGVydmFsAAAAAA1idXlGZWVQZXJjZW50CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABBJZHhCdXlGZWVQZXJjZW50AAAAAA5zZWxsRmVlUGVyY2VudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAARSWR4U2VsbEZlZVBlcmNlbnQAAAAAHndlZWtlbmRzUHJpY2VDaGFuZ2VDb2VmZmljaWVudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAAhSWR4V2Vla2VuZHNQcmljZUNoYW5nZUNvZWZmaWNpZW50AAAAABVhc3NldEFjY291bnRQdWJsaWNTdHIJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABhJZHhBc3NldEFjY291bnRQdWJsaWNTdHIAAAAAHWFzc2V0U3Rha2luZ1JlZmVycmFsUHVibGljU3RyCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAAgSWR4QXNzZXRTdGFraW5nUmVmZXJyYWxQdWJsaWNTdHIAAAAAGGNyb3NzRXhjaGFuZ2VDb2VmZmljaWVudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAAbSWR4Q3Jvc3NFeGNoYW5nZUNvZWZmaWNpZW50AAAAACBzdGFraW5nTWluQW10RnJvbVNlbGxDb2VmZmljaWVudAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADHRoaXNDZmdBcnJheQUAAAAjSWR4U3Rha2luZ01pbkFtdEZyb21TZWxsQ29lZmZpY2llbnQAAAAAFHBvb2xTdGFiaWxpdHlGZWVQYXJ0CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABdJZHhQb29sU3RhYmlsaXR5RmVlUGFydAEAAAAMa2V5SXNCbG9ja2VkAAAAAAIAAAANJXNfX2lzQmxvY2tlZAEAAAARa2V5SXNNYXJrZXRPcGVuZWQAAAABAAAACWFzc2V0Q29kZQkAASwAAAACAgAAABYlcyVzX19pc01hcmtldE9wZW5lZF9fBQAAAAlhc3NldENvZGUAAAAACWlzQmxvY2tlZAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACBQAAAA5wcmljZU9yYWNsZUFjYwkBAAAADGtleUlzQmxvY2tlZAAAAAAHAAAAAA5pc01hcmtldE9wZW5lZAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACBQAAAA5wcmljZU9yYWNsZUFjYwkBAAAAEWtleUlzTWFya2V0T3BlbmVkAAAAAQUAAAANZGVmb0Fzc2V0Q29kZQcBAAAAE2NvbnRyb2xBY2NSZWFkUHJpY2UAAAABAAAACWFzc2V0Q29kZQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAADnByaWNlT3JhY2xlQWNjCQEAAAAIa2V5UHJpY2UAAAABBQAAAAlhc3NldENvZGUJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAGE5vIHByaWNlIGF0IHByaWNlT3JhY2xlPQkABCUAAAABBQAAAA5wcmljZU9yYWNsZUFjYwIAAAAJIGZvciBrZXk9CQEAAAAIa2V5UHJpY2UAAAABBQAAAAlhc3NldENvZGUBAAAAGGNvbnRyb2xBY2NSZWFkTGFzdEhlaWdodAAAAAEAAAAJYXNzZXRDb2RlCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAOcHJpY2VPcmFjbGVBY2MJAQAAABRrZXlDb250cm9sTGFzdEhlaWdodAAAAAEFAAAACWFzc2V0Q29kZQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAdTm8gbGFzdEhlaWdodCBhdCBwcmljZU9yYWNsZT0JAAQlAAAAAQUAAAAOcHJpY2VPcmFjbGVBY2MCAAAACSBmb3Iga2V5PQkBAAAAFGtleUNvbnRyb2xMYXN0SGVpZ2h0AAAAAQUAAAAJYXNzZXRDb2RlAQAAABtjb250cm9sQWNjUmVhZEN1cnJJZHhPckZhaWwAAAAACQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAOcHJpY2VPcmFjbGVBY2MCAAAAB2N1cnJJZHgJAAEsAAAAAgIAAAAZTm8gY3VycklkeCBhdCBjb250cm9sQWNjPQkABCUAAAABBQAAAA5wcmljZU9yYWNsZUFjYwEAAAAXY29udHJvbEFjY1JlYWRJZHhIZWlnaHQAAAABAAAAA2lkeAQAAAAMaWR4SGVpZ2h0S2V5CQABLAAAAAICAAAACmlkeEhlaWdodF8JAAGkAAAAAQUAAAADaWR4CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAADnByaWNlT3JhY2xlQWNjBQAAAAxpZHhIZWlnaHRLZXkAAAAAAAAAAAABAAAAG2NvbnRyb2xBY2NSZWFkUHJpY2VCeUhlaWdodAAAAAEAAAALcHJpY2VIZWlnaHQEAAAAEHByaWNlQnlIZWlnaHRLZXkJAAEsAAAAAgIAAAAGcHJpY2VfCQABpAAAAAEFAAAAC3ByaWNlSGVpZ2h0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAOcHJpY2VPcmFjbGVBY2MFAAAAEHByaWNlQnlIZWlnaHRLZXkJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAA05vIAUAAAAQcHJpY2VCeUhlaWdodEtleQIAAAAPIGF0IGNvbnRyb2xBY2M9CQAEJQAAAAEFAAAADnByaWNlT3JhY2xlQWNjAAAAAA9wcmljZUxhc3RIZWlnaHQJAQAAABhjb250cm9sQWNjUmVhZExhc3RIZWlnaHQAAAABBQAAAA1kZWZvQXNzZXRDb2RlAAAAABVpc0Jsb2NrZWRCeUxhc3RIZWlnaHQJAABmAAAAAgkAAGUAAAACBQAAAA9wcmljZUxhc3RIZWlnaHQFAAAAD3ByaWNlTGFzdEhlaWdodAAAAAAAAAAABQAAAAAVa2V5RGVmb1N0YWtpbmdBZGRyZXNzAgAAACYlcyVzX19jb21tb25Db25maWdfX2RlZm9TdGFraW5nQWRkcmVzcwAAAAAZa2V5TmV1dHJpbm9TdGFraW5nQWRkcmVzcwIAAAAqJXMlc19fY29tbW9uQ29uZmlnX19uZXV0cmlub1N0YWtpbmdBZGRyZXNzAQAAABprZXlEZWZvU3Rha2luZ0Fzc2V0QmFsYW5jZQAAAAEAAAAHYXNzZXRJZAkAASwAAAACAgAAABYlcyVzX19zdGFraW5nQmFsYW5jZV9fBQAAAAdhc3NldElkAQAAABlrZXlOZXV0cmlub1N0YWtpbmdCYWxhbmNlAAAAAAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAMcnBkX2JhbGFuY2VfBQAAAA5iYXNlQXNzZXRJZFN0cgIAAAABXwkABCUAAAABBQAAAAR0aGlzAAAAAA5kZWZvU3Rha2luZ0FjYwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEJgAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAApmYWN0b3J5QWNjBQAAABVrZXlEZWZvU3Rha2luZ0FkZHJlc3MJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAF05vIGNvbmZpZyBhdCBmYWN0b3J5QWNjCQAEJQAAAAEFAAAACmZhY3RvcnlBY2MCAAAACSBmb3Iga2V5PQUAAAAVa2V5RGVmb1N0YWtpbmdBZGRyZXNzCQABLAAAAAICAAAAIWFkZHJlc3MgZXh0cmFjdGlvbiBlcnJvciBmb3Iga2V5PQUAAAAVa2V5RGVmb1N0YWtpbmdBZGRyZXNzAAAAABJuZXV0cmlub1N0YWtpbmdBY2MJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAKZmFjdG9yeUFjYwUAAAAZa2V5TmV1dHJpbm9TdGFraW5nQWRkcmVzcwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAXTm8gY29uZmlnIGF0IGZhY3RvcnlBY2MJAAQlAAAAAQUAAAAKZmFjdG9yeUFjYwIAAAAJIGZvciBrZXk9BQAAABlrZXlOZXV0cmlub1N0YWtpbmdBZGRyZXNzCQABLAAAAAICAAAAIWFkZHJlc3MgZXh0cmFjdGlvbiBlcnJvciBmb3Iga2V5PQUAAAAZa2V5TmV1dHJpbm9TdGFraW5nQWRkcmVzcwEAAAAZZ2V0VGhpc0RlZm9TdGFraW5nQmFsYW5jZQAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAOZGVmb1N0YWtpbmdBY2MJAQAAABprZXlEZWZvU3Rha2luZ0Fzc2V0QmFsYW5jZQAAAAEFAAAADmRlZm9Bc3NldElkU3RyAAAAAAAAAAAAAQAAAB1nZXRUaGlzTmV1dHJpbm9TdGFraW5nQmFsYW5jZQAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAASbmV1dHJpbm9TdGFraW5nQWNjCQEAAAAZa2V5TmV1dHJpbm9TdGFraW5nQmFsYW5jZQAAAAAAAAAAAAAAAAAAAAAAC3Vjb2xsYXRlcmFsCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAAA5rZXlVY29sbGF0ZXJhbAAAAAAAAAAAAAAAAAAAAAAADmFjY3VtdWxhdGVkRmVlCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAQAAABFrZXlBY2N1bXVsYXRlZEZlZQAAAAAAAAAAAAAAAAAAAAAADmN1cnJQb29sQW1vdW50CQEAAAARQGV4dHJOYXRpdmUoMTA1MCkAAAACBQAAAApmYWN0b3J5QWNjCQEAAAAaa2V5RmFjdG9yeUFzc2V0Q3VycmVudFBvb2wAAAABBQAAAAR0aGlzAAAAAAtkZWJ0QXNzZXRJZAkAAlkAAAABCQEAAAAWZmFjdG9yeVJlYWREZWJ0QXNzZXRJZAAAAAAAAAAAFmRlYnRBc3NldEV0YWxvbkJhbGFuY2UJAQAAABFAZXh0ck5hdGl2ZSgxMDUwKQAAAAIFAAAACmZhY3RvcnlBY2MJAQAAACBrZXlGYWN0b3J5RGVidEFzc2V0RXRhbG9uQmFsYW5jZQAAAAAAAAAAEmxlbmRlZE9yRGVidEFtb3VudAkAAGUAAAACBQAAABZkZWJ0QXNzZXRFdGFsb25CYWxhbmNlCQAD8AAAAAIFAAAABHRoaXMFAAAAC2RlYnRBc3NldElkAAAAABdjdXJyZW50QmFzZUFzc2V0QmFsYW5jZQkAAGQAAAACCQAAZAAAAAIJAAPwAAAAAgUAAAAEdGhpcwUAAAALYmFzZUFzc2V0SWQJAQAAAB1nZXRUaGlzTmV1dHJpbm9TdGFraW5nQmFsYW5jZQAAAAAFAAAAEmxlbmRlZE9yRGVidEFtb3VudAAAAAAMY29udHJvbFByaWNlCQEAAAATY29udHJvbEFjY1JlYWRQcmljZQAAAAEJAAGRAAAAAgUAAAAMdGhpc0NmZ0FycmF5BQAAABBJZHhEZWZvQXNzZXRDb2RlAAAAAAhlbWlzc2lvbgkAAGUAAAACCAkBAAAABXZhbHVlAAAAAQkAA+wAAAABBQAAAAtkZWZvQXNzZXRJZAAAAAhxdWFudGl0eQkAA/AAAAACBQAAAAR0aGlzBQAAAAtkZWZvQXNzZXRJZAEAAAALZ2V0QnV5UHJpY2UAAAABAAAAC2NoYW5nZUNvZWZmAwUAAAAOaXNNYXJrZXRPcGVuZWQFAAAADGNvbnRyb2xQcmljZQkAAGsAAAADCQAAZQAAAAIFAAAADXByaWNlRGVjaW1hbHMFAAAAC2NoYW5nZUNvZWZmBQAAAAxjb250cm9sUHJpY2UFAAAADXByaWNlRGVjaW1hbHMBAAAAI2dldEJ1eUZlZUNvbnNpZGVyaW5nU3Rha2luZ1JlZmVycmFsAAAAAQAAAA5jYWxsZXJQdWI1OFN0cgMJAAAAAAAAAgUAAAAdYXNzZXRTdGFraW5nUmVmZXJyYWxQdWJsaWNTdHIFAAAADmNhbGxlclB1YjU4U3RyAAAAAAAAAAAABQAAAA1idXlGZWVQZXJjZW50AQAAACVnZXRCdXlQcmljZUNvbnNpZGVyaW5nU3Rha2luZ1JlZmVycmFsAAAAAgAAAAtjaGFuZ2VDb2VmZgAAAA5jYWxsZXJQdWI1OFN0cgMJAAAAAAAAAgUAAAAdYXNzZXRTdGFraW5nUmVmZXJyYWxQdWJsaWNTdHIFAAAADmNhbGxlclB1YjU4U3RyBQAAAAxjb250cm9sUHJpY2UJAQAAAAtnZXRCdXlQcmljZQAAAAEFAAAAC2NoYW5nZUNvZWZmAQAAAAxnZXRTZWxsUHJpY2UAAAABAAAAC2NoYW5nZUNvZWZmAwUAAAAOaXNNYXJrZXRPcGVuZWQFAAAADGNvbnRyb2xQcmljZQkAAGsAAAADCQAAZAAAAAIFAAAADXByaWNlRGVjaW1hbHMFAAAAC2NoYW5nZUNvZWZmBQAAAAxjb250cm9sUHJpY2UFAAAADXByaWNlRGVjaW1hbHMBAAAAEGdldFNlbGxQcmljZUZyb20AAAACAAAACWZyb21QcmljZQAAAAtjaGFuZ2VDb2VmZgMFAAAADmlzTWFya2V0T3BlbmVkBQAAAAlmcm9tUHJpY2UJAABrAAAAAwkAAGQAAAACBQAAAA1wcmljZURlY2ltYWxzBQAAAAtjaGFuZ2VDb2VmZgUAAAAJZnJvbVByaWNlBQAAAA1wcmljZURlY2ltYWxzAQAAABBpbnRlcm5hbEJ1eUFzc2V0AAAABgAAAApzZWxsZXJBZGRyAAAAB3NlbGxBbXQAAAALc2VsbEFzc2V0SWQAAAAKbWluU2VsbEFtdAAAAA1idXkyc2VsbFByaWNlAAAAEXBvb2xNYWtlcnNGZWVQYXJ0BAAAABRkZWZvQXNzZXRBbW91bnRHcm9zcwkAAGsAAAADBQAAAAdzZWxsQW10BQAAAA1idXkyc2VsbFByaWNlBQAAAA1wcmljZURlY2ltYWxzBAAAABZzdGFiaWxpdHlGZWVEZWZvQW1vdW50CQAAawAAAAMFAAAAFHBvb2xTdGFiaWxpdHlGZWVQYXJ0BQAAABRkZWZvQXNzZXRBbW91bnRHcm9zcwUAAAANcHJpY2VEZWNpbWFscwQAAAAXcG9vbE1ha2Vyc0ZlZURlZm9BbW91bnQJAABrAAAAAwUAAAARcG9vbE1ha2Vyc0ZlZVBhcnQFAAAAFGRlZm9Bc3NldEFtb3VudEdyb3NzBQAAAA1wcmljZURlY2ltYWxzBAAAAA9kZWZvQXNzZXRBbW91bnQJAABlAAAAAgkAAGUAAAACBQAAABRkZWZvQXNzZXRBbW91bnRHcm9zcwUAAAAWc3RhYmlsaXR5RmVlRGVmb0Ftb3VudAUAAAAXcG9vbE1ha2Vyc0ZlZURlZm9BbW91bnQEAAAAGHJlcXVpcmVkQmFzaWNBc3NldEFtb3VudAkAAGsAAAADBQAAABRkZWZvQXNzZXRBbW91bnRHcm9zcwUAAAANcHJpY2VEZWNpbWFscwUAAAANYnV5MnNlbGxQcmljZQQAAAAGY2hhbmdlCQAAZQAAAAIFAAAAB3NlbGxBbXQFAAAAGHJlcXVpcmVkQmFzaWNBc3NldEFtb3VudAMDCQAAZgAAAAIFAAAACm1pblNlbGxBbXQFAAAAB3NlbGxBbXQJAQAAAAIhPQAAAAIJAAQlAAAAAQUAAAAKc2VsbGVyQWRkcgkABCUAAAABBQAAAA5kZWZvU3Rha2luZ0FjYwcJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAGGltcG9zc2libGUgdG8gaXNzdWUgbmV3IAUAAAANZGVmb0Fzc2V0Q29kZQIAAAAKOiBwYXltZW50PQkAAaQAAAABBQAAAAdzZWxsQW10AgAAABhpcyBsZXNzIHRoZW4gbWluIGFtb3VudD0JAAGkAAAAAQUAAAAKbWluU2VsbEFtdAkABRQAAAACCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAOa2V5VWNvbGxhdGVyYWwAAAAACQAAZAAAAAIFAAAAC3Vjb2xsYXRlcmFsBQAAABhyZXF1aXJlZEJhc2ljQXNzZXRBbW91bnQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAE2tleUFjY291bnRPcGVyYXRpb24AAAADBQAAAAZoZWlnaHQJAAQlAAAAAQUAAAAKc2VsbGVyQWRkcgIAAAAIRklOSVNIRUQJAQAAABZhc3NldERhdGFTd2FwT3BlcmF0aW9uAAAABwUAAAAHc2VsbEFtdAkAAlgAAAABBQAAAAtzZWxsQXNzZXRJZAUAAAAMY29udHJvbFByaWNlBQAAAA9kZWZvQXNzZXRBbW91bnQJAAJYAAAAAQUAAAALZGVmb0Fzc2V0SWQFAAAAFGRlZm9Bc3NldEFtb3VudEdyb3NzBQAAABdwb29sTWFrZXJzRmVlRGVmb0Ftb3VudAkABEwAAAACCQEAAAAHUmVpc3N1ZQAAAAMFAAAAC2RlZm9Bc3NldElkCQAAZAAAAAIFAAAAD2RlZm9Bc3NldEFtb3VudAUAAAAXcG9vbE1ha2Vyc0ZlZURlZm9BbW91bnQGCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMFAAAACnNlbGxlckFkZHIFAAAAD2RlZm9Bc3NldEFtb3VudAUAAAALZGVmb0Fzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAKc2VsbGVyQWRkcgUAAAAGY2hhbmdlBQAAAAtzZWxsQXNzZXRJZAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAnZmFjdG9yeVJlYWROZXh0UG9vbE1ha2VyVG9EaXN0cmlidXRlRmVlAAAAAQkABCUAAAABBQAAAAR0aGlzBQAAABdwb29sTWFrZXJzRmVlRGVmb0Ftb3VudAUAAAALZGVmb0Fzc2V0SWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABFrZXlBY2N1bXVsYXRlZEZlZQAAAAAJAABkAAAAAgUAAAAOYWNjdW11bGF0ZWRGZWUFAAAAF3Bvb2xNYWtlcnNGZWVEZWZvQW1vdW50BQAAAANuaWwFAAAABmNoYW5nZQAAAAUAAAABaQEAAAAIYnV5QXNzZXQAAAAACQAAAgAAAAECAAAAL05HTiBidXlBc3NldCBvcGVyYXRpb24gaXMgdGVtcG9yYXJ5IHVuYXZhaWxhYmxlAAAAAWkBAAAACXNlbGxBc3NldAAAAAAEAAAAA3BtdAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAAIcG10QXNzZXQJAQAAAAV2YWx1ZQAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAQAAAANY2FsbGVyQWRkcmVzcwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAACXNlbGxQcmljZQkBAAAADGdldFNlbGxQcmljZQAAAAEFAAAAHndlZWtlbmRzUHJpY2VDaGFuZ2VDb2VmZmljaWVudAMFAAAACWlzQmxvY2tlZAkAAAIAAAABAgAAAFpjb250cmFjdCBpcyBibG9ja2VkIGJ5IEVNRVJHRU5DWSBTSFVURE9XTiBhY3Rpb25zIHVudGlsbCByZWFjdGl2YXRpb24gYnkgZW1lcmdlbmN5IG9yYWNsZXMDCQEAAAACIT0AAAACBQAAAAhwbXRBc3NldAUAAAALZGVmb0Fzc2V0SWQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAjSW52YWxpZCBwYXltZW50IGFzc2V0IGlkOiBleHBlY3RlZD0JAAJYAAAAAQUAAAALZGVmb0Fzc2V0SWQCAAAACCBhY3R1YWw9CQACWAAAAAEFAAAACHBtdEFzc2V0AwkAAGYAAAACBQAAABJtaW5TeW50aFNlbGxBbW91bnQIBQAAAANwbXQAAAAGYW1vdW50CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAOlBheW1lbnQgYW1vdW50IGxlc3MgdGhlbiBtaW5pbmltYWwgYWxsb3dlZDogcGF5bWVudEFtb3VudD0JAAGkAAAAAQgFAAAAA3BtdAAAAAZhbW91bnQCAAAACyBtaW5BbW91bnQ9CQABpAAAAAEFAAAAEm1pblN5bnRoU2VsbEFtb3VudAQAAAAdYmFzZUFzc2V0QW1vdW50Tm9CYWxhbmNlTGltaXQJAABrAAAAAwgFAAAAA3BtdAAAAAZhbW91bnQFAAAADXByaWNlRGVjaW1hbHMFAAAACXNlbGxQcmljZQQAAAAYYmFzZUFzc2V0QW1vdW50QXZhaWxhYmxlAwkAAGYAAAACBQAAAB1iYXNlQXNzZXRBbW91bnROb0JhbGFuY2VMaW1pdAUAAAAXY3VycmVudEJhc2VBc3NldEJhbGFuY2UFAAAAF2N1cnJlbnRCYXNlQXNzZXRCYWxhbmNlBQAAAB1iYXNlQXNzZXRBbW91bnROb0JhbGFuY2VMaW1pdAQAAAAYc29sZERlZm9Bc3NldEFtb3VudEdyb3NzCQAAawAAAAMFAAAAGGJhc2VBc3NldEFtb3VudEF2YWlsYWJsZQUAAAAJc2VsbFByaWNlBQAAAA1wcmljZURlY2ltYWxzBAAAAAZjaGFuZ2UJAABlAAAAAggFAAAAA3BtdAAAAAZhbW91bnQFAAAAGHNvbGREZWZvQXNzZXRBbW91bnRHcm9zcwQAAAAWc3RhYmlsaXR5RmVlRGVmb0Ftb3VudAkAAGsAAAADBQAAABRwb29sU3RhYmlsaXR5RmVlUGFydAUAAAAYc29sZERlZm9Bc3NldEFtb3VudEdyb3NzBQAAAA1wcmljZURlY2ltYWxzBAAAABdwb29sTWFrZXJzRmVlRGVmb0Ftb3VudAkAAGsAAAADBQAAAA5zZWxsRmVlUGVyY2VudAUAAAAYc29sZERlZm9Bc3NldEFtb3VudEdyb3NzBQAAAA1wcmljZURlY2ltYWxzBAAAABNzb2xkRGVmb0Fzc2V0QW1vdW50CQAAZQAAAAIJAABlAAAAAgUAAAAYc29sZERlZm9Bc3NldEFtb3VudEdyb3NzBQAAABZzdGFiaWxpdHlGZWVEZWZvQW1vdW50BQAAABdwb29sTWFrZXJzRmVlRGVmb0Ftb3VudAQAAAAVYmFzZUFzc2V0QW1vdW50VG9TZW5kCQAAawAAAAMFAAAAE3NvbGREZWZvQXNzZXRBbW91bnQFAAAADXByaWNlRGVjaW1hbHMFAAAACXNlbGxQcmljZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAADmtleVVjb2xsYXRlcmFsAAAAAAkAAGUAAAACBQAAAAt1Y29sbGF0ZXJhbAUAAAAVYmFzZUFzc2V0QW1vdW50VG9TZW5kCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABNrZXlBY2NvdW50T3BlcmF0aW9uAAAAAwUAAAAGaGVpZ2h0BQAAAA1jYWxsZXJBZGRyZXNzAgAAAAhGSU5JU0hFRAkBAAAAFmFzc2V0RGF0YVN3YXBPcGVyYXRpb24AAAAHCAUAAAADcG10AAAABmFtb3VudAkAAlgAAAABBQAAAAhwbXRBc3NldAUAAAAJc2VsbFByaWNlBQAAABViYXNlQXNzZXRBbW91bnRUb1NlbmQFAAAADmJhc2VBc3NldElkU3RyBQAAABhzb2xkRGVmb0Fzc2V0QW1vdW50R3Jvc3MFAAAAF3Bvb2xNYWtlcnNGZWVEZWZvQW1vdW50CQAETAAAAAIJAQAAAARCdXJuAAAAAgUAAAALZGVmb0Fzc2V0SWQJAABkAAAAAgUAAAATc29sZERlZm9Bc3NldEFtb3VudAUAAAAWc3RhYmlsaXR5RmVlRGVmb0Ftb3VudAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAFWJhc2VBc3NldEFtb3VudFRvU2VuZAUAAAALYmFzZUFzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAZjaGFuZ2UFAAAAC2RlZm9Bc3NldElkCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMJAQAAACdmYWN0b3J5UmVhZE5leHRQb29sTWFrZXJUb0Rpc3RyaWJ1dGVGZWUAAAABCQAEJQAAAAEFAAAABHRoaXMFAAAAF3Bvb2xNYWtlcnNGZWVEZWZvQW1vdW50BQAAAAtkZWZvQXNzZXRJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAEWtleUFjY3VtdWxhdGVkRmVlAAAAAAkAAGQAAAACBQAAAA5hY2N1bXVsYXRlZEZlZQUAAAAXcG9vbE1ha2Vyc0ZlZURlZm9BbW91bnQFAAAAA25pbAAAAAFpAQAAAA1jcm9zc0V4Y2hhbmdlAAAAAgAAABNidXlBc3NldENvZGVDb25maXJtAAAAFHNlbGxBc3NldENvZGVDb25maXJtCQAAAgAAAAECAAAANE5HTiBjcm9zc0V4Y2hhbmdlIG9wZXJhdGlvbiBpcyB0ZW1wb3JhcnkgdW5hdmFpbGFibGUAAAABaQEAAAAOcmViYWxhbmNlRGVidHMAAAAABAAAAAhkZWJ0UG10MAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAANZGVidFBtdEFzc2V0MAkBAAAABXZhbHVlAAAAAQgFAAAACGRlYnRQbXQwAAAAB2Fzc2V0SWQEAAAACGJhc2VQbXQxCQEAAAAFdmFsdWUAAAABCQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABBAAAAA1iYXNlUG10QXNzZXQxCQEAAAAFdmFsdWUAAAABCAUAAAAIYmFzZVBtdDEAAAAHYXNzZXRJZAQAAAANZGVidG9yQWRkcmVzcwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAADmRlYnRvckFzc2V0Q2ZnCQEAAAAcZmFjdG9yeVJlYWRBc3NldENmZ0J5QWRkcmVzcwAAAAEFAAAADWRlYnRvckFkZHJlc3MEAAAAD2RlYnRvckFzc2V0Q29kZQkAAZEAAAACBQAAAA5kZWJ0b3JBc3NldENmZwUAAAAQSWR4RGVmb0Fzc2V0Q29kZQQAAAAabGVuZGVkQW1vdW50QnlBc3NldENvZGVLZXkJAQAAABprZXlMZW5kZWRBbW91bnRCeUFzc2V0Q29kZQAAAAEFAAAAD2RlYnRvckFzc2V0Q29kZQQAAAAJbGVuZGVkQW10CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwUAAAAabGVuZGVkQW1vdW50QnlBc3NldENvZGVLZXkJAAEsAAAAAgIAAAANTm8gZGVidHMgZm9yIAUAAAAPZGVidG9yQXNzZXRDb2RlAwUAAAAJaXNCbG9ja2VkCQAAAgAAAAECAAAAWmNvbnRyYWN0IGlzIGJsb2NrZWQgYnkgRU1FUkdFTkNZIFNIVVRET1dOIGFjdGlvbnMgdW50aWxsIHJlYWN0aXZhdGlvbiBieSBlbWVyZ2VuY3kgb3JhY2xlcwMJAQAAAAIhPQAAAAIFAAAAC2RlYnRBc3NldElkBQAAAA1kZWJ0UG10QXNzZXQwCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAANGludmFsaWQgZGVidCBhc3NldCBpZCBpbiB0aGUgZmlyc3QgcGF5bWV0OiBleHBlY3RlZD0JAAJYAAAAAQUAAAALZGVidEFzc2V0SWQCAAAACCBhY3R1YWw9CQACWAAAAAEFAAAADWRlYnRQbXRBc3NldDADCQEAAAACIT0AAAACBQAAAAtiYXNlQXNzZXRJZAUAAAANYmFzZVBtdEFzc2V0MQkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAADZpbnZhbGlkIGJhc2UgYXNzZXQgaWQgaW4gdGhlIHNlY29uZCBwYXltZW50OiBleHBlY3RlZD0JAAJYAAAAAQUAAAALYmFzZUFzc2V0SWQCAAAACCBhY3R1YWw9CQACWAAAAAEFAAAADWJhc2VQbXRBc3NldDEDCQEAAAACIT0AAAACCAUAAAAIZGVidFBtdDAAAAAGYW1vdW50CAUAAAAIYmFzZVBtdDEAAAAGYW1vdW50CQAAAgAAAAECAAAAP2ZpcnN0IHBheW1lbnQgYW1vdW50IGRvZXNuJ3QgbWF0Y2ggdG8gdGhlIHNlY29uZCBwYXltZW50IGFtb3VudAMJAABnAAAAAgAAAAAAAAAAAAUAAAAJbGVuZGVkQW10CQAAAgAAAAEJAAEsAAAAAgIAAAAnbGVuZGVkQW10IGlzIGxlc3MgdGhlbiB6ZXJvOiBsZW5kZWRBbXQ9CQABpAAAAAEFAAAACWxlbmRlZEFtdAMJAABnAAAAAgkAAGgAAAACAAAAAAAAAAABBQAAAA1wcmljZURlY2ltYWxzCAUAAAAIZGVidFBtdDAAAAAGYW1vdW50CQAAAgAAAAEJAAEsAAAAAgIAAAA3YXR0YWNoZWQgcGF5bWVudCBtdXN0IGJlIGdyZWF0ZXIgdGhlbiAxMDA6IHBtdDAuYW1vdW50PQkAAaQAAAABCAUAAAAIZGVidFBtdDAAAAAGYW1vdW50AwkAAGYAAAACCAUAAAAIZGVidFBtdDAAAAAGYW1vdW50BQAAAAlsZW5kZWRBbXQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAA0YXR0YWNoZWQgcGF5bWVudCBpcyBncmF0ZXIgdGhhbiByZXF1aXJlZDogcG10QW1vdW50PQkAAaQAAAABCAUAAAAIZGVidFBtdDAAAAAGYW1vdW50AgAAAAsgbGVuZGVkQW10PQkAAaQAAAABBQAAAAlsZW5kZWRBbXQEAAAAFnRvdGFsTGVuZGVkQXRPdGhlckFjY3MJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwkBAAAAGWtleVRvdGFsTGVuZGVkQXRPdGhlckFjY3MAAAAAAAAAAAAAAAAABAAAAA5sZW5kZWRBbXRBZnRlcgkAAGUAAAACBQAAAAlsZW5kZWRBbXQIBQAAAAhkZWJ0UG10MAAAAAZhbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAGmxlbmRlZEFtb3VudEJ5QXNzZXRDb2RlS2V5BQAAAA5sZW5kZWRBbXRBZnRlcgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAGWtleVRvdGFsTGVuZGVkQXRPdGhlckFjY3MAAAAACQAAZQAAAAIFAAAAFnRvdGFsTGVuZGVkQXRPdGhlckFjY3MIBQAAAAhkZWJ0UG10MAAAAAZhbW91bnQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkAASwAAAACAgAAABYlcyVzX19yZWJhbGFuY2VUcmFjZV9fCQACWAAAAAEIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQJAQAAABdhc3NldERhdGFSZWJhbGFuY2VUcmFjZQAAAAUFAAAAD2RlYnRvckFzc2V0Q29kZQUAAAAIZGVidFBtdDAFAAAACGJhc2VQbXQxBQAAAAlsZW5kZWRBbXQFAAAADmxlbmRlZEFtdEFmdGVyBQAAAANuaWwAAAABaQEAAAAUZnVsZmlsbFJlZGVlbVJlcXVlc3QAAAABAAAAEHBvb2xNYWtlckFkZHJlc3MEAAAADnRoaXNBZGRyZXNzU3RyCQAEJQAAAAEFAAAABHRoaXMEAAAAGHBvb2xNYWtlclVubG9ja0hlaWdodEtleQkBAAAAH2tleUZhY3RvcnlQb29sTWFrZXJVbmxvY2tIZWlnaHQAAAACBQAAAA50aGlzQWRkcmVzc1N0cgUAAAAQcG9vbE1ha2VyQWRkcmVzcwQAAAAVcG9vbE1ha2VyVW5sb2NrSGVpZ2h0CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAACmZhY3RvcnlBY2MFAAAAGHBvb2xNYWtlclVubG9ja0hlaWdodEtleQAAAAAAAAAAAAMJAABnAAAAAgAAAAAAAAAAAAUAAAAVcG9vbE1ha2VyVW5sb2NrSGVpZ2h0CQAAAgAAAAECAAAAH0FsbCBsaXF1aWRpdHkgcmVxdWVzdCBmdWxmaWxsZWQEAAAAHHBvb2xNYWtlckxpcXVpZGl0eVJlcXVlc3RLZXkJAQAAACNrZXlGYWN0b3J5UG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdAAAAAMFAAAADnRoaXNBZGRyZXNzU3RyBQAAABBwb29sTWFrZXJBZGRyZXNzBQAAABVwb29sTWFrZXJVbmxvY2tIZWlnaHQEAAAAH3Bvb2xNYWtlckxpcXVpZGl0eVJlcXVlc3RBbW91bnQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAApmYWN0b3J5QWNjBQAAABxwb29sTWFrZXJMaXF1aWRpdHlSZXF1ZXN0S2V5AgAAADFFbXB0eSBwb29sTWFrZXJMaXF1aWRpdHlSZXF1ZXN0S2V5IGF0IGZhY3RvcnkgYWNjAwkBAAAACWlzRGVmaW5lZAAAAAEJAAQaAAAAAgUAAAAEdGhpcwUAAAAccG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdEtleQkAAAIAAAABAgAAACxMaXF1aWRpdHkgcmVxdWVzdCBoYXMgYmVlbiBhbHJlYWR5IGZ1bGZpbGxlZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAccG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdEtleQUAAAAfcG9vbE1ha2VyTGlxdWlkaXR5UmVxdWVzdEFtb3VudAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAAApmYWN0b3J5QWNjBQAAAB9wb29sTWFrZXJMaXF1aWRpdHlSZXF1ZXN0QW1vdW50BQAAAAtiYXNlQXNzZXRJZAUAAAADbmlsAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAQAAAAHJG1hdGNoMAUAAAACdHgDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAF0ludm9rZVNjcmlwdFRyYW5zYWN0aW9uBAAAAANpbnYFAAAAByRtYXRjaDADCQAAZgAAAAIIBQAAAANpbnYAAAADZmVlCQAAaAAAAAIAAAAAAAAAA4QAAAAAAAAAA+gJAAACAAAAAQkAASwAAAACAgAAAChmZWUgYW1vdW50IGlzIGdyZWF0ZXIgdGhhbiBtYXggYWxsb3dlZDogCQABpAAAAAEIBQAAAANpbnYAAAADZmVlAwkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAANpbnYAAAAKZmVlQXNzZXRJZAkAAAIAAAABAgAAACNvbmx5IFdhdmVzIGlzIGFsbG93ZWQgYXMgZmVlQXNzZXRJZAMJAAAAAAAAAggFAAAAA2ludgAAAAhmdW5jdGlvbgIAAAAOcmViYWxhbmNlRGVidHMEAAAADmludkRhcHBBZGRyZXNzCQAEJQAAAAEJAAQkAAAAAQgFAAAAA2ludgAAAARkQXBwAwkBAAAAAiE9AAAAAgkAAZEAAAACCQEAAAAcZmFjdG9yeVJlYWRBc3NldENmZ0J5QWRkcmVzcwAAAAEFAAAADmludkRhcHBBZGRyZXNzBQAAABJJZHhEZWZvQXNzZXRTdGF0dXMCAAAABklTU1VFRAkAAAIAAAABAgAAABlvbmx5IGRlZm8gZGFwcCBpcyBhbGxvd2VkAwkAAAAAAAACBQAAAA5pbnZEYXBwQWRkcmVzcwkABCUAAAABBQAAAAR0aGlzCQAAAgAAAAECAAAAJWltcG9zc2libGUgdG8gY2FsbCBzZWxmIHJlYmVhbG5jZURlYnQGAwMDCQAAAAAAAAIIBQAAAANpbnYAAAAIZnVuY3Rpb24CAAAADGxvY2tOZXV0cmlubwYJAAAAAAAAAggFAAAAA2ludgAAAAhmdW5jdGlvbgIAAAAObG9ja05ldXRyaW5vU1AGCQAAAAAAAAIIBQAAAANpbnYAAAAIZnVuY3Rpb24CAAAADnVubG9ja05ldXRyaW5vAwkBAAAAAiE9AAAAAgkABCUAAAABBQAAABJuZXV0cmlub1N0YWtpbmdBY2MJAAQlAAAAAQkABCQAAAABCAUAAAADaW52AAAABGRBcHAJAAACAAAAAQIAAAAlaW52YWxpZCBuZXV0cmlubyBzdGFraW5nIGRhcHAgYWRkcmVzcwkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAJAQAAACJmYWN0b3J5UmVhZERlZm9TdGFraW5nUGFjZW1ha2VyUHViAAAAAAkAAAIAAAABAgAAACNOb3QgYWxsb3dlZCBpbnZvY2F0aW9uIG1ldGhvZCBjYWxscwkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAIBQAAAAJ0eAAAAA9zZW5kZXJQdWJsaWNLZXk00LJj", "chainId": 84, "height": 1474710, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: CUZCV8h3PQ3ZPWCYssp1NrHcBeRkdZNygPKHeD79jC7t Next: 8TS9aqjJLh5snokC6uAoEWgx8wfr8BUMn183KvinqZLu Diff:
OldNewDifferences
9595 }
9696
9797
98-func factoryReadNextPoolMakerToDistributeFee (assetAddressStr) = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(factoryAcc, keyFactoryAssetPoolMakers(assetAddressStr)), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryAssetPoolMakers(assetAddressStr)))), ("address extraction error for key=" + keyFactoryAssetPoolMakers(assetAddressStr)))
98+func factoryReadNextPoolMakerToDistributeFee (assetAddressStr) = addressFromStringValue("3MsbFMstwm3FHPJXmMfTgyaw7zQrpZfkwnx")
9999
100100
101101 func factoryReadDefoStakingPacemakerPub () = fromBase58String(valueOrErrorMessage(getString(factoryAcc, keyFactoryDefoStakingPacemakerPub()), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryDefoStakingPacemakerPub())))
133133
134134 let IdxWeekendsPriceChangeCoefficient = 16
135135
136+let IdxAssetAccountPublicStr = 17
137+
138+let IdxAssetStakingReferralPublicStr = 18
139+
140+let IdxCrossExchangeCoefficient = 19
141+
142+let IdxStakingMinAmtFromSellCoefficient = 20
143+
144+let IdxPoolStabilityFeePart = 21
145+
136146 let thisCfgArray = factoryReadAssetCfgByAddress(toString(this))
137147
138148 let defoAssetCode = thisCfgArray[IdxDefoAssetCode]
164174 let sellFeePercent = parseIntValue(thisCfgArray[IdxSellFeePercent])
165175
166176 let weekendsPriceChangeCoefficient = parseIntValue(thisCfgArray[IdxWeekendsPriceChangeCoefficient])
177+
178+let assetAccountPublicStr = thisCfgArray[IdxAssetAccountPublicStr]
179+
180+let assetStakingReferralPublicStr = thisCfgArray[IdxAssetStakingReferralPublicStr]
181+
182+let crossExchangeCoefficient = parseIntValue(thisCfgArray[IdxCrossExchangeCoefficient])
183+
184+let stakingMinAmtFromSellCoefficient = parseIntValue(thisCfgArray[IdxStakingMinAmtFromSellCoefficient])
185+
186+let poolStabilityFeePart = parseIntValue(thisCfgArray[IdxPoolStabilityFeePart])
167187
168188 func keyIsBlocked () = "%s__isBlocked"
169189
243263 else fraction((priceDecimals - changeCoeff), controlPrice, priceDecimals)
244264
245265
266+func getBuyFeeConsideringStakingReferral (callerPub58Str) = if ((assetStakingReferralPublicStr == callerPub58Str))
267+ then 0
268+ else buyFeePercent
269+
270+
271+func getBuyPriceConsideringStakingReferral (changeCoeff,callerPub58Str) = if ((assetStakingReferralPublicStr == callerPub58Str))
272+ then controlPrice
273+ else getBuyPrice(changeCoeff)
274+
275+
246276 func getSellPrice (changeCoeff) = if (isMarketOpened)
247277 then controlPrice
248278 else fraction((priceDecimals + changeCoeff), controlPrice, priceDecimals)
253283 else fraction((priceDecimals + changeCoeff), fromPrice, priceDecimals)
254284
255285
256-func internalBuyAsset (sellerAddr,sellAmt,sellAssetId,minSellAmt,buy2sellPrice,feePercent) = {
286+func internalBuyAsset (sellerAddr,sellAmt,sellAssetId,minSellAmt,buy2sellPrice,poolMakersFeePart) = {
257287 let defoAssetAmountGross = fraction(sellAmt, buy2sellPrice, priceDecimals)
258- let defoAssetAmount = fraction((priceDecimals - feePercent), defoAssetAmountGross, priceDecimals)
259- let feeAmount = (defoAssetAmountGross - defoAssetAmount)
288+ let stabilityFeeDefoAmount = fraction(poolStabilityFeePart, defoAssetAmountGross, priceDecimals)
289+ let poolMakersFeeDefoAmount = fraction(poolMakersFeePart, defoAssetAmountGross, priceDecimals)
290+ let defoAssetAmount = ((defoAssetAmountGross - stabilityFeeDefoAmount) - poolMakersFeeDefoAmount)
260291 let requiredBasicAssetAmount = fraction(defoAssetAmountGross, priceDecimals, buy2sellPrice)
261292 let change = (sellAmt - requiredBasicAssetAmount)
262293 if (if ((minSellAmt > sellAmt))
263294 then (toString(sellerAddr) != toString(defoStakingAcc))
264295 else false)
265296 then throw(((((("impossible to issue new " + defoAssetCode) + ": payment=") + toString(sellAmt)) + "is less then min amount=") + toString(minSellAmt)))
266- else $Tuple2([IntegerEntry(keyUcollateral(), (ucollateral + requiredBasicAssetAmount)), StringEntry(keyAccountOperation(height, toString(sellerAddr), "FINISHED"), assetDataSwapOperation(sellAmt, toBase58String(sellAssetId), controlPrice, defoAssetAmount, toBase58String(defoAssetId), defoAssetAmountGross, feeAmount)), Reissue(defoAssetId, (defoAssetAmount + feeAmount), true), ScriptTransfer(sellerAddr, defoAssetAmount, defoAssetId), ScriptTransfer(sellerAddr, change, sellAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), feeAmount, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + feeAmount))], change)
297+ else $Tuple2([IntegerEntry(keyUcollateral(), (ucollateral + requiredBasicAssetAmount)), StringEntry(keyAccountOperation(height, toString(sellerAddr), "FINISHED"), assetDataSwapOperation(sellAmt, toBase58String(sellAssetId), controlPrice, defoAssetAmount, toBase58String(defoAssetId), defoAssetAmountGross, poolMakersFeeDefoAmount)), Reissue(defoAssetId, (defoAssetAmount + poolMakersFeeDefoAmount), true), ScriptTransfer(sellerAddr, defoAssetAmount, defoAssetId), ScriptTransfer(sellerAddr, change, sellAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), poolMakersFeeDefoAmount, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + poolMakersFeeDefoAmount))], change)
267298 }
268299
269300
270301 @Callable(i)
271-func buyAsset () = {
272- let pmt = value(i.payments[0])
273- let pmtAssetId = value(pmt.assetId)
274- if (isBlocked)
275- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
276- else if (isBlockedByLastHeight)
277- then throw(((("last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)))
278- else if ((pmtAssetId != baseAssetId))
279- then throw(((("Payment asset id doesn't match basic asset: expected=" + toBase58String(baseAssetId)) + " actual=") + toBase58String(pmtAssetId)))
280- else internalBuyAsset(i.caller, pmt.amount, pmtAssetId, minBasicBuyAmount, getBuyPrice(weekendsPriceChangeCoefficient), buyFeePercent)._1
281- }
302+func buyAsset () = throw("NGN buyAsset operation is temporary unavailable")
282303
283304
284305
290311 let sellPrice = getSellPrice(weekendsPriceChangeCoefficient)
291312 if (isBlocked)
292313 then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
293- else if (isBlockedByLastHeight)
294- then throw(((("last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)))
295- else if ((pmtAsset != defoAssetId))
296- then throw(((("Invalid payment asset id: expected=" + toBase58String(defoAssetId)) + " actual=") + toBase58String(pmtAsset)))
297- else if ((minSynthSellAmount > pmt.amount))
298- then throw(((("Payment amount less then mininimal allowed: paymentAmount=" + toString(pmt.amount)) + " minAmount=") + toString(minSynthSellAmount)))
299- else {
300- let baseAssetAmountNoBalanceLimit = fraction(pmt.amount, priceDecimals, sellPrice)
301- let baseAssetAmountAvailable = if ((baseAssetAmountNoBalanceLimit > currentBaseAssetBalance))
302- then currentBaseAssetBalance
303- else baseAssetAmountNoBalanceLimit
304- let soldDefoAssetAmountGross = fraction(baseAssetAmountAvailable, sellPrice, priceDecimals)
305- let change = (pmt.amount - soldDefoAssetAmountGross)
306- let defoAmountFee = fraction(sellFeePercent, soldDefoAssetAmountGross, priceDecimals)
307- let soldDefoAssetAmount = (soldDefoAssetAmountGross - defoAmountFee)
308- let baseAssetAmountToSend = fraction(soldDefoAssetAmount, priceDecimals, sellPrice)
309-[IntegerEntry(keyUcollateral(), (ucollateral - baseAssetAmountToSend)), StringEntry(keyAccountOperation(height, callerAddress, "FINISHED"), assetDataSwapOperation(pmt.amount, toBase58String(pmtAsset), sellPrice, baseAssetAmountToSend, baseAssetIdStr, soldDefoAssetAmountGross, defoAmountFee)), Burn(defoAssetId, soldDefoAssetAmount), ScriptTransfer(i.caller, baseAssetAmountToSend, baseAssetId), ScriptTransfer(i.caller, change, defoAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), defoAmountFee, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + defoAmountFee))]
310- }
314+ else if ((pmtAsset != defoAssetId))
315+ then throw(((("Invalid payment asset id: expected=" + toBase58String(defoAssetId)) + " actual=") + toBase58String(pmtAsset)))
316+ else if ((minSynthSellAmount > pmt.amount))
317+ then throw(((("Payment amount less then mininimal allowed: paymentAmount=" + toString(pmt.amount)) + " minAmount=") + toString(minSynthSellAmount)))
318+ else {
319+ let baseAssetAmountNoBalanceLimit = fraction(pmt.amount, priceDecimals, sellPrice)
320+ let baseAssetAmountAvailable = if ((baseAssetAmountNoBalanceLimit > currentBaseAssetBalance))
321+ then currentBaseAssetBalance
322+ else baseAssetAmountNoBalanceLimit
323+ let soldDefoAssetAmountGross = fraction(baseAssetAmountAvailable, sellPrice, priceDecimals)
324+ let change = (pmt.amount - soldDefoAssetAmountGross)
325+ let stabilityFeeDefoAmount = fraction(poolStabilityFeePart, soldDefoAssetAmountGross, priceDecimals)
326+ let poolMakersFeeDefoAmount = fraction(sellFeePercent, soldDefoAssetAmountGross, priceDecimals)
327+ let soldDefoAssetAmount = ((soldDefoAssetAmountGross - stabilityFeeDefoAmount) - poolMakersFeeDefoAmount)
328+ let baseAssetAmountToSend = fraction(soldDefoAssetAmount, priceDecimals, sellPrice)
329+[IntegerEntry(keyUcollateral(), (ucollateral - baseAssetAmountToSend)), StringEntry(keyAccountOperation(height, callerAddress, "FINISHED"), assetDataSwapOperation(pmt.amount, toBase58String(pmtAsset), sellPrice, baseAssetAmountToSend, baseAssetIdStr, soldDefoAssetAmountGross, poolMakersFeeDefoAmount)), Burn(defoAssetId, (soldDefoAssetAmount + stabilityFeeDefoAmount)), ScriptTransfer(i.caller, baseAssetAmountToSend, baseAssetId), ScriptTransfer(i.caller, change, defoAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), poolMakersFeeDefoAmount, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + poolMakersFeeDefoAmount))]
330+ }
311331 }
312332
313333
314334
315335 @Callable(i)
316-func crossExchange (buyAssetCodeConfirm,sellAssetCodeConfirm) = {
317- let pmt = value(i.payments[0])
318- let pmtAsset = value(pmt.assetId)
319- let pmtAssetStr = toBase58String(pmtAsset)
320- let pmtAmount = pmt.amount
321- let callerAddress = toString(i.caller)
322- let buyAssetCfg = thisCfgArray
323- let sellAssetTuple = factoryReadAssetCfgByCode(sellAssetCodeConfirm)
324- let sellAssetCfg = sellAssetTuple._2
325- let sellAssetAccAddress = valueOrErrorMessage(addressFromString(sellAssetTuple._1), ("couldn't parse address from string for assetCode=" + sellAssetCodeConfirm))
326- let minSellPmt = valueOrErrorMessage(parseInt(sellAssetCfg[IdxMinSellPayment]), ("minSellPmt parsing error: rawVal=" + sellAssetCfg[IdxMinSellPayment]))
327- let sellPriceLastHeight = controlAccReadLastHeight(sellAssetCodeConfirm)
328- let isSellBlockedByLastHeight = ((sellPriceLastHeight - sellPriceLastHeight) > 5)
329- if (isBlocked)
330- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
331- else if ((thisCfgArray[IdxDefoAssetCode] != buyAssetCodeConfirm))
332- then throw(((("buyAsset confirmation failed: buyAssetIdConfirm=" + thisCfgArray[IdxDefoAssetCode]) + " BUT buyAssetId=") + buyAssetCodeConfirm))
333- else if ((sellAssetCfg[IdxDefoAssetId] != pmtAssetStr))
334- then throw(((("sellAsset confirmation failed: sellAssetIdConfirm=" + sellAssetCfg[IdxDefoAssetId]) + "BUT pmtAsset=") + pmtAssetStr))
335- else if ((thisCfgArray[IdxDefoAssetStatus] != "ISSUED"))
336- then throw(((("toAsset has not been issued yet: buyAssetId=" + buyAssetCodeConfirm) + " BUT status=") + thisCfgArray[IdxDefoAssetStatus]))
337- else if ((sellAssetCfg[IdxDefoAssetStatus] != "ISSUED"))
338- then throw(((("fromAssetCfg has not been issued yet: sellAssetId=" + pmtAssetStr) + " BUT status=") + sellAssetCfg[IdxDefoAssetStatus]))
339- else if (isBlockedByLastHeight)
340- then throw(((((("buy last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)) + " buyCode=") + buyAssetCodeConfirm))
341- else if (isSellBlockedByLastHeight)
342- then throw(((((("sell last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)) + " sellCode=") + sellAssetCodeConfirm))
343- else {
344- let buyAssetUsdPrice = getBuyPrice((weekendsPriceChangeCoefficient / 2))
345- let sellAssetUsdPrice = getSellPriceFrom(controlAccReadPrice(sellAssetCodeConfirm), (weekendsPriceChangeCoefficient / 2))
346- let buy2sellPrice = fraction(buyAssetUsdPrice, priceDecimals, sellAssetUsdPrice)
347- let usdnDebt = fraction(pmtAmount, priceDecimals, sellAssetUsdPrice)
348- let totalLendedAtOtherAccs = valueOrElse(getInteger(this, keyTotalLendedAtOtherAccs()), 0)
349- let lendedAmountByAssetCodeKey = keyLendedAmountByAssetCode(sellAssetCodeConfirm)
350- let lendedAmtByAssetCode = valueOrElse(getInteger(this, lendedAmountByAssetCodeKey), 0)
351- let sellAssetSellFeePercent = parseIntValue(sellAssetCfg[IdxSellFeePercent])
352- let buyAssetResult = internalBuyAsset(i.caller, pmtAmount, pmtAsset, minSellPmt, buy2sellPrice, fraction((buyFeePercent + sellAssetSellFeePercent), 50, 100))
353- ((((buyAssetResult._1 :+ ScriptTransfer(sellAssetAccAddress, usdnDebt, debtAssetId)) :+ ScriptTransfer(sellAssetAccAddress, (pmtAmount - buyAssetResult._2), pmtAsset)) :+ IntegerEntry(lendedAmountByAssetCodeKey, (lendedAmtByAssetCode + usdnDebt))) :+ IntegerEntry(keyTotalLendedAtOtherAccs(), (totalLendedAtOtherAccs + usdnDebt)))
354- }
355- }
336+func crossExchange (buyAssetCodeConfirm,sellAssetCodeConfirm) = throw("NGN crossExchange operation is temporary unavailable")
356337
357338
358339
377358 then throw("first payment amount doesn't match to the second payment amount")
378359 else if ((0 >= lendedAmt))
379360 then throw(("lendedAmt is less then zero: lendedAmt=" + toString(lendedAmt)))
380- else if (((100 * priceDecimals) >= debtPmt0.amount))
361+ else if (((1 * priceDecimals) >= debtPmt0.amount))
381362 then throw(("attached payment must be greater then 100: pmt0.amount=" + toString(debtPmt0.amount)))
382363 else if ((debtPmt0.amount > lendedAmt))
383364 then throw(((("attached payment is grater than required: pmtAmount=" + toString(debtPmt0.amount)) + " lendedAmt=") + toString(lendedAmt)))
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func keyAccumulatedFee () = "%s__accumulatedFee"
55
66
77 func keyUcollateral () = "%s__ucollateral"
88
99
1010 func keyTotalLendedAtOtherAccs () = "%s__totalLendedAtOtherAccs"
1111
1212
1313 func keyAssetLockedTotal (assetId) = ("%s%s__assetLockedTotal__" + assetId)
1414
1515
1616 func keyAccountOperation (unlockHeight,address,status) = ((((("%s%s%d%s__defoAssetOperation__" + address) + "__") + toString(unlockHeight)) + "__") + status)
1717
1818
1919 func keyFactory () = "%s__factory"
2020
2121
2222 func keyLendedAmountByAssetCode (assetCode) = ("%s%s__lendedBaseAssetAmount__" + assetCode)
2323
2424
2525 func keyPrice (assetCode) = ("%s%s__price__" + assetCode)
2626
2727
2828 func keyControlLastHeight (assetCode) = ("%s%s__lastHeight__" + assetCode)
2929
3030
3131 let IdxOperationAmountIn = 1
3232
3333 let IdxOperationAssetIn = 2
3434
3535 let IdxOperationPrice = 3
3636
3737 let IdxOperationAmountOut = 4
3838
3939 let IdxOperationAssetOut = 5
4040
4141 func assetDataSwapOperation (amountIn,assetIn,price,amountOut,assetOut,bruttoAmount,feeAmount) = makeString(["%d%s%d%s%d%d%d", toString(amountIn), assetIn, toString(amountOut), assetOut, toString(price), toString(bruttoAmount), toString(feeAmount)], "__")
4242
4343
4444 func assetDataRebalanceTrace (debtorAssetCode,debtPmt,basePmt,lendedAmtBefore,lendedAmtAfter) = makeString(["%s%s%d%s%d%d%d", debtorAssetCode, toBase58String(value(debtPmt.assetId)), toString(debtPmt.amount), toBase58String(value(basePmt.assetId)), toString(basePmt.amount), toString(lendedAmtBefore), toString(lendedAmtAfter)], "__")
4545
4646
4747 func assetReadSwapDataArrayOrFail (accOperationKey) = {
4848 let accOperationDataStr = valueOrErrorMessage(getString(this, accOperationKey), ("There is no request for passed arguments: " + accOperationKey))
4949 split(accOperationDataStr, "__")
5050 }
5151
5252
5353 let nullInt = -1
5454
5555 let nullStr = "NULL"
5656
5757 let factoryAcc = addressFromStringValue(valueOrErrorMessage(getString(this, keyFactory()), ((("No config at this=" + toString(this)) + " for key=") + keyFactory())))
5858
5959 func keyFactoryDebtAssetId () = "%s%s__commonConfig__debtAssetId"
6060
6161
6262 func keyFactoryDebtAssetEtalonBalance () = "%s%s__commonConfig__debtAssetEtalonBalance"
6363
6464
6565 func keyFactoryAssetCfg (assetAddressStr) = (("%s%s%s__defoAsset__" + assetAddressStr) + "__config")
6666
6767
6868 func keyFactoryAssetCurrentPool (assetAccAddress) = (("%s%s%s__defoAsset__" + toString(assetAccAddress)) + "__currentPool")
6969
7070
7171 func keyFactoryDefoAddressByAssetCode (assetCode) = (("%s%s%s__defoAsset__" + assetCode) + "__addressByAssetCode")
7272
7373
7474 func keyFactoryAssetPoolMakers (assetAddress) = (("%s%s%s__defoAsset__" + assetAddress) + "__poolMakers")
7575
7676
7777 func keyFactoryDefoStakingPacemakerPub () = "%s%s__commonConfig__defoStakingPacemakerPub"
7878
7979
8080 func keyFactoryPoolMakerLiquidityRequest (assetAddress,poolMakerAddress,h) = makeString(["%s%s%s%d%s__pool", assetAddress, poolMakerAddress, toString(h), "liquidityRequest"], "__")
8181
8282
8383 func keyFactoryPoolMakerUnlockHeight (assetAddress,poolMakerAddress) = makeString(["%s%s%s%s__pool", assetAddress, poolMakerAddress, "unlockHeight"], "__")
8484
8585
8686 func factoryReadDebtAssetId () = valueOrErrorMessage(getString(factoryAcc, keyFactoryDebtAssetId()), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryDebtAssetId()))
8787
8888
8989 func factoryReadAssetCfgByAddress (assetAddressStr) = split(valueOrErrorMessage(getString(factoryAcc, keyFactoryAssetCfg(assetAddressStr)), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryAssetCfg(assetAddressStr))), "__")
9090
9191
9292 func factoryReadAssetCfgByCode (assetCode) = {
9393 let assetAddressStr = valueOrErrorMessage(getString(factoryAcc, keyFactoryDefoAddressByAssetCode(assetCode)), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryDefoAddressByAssetCode(assetCode)))
9494 $Tuple2(assetAddressStr, factoryReadAssetCfgByAddress(assetAddressStr))
9595 }
9696
9797
98-func factoryReadNextPoolMakerToDistributeFee (assetAddressStr) = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(factoryAcc, keyFactoryAssetPoolMakers(assetAddressStr)), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryAssetPoolMakers(assetAddressStr)))), ("address extraction error for key=" + keyFactoryAssetPoolMakers(assetAddressStr)))
98+func factoryReadNextPoolMakerToDistributeFee (assetAddressStr) = addressFromStringValue("3MsbFMstwm3FHPJXmMfTgyaw7zQrpZfkwnx")
9999
100100
101101 func factoryReadDefoStakingPacemakerPub () = fromBase58String(valueOrErrorMessage(getString(factoryAcc, keyFactoryDefoStakingPacemakerPub()), ((("No config at factory=" + toString(factoryAcc)) + " for key=") + keyFactoryDefoStakingPacemakerPub())))
102102
103103
104104 let IdxDefoAssetCode = 1
105105
106106 let IdxDefoAssetId = 2
107107
108108 let IdxDefoAssetStatus = 3
109109
110110 let IdxPriceDecimals = 4
111111
112112 let IdxBaseAssetId = 5
113113
114114 let IdxOverCollateralPercent = 6
115115
116116 let IdxMinInitPool = 7
117117
118118 let IdxPriceOracleAddress = 8
119119
120120 let IdxMinBuyPayment = 9
121121
122122 let IdxMinSellPayment = 10
123123
124124 let IdxBuyLockInterval = 11
125125
126126 let IdxSellLockInterval = 12
127127
128128 let IdxBuyFeePercent = 13
129129
130130 let IdxSellFeePercent = 14
131131
132132 let IdxPoolRedemptionTimeout = 15
133133
134134 let IdxWeekendsPriceChangeCoefficient = 16
135135
136+let IdxAssetAccountPublicStr = 17
137+
138+let IdxAssetStakingReferralPublicStr = 18
139+
140+let IdxCrossExchangeCoefficient = 19
141+
142+let IdxStakingMinAmtFromSellCoefficient = 20
143+
144+let IdxPoolStabilityFeePart = 21
145+
136146 let thisCfgArray = factoryReadAssetCfgByAddress(toString(this))
137147
138148 let defoAssetCode = thisCfgArray[IdxDefoAssetCode]
139149
140150 let defoAssetIdStr = thisCfgArray[IdxDefoAssetId]
141151
142152 let defoAssetId = fromBase58String(defoAssetIdStr)
143153
144154 let priceOracleAcc = addressFromStringValue(thisCfgArray[IdxPriceOracleAddress])
145155
146156 let overCollateralPercent = parseIntValue(thisCfgArray[IdxOverCollateralPercent])
147157
148158 let baseAssetIdStr = thisCfgArray[IdxBaseAssetId]
149159
150160 let baseAssetId = fromBase58String(baseAssetIdStr)
151161
152162 let priceDecimals = parseIntValue(thisCfgArray[IdxPriceDecimals])
153163
154164 let minBasicBuyAmount = parseIntValue(thisCfgArray[IdxMinBuyPayment])
155165
156166 let minSynthSellAmount = parseIntValue(thisCfgArray[IdxMinSellPayment])
157167
158168 let buyLockInterval = parseIntValue(thisCfgArray[IdxBuyLockInterval])
159169
160170 let sellLockInterval = parseIntValue(thisCfgArray[IdxSellLockInterval])
161171
162172 let buyFeePercent = parseIntValue(thisCfgArray[IdxBuyFeePercent])
163173
164174 let sellFeePercent = parseIntValue(thisCfgArray[IdxSellFeePercent])
165175
166176 let weekendsPriceChangeCoefficient = parseIntValue(thisCfgArray[IdxWeekendsPriceChangeCoefficient])
177+
178+let assetAccountPublicStr = thisCfgArray[IdxAssetAccountPublicStr]
179+
180+let assetStakingReferralPublicStr = thisCfgArray[IdxAssetStakingReferralPublicStr]
181+
182+let crossExchangeCoefficient = parseIntValue(thisCfgArray[IdxCrossExchangeCoefficient])
183+
184+let stakingMinAmtFromSellCoefficient = parseIntValue(thisCfgArray[IdxStakingMinAmtFromSellCoefficient])
185+
186+let poolStabilityFeePart = parseIntValue(thisCfgArray[IdxPoolStabilityFeePart])
167187
168188 func keyIsBlocked () = "%s__isBlocked"
169189
170190
171191 func keyIsMarketOpened (assetCode) = ("%s%s__isMarketOpened__" + assetCode)
172192
173193
174194 let isBlocked = valueOrElse(getBoolean(priceOracleAcc, keyIsBlocked()), false)
175195
176196 let isMarketOpened = valueOrElse(getBoolean(priceOracleAcc, keyIsMarketOpened(defoAssetCode)), false)
177197
178198 func controlAccReadPrice (assetCode) = valueOrErrorMessage(getInteger(priceOracleAcc, keyPrice(assetCode)), ((("No price at priceOracle=" + toString(priceOracleAcc)) + " for key=") + keyPrice(assetCode)))
179199
180200
181201 func controlAccReadLastHeight (assetCode) = valueOrErrorMessage(getInteger(priceOracleAcc, keyControlLastHeight(assetCode)), ((("No lastHeight at priceOracle=" + toString(priceOracleAcc)) + " for key=") + keyControlLastHeight(assetCode)))
182202
183203
184204 func controlAccReadCurrIdxOrFail () = valueOrErrorMessage(getInteger(priceOracleAcc, "currIdx"), ("No currIdx at controlAcc=" + toString(priceOracleAcc)))
185205
186206
187207 func controlAccReadIdxHeight (idx) = {
188208 let idxHeightKey = ("idxHeight_" + toString(idx))
189209 valueOrElse(getInteger(priceOracleAcc, idxHeightKey), 0)
190210 }
191211
192212
193213 func controlAccReadPriceByHeight (priceHeight) = {
194214 let priceByHeightKey = ("price_" + toString(priceHeight))
195215 valueOrErrorMessage(getInteger(priceOracleAcc, priceByHeightKey), ((("No " + priceByHeightKey) + " at controlAcc=") + toString(priceOracleAcc)))
196216 }
197217
198218
199219 let priceLastHeight = controlAccReadLastHeight(defoAssetCode)
200220
201221 let isBlockedByLastHeight = ((priceLastHeight - priceLastHeight) > 5)
202222
203223 let keyDefoStakingAddress = "%s%s__commonConfig__defoStakingAddress"
204224
205225 let keyNeutrinoStakingAddress = "%s%s__commonConfig__neutrinoStakingAddress"
206226
207227 func keyDefoStakingAssetBalance (assetId) = ("%s%s__stakingBalance__" + assetId)
208228
209229
210230 func keyNeutrinoStakingBalance () = ((("rpd_balance_" + baseAssetIdStr) + "_") + toString(this))
211231
212232
213233 let defoStakingAcc = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(factoryAcc, keyDefoStakingAddress), ((("No config at factoryAcc" + toString(factoryAcc)) + " for key=") + keyDefoStakingAddress))), ("address extraction error for key=" + keyDefoStakingAddress))
214234
215235 let neutrinoStakingAcc = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(factoryAcc, keyNeutrinoStakingAddress), ((("No config at factoryAcc" + toString(factoryAcc)) + " for key=") + keyNeutrinoStakingAddress))), ("address extraction error for key=" + keyNeutrinoStakingAddress))
216236
217237 func getThisDefoStakingBalance () = valueOrElse(getInteger(defoStakingAcc, keyDefoStakingAssetBalance(defoAssetIdStr)), 0)
218238
219239
220240 func getThisNeutrinoStakingBalance () = valueOrElse(getInteger(neutrinoStakingAcc, keyNeutrinoStakingBalance()), 0)
221241
222242
223243 let ucollateral = valueOrElse(getInteger(this, keyUcollateral()), 0)
224244
225245 let accumulatedFee = valueOrElse(getInteger(this, keyAccumulatedFee()), 0)
226246
227247 let currPoolAmount = getIntegerValue(factoryAcc, keyFactoryAssetCurrentPool(this))
228248
229249 let debtAssetId = fromBase58String(factoryReadDebtAssetId())
230250
231251 let debtAssetEtalonBalance = getIntegerValue(factoryAcc, keyFactoryDebtAssetEtalonBalance())
232252
233253 let lendedOrDebtAmount = (debtAssetEtalonBalance - assetBalance(this, debtAssetId))
234254
235255 let currentBaseAssetBalance = ((assetBalance(this, baseAssetId) + getThisNeutrinoStakingBalance()) + lendedOrDebtAmount)
236256
237257 let controlPrice = controlAccReadPrice(thisCfgArray[IdxDefoAssetCode])
238258
239259 let emission = (value(assetInfo(defoAssetId)).quantity - assetBalance(this, defoAssetId))
240260
241261 func getBuyPrice (changeCoeff) = if (isMarketOpened)
242262 then controlPrice
243263 else fraction((priceDecimals - changeCoeff), controlPrice, priceDecimals)
244264
245265
266+func getBuyFeeConsideringStakingReferral (callerPub58Str) = if ((assetStakingReferralPublicStr == callerPub58Str))
267+ then 0
268+ else buyFeePercent
269+
270+
271+func getBuyPriceConsideringStakingReferral (changeCoeff,callerPub58Str) = if ((assetStakingReferralPublicStr == callerPub58Str))
272+ then controlPrice
273+ else getBuyPrice(changeCoeff)
274+
275+
246276 func getSellPrice (changeCoeff) = if (isMarketOpened)
247277 then controlPrice
248278 else fraction((priceDecimals + changeCoeff), controlPrice, priceDecimals)
249279
250280
251281 func getSellPriceFrom (fromPrice,changeCoeff) = if (isMarketOpened)
252282 then fromPrice
253283 else fraction((priceDecimals + changeCoeff), fromPrice, priceDecimals)
254284
255285
256-func internalBuyAsset (sellerAddr,sellAmt,sellAssetId,minSellAmt,buy2sellPrice,feePercent) = {
286+func internalBuyAsset (sellerAddr,sellAmt,sellAssetId,minSellAmt,buy2sellPrice,poolMakersFeePart) = {
257287 let defoAssetAmountGross = fraction(sellAmt, buy2sellPrice, priceDecimals)
258- let defoAssetAmount = fraction((priceDecimals - feePercent), defoAssetAmountGross, priceDecimals)
259- let feeAmount = (defoAssetAmountGross - defoAssetAmount)
288+ let stabilityFeeDefoAmount = fraction(poolStabilityFeePart, defoAssetAmountGross, priceDecimals)
289+ let poolMakersFeeDefoAmount = fraction(poolMakersFeePart, defoAssetAmountGross, priceDecimals)
290+ let defoAssetAmount = ((defoAssetAmountGross - stabilityFeeDefoAmount) - poolMakersFeeDefoAmount)
260291 let requiredBasicAssetAmount = fraction(defoAssetAmountGross, priceDecimals, buy2sellPrice)
261292 let change = (sellAmt - requiredBasicAssetAmount)
262293 if (if ((minSellAmt > sellAmt))
263294 then (toString(sellerAddr) != toString(defoStakingAcc))
264295 else false)
265296 then throw(((((("impossible to issue new " + defoAssetCode) + ": payment=") + toString(sellAmt)) + "is less then min amount=") + toString(minSellAmt)))
266- else $Tuple2([IntegerEntry(keyUcollateral(), (ucollateral + requiredBasicAssetAmount)), StringEntry(keyAccountOperation(height, toString(sellerAddr), "FINISHED"), assetDataSwapOperation(sellAmt, toBase58String(sellAssetId), controlPrice, defoAssetAmount, toBase58String(defoAssetId), defoAssetAmountGross, feeAmount)), Reissue(defoAssetId, (defoAssetAmount + feeAmount), true), ScriptTransfer(sellerAddr, defoAssetAmount, defoAssetId), ScriptTransfer(sellerAddr, change, sellAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), feeAmount, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + feeAmount))], change)
297+ else $Tuple2([IntegerEntry(keyUcollateral(), (ucollateral + requiredBasicAssetAmount)), StringEntry(keyAccountOperation(height, toString(sellerAddr), "FINISHED"), assetDataSwapOperation(sellAmt, toBase58String(sellAssetId), controlPrice, defoAssetAmount, toBase58String(defoAssetId), defoAssetAmountGross, poolMakersFeeDefoAmount)), Reissue(defoAssetId, (defoAssetAmount + poolMakersFeeDefoAmount), true), ScriptTransfer(sellerAddr, defoAssetAmount, defoAssetId), ScriptTransfer(sellerAddr, change, sellAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), poolMakersFeeDefoAmount, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + poolMakersFeeDefoAmount))], change)
267298 }
268299
269300
270301 @Callable(i)
271-func buyAsset () = {
272- let pmt = value(i.payments[0])
273- let pmtAssetId = value(pmt.assetId)
274- if (isBlocked)
275- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
276- else if (isBlockedByLastHeight)
277- then throw(((("last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)))
278- else if ((pmtAssetId != baseAssetId))
279- then throw(((("Payment asset id doesn't match basic asset: expected=" + toBase58String(baseAssetId)) + " actual=") + toBase58String(pmtAssetId)))
280- else internalBuyAsset(i.caller, pmt.amount, pmtAssetId, minBasicBuyAmount, getBuyPrice(weekendsPriceChangeCoefficient), buyFeePercent)._1
281- }
302+func buyAsset () = throw("NGN buyAsset operation is temporary unavailable")
282303
283304
284305
285306 @Callable(i)
286307 func sellAsset () = {
287308 let pmt = value(i.payments[0])
288309 let pmtAsset = value(pmt.assetId)
289310 let callerAddress = toString(i.caller)
290311 let sellPrice = getSellPrice(weekendsPriceChangeCoefficient)
291312 if (isBlocked)
292313 then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
293- else if (isBlockedByLastHeight)
294- then throw(((("last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)))
295- else if ((pmtAsset != defoAssetId))
296- then throw(((("Invalid payment asset id: expected=" + toBase58String(defoAssetId)) + " actual=") + toBase58String(pmtAsset)))
297- else if ((minSynthSellAmount > pmt.amount))
298- then throw(((("Payment amount less then mininimal allowed: paymentAmount=" + toString(pmt.amount)) + " minAmount=") + toString(minSynthSellAmount)))
299- else {
300- let baseAssetAmountNoBalanceLimit = fraction(pmt.amount, priceDecimals, sellPrice)
301- let baseAssetAmountAvailable = if ((baseAssetAmountNoBalanceLimit > currentBaseAssetBalance))
302- then currentBaseAssetBalance
303- else baseAssetAmountNoBalanceLimit
304- let soldDefoAssetAmountGross = fraction(baseAssetAmountAvailable, sellPrice, priceDecimals)
305- let change = (pmt.amount - soldDefoAssetAmountGross)
306- let defoAmountFee = fraction(sellFeePercent, soldDefoAssetAmountGross, priceDecimals)
307- let soldDefoAssetAmount = (soldDefoAssetAmountGross - defoAmountFee)
308- let baseAssetAmountToSend = fraction(soldDefoAssetAmount, priceDecimals, sellPrice)
309-[IntegerEntry(keyUcollateral(), (ucollateral - baseAssetAmountToSend)), StringEntry(keyAccountOperation(height, callerAddress, "FINISHED"), assetDataSwapOperation(pmt.amount, toBase58String(pmtAsset), sellPrice, baseAssetAmountToSend, baseAssetIdStr, soldDefoAssetAmountGross, defoAmountFee)), Burn(defoAssetId, soldDefoAssetAmount), ScriptTransfer(i.caller, baseAssetAmountToSend, baseAssetId), ScriptTransfer(i.caller, change, defoAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), defoAmountFee, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + defoAmountFee))]
310- }
314+ else if ((pmtAsset != defoAssetId))
315+ then throw(((("Invalid payment asset id: expected=" + toBase58String(defoAssetId)) + " actual=") + toBase58String(pmtAsset)))
316+ else if ((minSynthSellAmount > pmt.amount))
317+ then throw(((("Payment amount less then mininimal allowed: paymentAmount=" + toString(pmt.amount)) + " minAmount=") + toString(minSynthSellAmount)))
318+ else {
319+ let baseAssetAmountNoBalanceLimit = fraction(pmt.amount, priceDecimals, sellPrice)
320+ let baseAssetAmountAvailable = if ((baseAssetAmountNoBalanceLimit > currentBaseAssetBalance))
321+ then currentBaseAssetBalance
322+ else baseAssetAmountNoBalanceLimit
323+ let soldDefoAssetAmountGross = fraction(baseAssetAmountAvailable, sellPrice, priceDecimals)
324+ let change = (pmt.amount - soldDefoAssetAmountGross)
325+ let stabilityFeeDefoAmount = fraction(poolStabilityFeePart, soldDefoAssetAmountGross, priceDecimals)
326+ let poolMakersFeeDefoAmount = fraction(sellFeePercent, soldDefoAssetAmountGross, priceDecimals)
327+ let soldDefoAssetAmount = ((soldDefoAssetAmountGross - stabilityFeeDefoAmount) - poolMakersFeeDefoAmount)
328+ let baseAssetAmountToSend = fraction(soldDefoAssetAmount, priceDecimals, sellPrice)
329+[IntegerEntry(keyUcollateral(), (ucollateral - baseAssetAmountToSend)), StringEntry(keyAccountOperation(height, callerAddress, "FINISHED"), assetDataSwapOperation(pmt.amount, toBase58String(pmtAsset), sellPrice, baseAssetAmountToSend, baseAssetIdStr, soldDefoAssetAmountGross, poolMakersFeeDefoAmount)), Burn(defoAssetId, (soldDefoAssetAmount + stabilityFeeDefoAmount)), ScriptTransfer(i.caller, baseAssetAmountToSend, baseAssetId), ScriptTransfer(i.caller, change, defoAssetId), ScriptTransfer(factoryReadNextPoolMakerToDistributeFee(toString(this)), poolMakersFeeDefoAmount, defoAssetId), IntegerEntry(keyAccumulatedFee(), (accumulatedFee + poolMakersFeeDefoAmount))]
330+ }
311331 }
312332
313333
314334
315335 @Callable(i)
316-func crossExchange (buyAssetCodeConfirm,sellAssetCodeConfirm) = {
317- let pmt = value(i.payments[0])
318- let pmtAsset = value(pmt.assetId)
319- let pmtAssetStr = toBase58String(pmtAsset)
320- let pmtAmount = pmt.amount
321- let callerAddress = toString(i.caller)
322- let buyAssetCfg = thisCfgArray
323- let sellAssetTuple = factoryReadAssetCfgByCode(sellAssetCodeConfirm)
324- let sellAssetCfg = sellAssetTuple._2
325- let sellAssetAccAddress = valueOrErrorMessage(addressFromString(sellAssetTuple._1), ("couldn't parse address from string for assetCode=" + sellAssetCodeConfirm))
326- let minSellPmt = valueOrErrorMessage(parseInt(sellAssetCfg[IdxMinSellPayment]), ("minSellPmt parsing error: rawVal=" + sellAssetCfg[IdxMinSellPayment]))
327- let sellPriceLastHeight = controlAccReadLastHeight(sellAssetCodeConfirm)
328- let isSellBlockedByLastHeight = ((sellPriceLastHeight - sellPriceLastHeight) > 5)
329- if (isBlocked)
330- then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
331- else if ((thisCfgArray[IdxDefoAssetCode] != buyAssetCodeConfirm))
332- then throw(((("buyAsset confirmation failed: buyAssetIdConfirm=" + thisCfgArray[IdxDefoAssetCode]) + " BUT buyAssetId=") + buyAssetCodeConfirm))
333- else if ((sellAssetCfg[IdxDefoAssetId] != pmtAssetStr))
334- then throw(((("sellAsset confirmation failed: sellAssetIdConfirm=" + sellAssetCfg[IdxDefoAssetId]) + "BUT pmtAsset=") + pmtAssetStr))
335- else if ((thisCfgArray[IdxDefoAssetStatus] != "ISSUED"))
336- then throw(((("toAsset has not been issued yet: buyAssetId=" + buyAssetCodeConfirm) + " BUT status=") + thisCfgArray[IdxDefoAssetStatus]))
337- else if ((sellAssetCfg[IdxDefoAssetStatus] != "ISSUED"))
338- then throw(((("fromAssetCfg has not been issued yet: sellAssetId=" + pmtAssetStr) + " BUT status=") + sellAssetCfg[IdxDefoAssetStatus]))
339- else if (isBlockedByLastHeight)
340- then throw(((((("buy last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)) + " buyCode=") + buyAssetCodeConfirm))
341- else if (isSellBlockedByLastHeight)
342- then throw(((((("sell last price finalization has been more then 5 blocks ago: priceLastHeight=" + toString(priceLastHeight)) + " currHeight=") + toString(height)) + " sellCode=") + sellAssetCodeConfirm))
343- else {
344- let buyAssetUsdPrice = getBuyPrice((weekendsPriceChangeCoefficient / 2))
345- let sellAssetUsdPrice = getSellPriceFrom(controlAccReadPrice(sellAssetCodeConfirm), (weekendsPriceChangeCoefficient / 2))
346- let buy2sellPrice = fraction(buyAssetUsdPrice, priceDecimals, sellAssetUsdPrice)
347- let usdnDebt = fraction(pmtAmount, priceDecimals, sellAssetUsdPrice)
348- let totalLendedAtOtherAccs = valueOrElse(getInteger(this, keyTotalLendedAtOtherAccs()), 0)
349- let lendedAmountByAssetCodeKey = keyLendedAmountByAssetCode(sellAssetCodeConfirm)
350- let lendedAmtByAssetCode = valueOrElse(getInteger(this, lendedAmountByAssetCodeKey), 0)
351- let sellAssetSellFeePercent = parseIntValue(sellAssetCfg[IdxSellFeePercent])
352- let buyAssetResult = internalBuyAsset(i.caller, pmtAmount, pmtAsset, minSellPmt, buy2sellPrice, fraction((buyFeePercent + sellAssetSellFeePercent), 50, 100))
353- ((((buyAssetResult._1 :+ ScriptTransfer(sellAssetAccAddress, usdnDebt, debtAssetId)) :+ ScriptTransfer(sellAssetAccAddress, (pmtAmount - buyAssetResult._2), pmtAsset)) :+ IntegerEntry(lendedAmountByAssetCodeKey, (lendedAmtByAssetCode + usdnDebt))) :+ IntegerEntry(keyTotalLendedAtOtherAccs(), (totalLendedAtOtherAccs + usdnDebt)))
354- }
355- }
336+func crossExchange (buyAssetCodeConfirm,sellAssetCodeConfirm) = throw("NGN crossExchange operation is temporary unavailable")
356337
357338
358339
359340 @Callable(i)
360341 func rebalanceDebts () = {
361342 let debtPmt0 = value(i.payments[0])
362343 let debtPmtAsset0 = value(debtPmt0.assetId)
363344 let basePmt1 = value(i.payments[1])
364345 let basePmtAsset1 = value(basePmt1.assetId)
365346 let debtorAddress = toString(i.caller)
366347 let debtorAssetCfg = factoryReadAssetCfgByAddress(debtorAddress)
367348 let debtorAssetCode = debtorAssetCfg[IdxDefoAssetCode]
368349 let lendedAmountByAssetCodeKey = keyLendedAmountByAssetCode(debtorAssetCode)
369350 let lendedAmt = valueOrErrorMessage(getInteger(this, lendedAmountByAssetCodeKey), ("No debts for " + debtorAssetCode))
370351 if (isBlocked)
371352 then throw("contract is blocked by EMERGENCY SHUTDOWN actions untill reactivation by emergency oracles")
372353 else if ((debtAssetId != debtPmtAsset0))
373354 then throw(((("invalid debt asset id in the first paymet: expected=" + toBase58String(debtAssetId)) + " actual=") + toBase58String(debtPmtAsset0)))
374355 else if ((baseAssetId != basePmtAsset1))
375356 then throw(((("invalid base asset id in the second payment: expected=" + toBase58String(baseAssetId)) + " actual=") + toBase58String(basePmtAsset1)))
376357 else if ((debtPmt0.amount != basePmt1.amount))
377358 then throw("first payment amount doesn't match to the second payment amount")
378359 else if ((0 >= lendedAmt))
379360 then throw(("lendedAmt is less then zero: lendedAmt=" + toString(lendedAmt)))
380- else if (((100 * priceDecimals) >= debtPmt0.amount))
361+ else if (((1 * priceDecimals) >= debtPmt0.amount))
381362 then throw(("attached payment must be greater then 100: pmt0.amount=" + toString(debtPmt0.amount)))
382363 else if ((debtPmt0.amount > lendedAmt))
383364 then throw(((("attached payment is grater than required: pmtAmount=" + toString(debtPmt0.amount)) + " lendedAmt=") + toString(lendedAmt)))
384365 else {
385366 let totalLendedAtOtherAccs = valueOrElse(getInteger(this, keyTotalLendedAtOtherAccs()), 0)
386367 let lendedAmtAfter = (lendedAmt - debtPmt0.amount)
387368 [IntegerEntry(lendedAmountByAssetCodeKey, lendedAmtAfter), IntegerEntry(keyTotalLendedAtOtherAccs(), (totalLendedAtOtherAccs - debtPmt0.amount)), StringEntry(("%s%s__rebalanceTrace__" + toBase58String(i.transactionId)), assetDataRebalanceTrace(debtorAssetCode, debtPmt0, basePmt1, lendedAmt, lendedAmtAfter))]
388369 }
389370 }
390371
391372
392373
393374 @Callable(i)
394375 func fulfillRedeemRequest (poolMakerAddress) = {
395376 let thisAddressStr = toString(this)
396377 let poolMakerUnlockHeightKey = keyFactoryPoolMakerUnlockHeight(thisAddressStr, poolMakerAddress)
397378 let poolMakerUnlockHeight = valueOrElse(getInteger(factoryAcc, poolMakerUnlockHeightKey), 0)
398379 if ((0 >= poolMakerUnlockHeight))
399380 then throw("All liquidity request fulfilled")
400381 else {
401382 let poolMakerLiquidityRequestKey = keyFactoryPoolMakerLiquidityRequest(thisAddressStr, poolMakerAddress, poolMakerUnlockHeight)
402383 let poolMakerLiquidityRequestAmount = valueOrErrorMessage(getInteger(factoryAcc, poolMakerLiquidityRequestKey), "Empty poolMakerLiquidityRequestKey at factory acc")
403384 if (isDefined(getInteger(this, poolMakerLiquidityRequestKey)))
404385 then throw("Liquidity request has been already fulfilled")
405386 else [IntegerEntry(poolMakerLiquidityRequestKey, poolMakerLiquidityRequestAmount), ScriptTransfer(factoryAcc, poolMakerLiquidityRequestAmount, baseAssetId)]
406387 }
407388 }
408389
409390
410391 @Verifier(tx)
411392 func verify () = match tx {
412393 case inv: InvokeScriptTransaction =>
413394 if ((inv.fee > (900 * 1000)))
414395 then throw(("fee amount is greater than max allowed: " + toString(inv.fee)))
415396 else if (isDefined(inv.feeAssetId))
416397 then throw("only Waves is allowed as feeAssetId")
417398 else if ((inv.function == "rebalanceDebts"))
418399 then {
419400 let invDappAddress = toString(addressFromRecipient(inv.dApp))
420401 if ((factoryReadAssetCfgByAddress(invDappAddress)[IdxDefoAssetStatus] != "ISSUED"))
421402 then throw("only defo dapp is allowed")
422403 else if ((invDappAddress == toString(this)))
423404 then throw("impossible to call self rebealnceDebt")
424405 else true
425406 }
426407 else if (if (if ((inv.function == "lockNeutrino"))
427408 then true
428409 else (inv.function == "lockNeutrinoSP"))
429410 then true
430411 else (inv.function == "unlockNeutrino"))
431412 then if ((toString(neutrinoStakingAcc) != toString(addressFromRecipient(inv.dApp))))
432413 then throw("invalid neutrino staking dapp address")
433414 else sigVerify(tx.bodyBytes, tx.proofs[0], factoryReadDefoStakingPacemakerPub())
434415 else throw("Not allowed invocation method calls")
435416 case _ =>
436417 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
437418 }
438419

github/deemru/w8io/026f985 
103.09 ms