tx · 9jBs1cJKpkEY4MEoxZ8aCt2GtkqBy5tEsUbxuKaFrcQW

3NBsEdgQXYpy59EHGqgwfE7jSAqFUzo7Ccp:  -0.05000000 Waves

2021.09.09 16:48 [1695590] smart account 3NBsEdgQXYpy59EHGqgwfE7jSAqFUzo7Ccp > SELF 0.00000000 Waves

{ "type": 13, "id": "9jBs1cJKpkEY4MEoxZ8aCt2GtkqBy5tEsUbxuKaFrcQW", "fee": 5000000, "feeAssetId": null, "timestamp": 1631195333478, "version": 2, "chainId": 84, "sender": "3NBsEdgQXYpy59EHGqgwfE7jSAqFUzo7Ccp", "senderPublicKey": "FwAzvdwqFM7zuHfsEbjdj845GeiE4UKnLGPLbqhS4U38", "proofs": [ "5mgrKNSmrz1vCayKWUyBa3VpT1EvNHgL8SQ9HD3vksaJCV88DVPuzrmkjbpw29WF6AeFKTrgNW1Kui8Hk6y5Siwd" ], "script": "base64:AAIFAAAAAAAAACkIAhIECgIBBBIAEgQKAggIEgASBQoDAQEIEgUKAwEBCBIFCgMIAQgSAAAAADkAAAAAD2ZhY3RvcnlDb250cmFjdAkBAAAAB0FkZHJlc3MAAAABAQAAABoBVLzyGze2RqObbRI79PVLCWJw86yqRU+BVAAAAAAKbFBkZWNpbWFscwAAAAAAAAAACAAAAAAGc2NhbGU4AAAAAAAF9eEAAAAAAAdzY2FsZTE4CQABNgAAAAEADeC2s6dkAAAAAAAAA1NFUAIAAAACX18AAAAAClBvb2xBY3RpdmUAAAAAAAAAAAEAAAAAD1Bvb2xQdXREaXNhYmxlZAAAAAAAAAAAAgAAAAATUG9vbE1hdGNoZXJEaXNhYmxlZAAAAAAAAAAAAwAAAAAMUG9vbFNodXRkb3duAAAAAAAAAAAEAAAAAA5pZHhQb29sQWRkcmVzcwAAAAAAAAAAAQAAAAANaWR4UG9vbFN0YXR1cwAAAAAAAAAAAgAAAAAQaWR4UG9vbExQQXNzZXRJZAAAAAAAAAAAAwAAAAAQaWR4QW1vdW50QXNzZXRJZAAAAAAAAAAABAAAAAAPaWR4UHJpY2VBc3NldElkAAAAAAAAAAAFAAAAABZpZHhBbW91bnRBc3NldERlY2ltYWxzAAAAAAAAAAAGAAAAABVpZHhQcmljZUFzc2V0RGVjaW1hbHMAAAAAAAAAAAcAAAAAGGlkeEFtb3VudEFzc2V0SW50ZXJuYWxJZAAAAAAAAAAACAAAAAAXaWR4UHJpY2VBc3NldEludGVybmFsSWQAAAAAAAAAAAkAAAAAEmlkeExQQXNzZXREZWNpbWFscwAAAAAAAAAACgAAAAATaWR4TWF0Y2hlclB1YmxpY0tleQAAAAAAAAAACwAAAAAVaWR4UG9vbEFtb3VudEFzc2V0QW10AAAAAAAAAAABAAAAABRpZHhQb29sUHJpY2VBc3NldEFtdAAAAAAAAAAAAgAAAAARaWR4UG9vbExQQXNzZXRBbXQAAAAAAAAAAAMAAAAAGWlkeEZhY3RvcnlTdGFraW5nQ29udHJhY3QAAAAAAAAAAAEAAAAAGGlkeEZhY3RvcnlCb29zdGluZ0NvbmZpZwAAAAAAAAAAAgEAAAAMa2V5UHJpY2VMYXN0AAAAAAIAAAARJXMlc19fcHJpY2VfX2xhc3QBAAAAD2tleVByaWNlSGlzdG9yeQAAAAIAAAABaAAAAAl0aW1lc3RhbXAJAAS5AAAAAgkABEwAAAACAgAAABglcyVzJWQlZF9fcHJpY2VfX2hpc3RvcnkJAARMAAAAAgkAAaQAAAABBQAAAAFoCQAETAAAAAIJAAGkAAAAAQUAAAAJdGltZXN0YW1wBQAAAANuaWwFAAAAA1NFUAEAAAAQa2V5UG9vbExpcXVpZGl0eQAAAAIAAAATaW50ZXJuYWxBbW91bnRBc3NldAAAABJpbnRlcm5hbFByaWNlQXNzZXQJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIJWQlZCVzX18FAAAAE2ludGVybmFsQW1vdW50QXNzZXQCAAAAAl9fBQAAABJpbnRlcm5hbFByaWNlQXNzZXQCAAAACF9fbG9ja2VkAQAAABZrZXlQb29sTGlxdWlkaXR5QnlVc2VyAAAAAwAAABNpbnRlcm5hbEFtb3VudEFzc2V0AAAAEmludGVybmFsUHJpY2VBc3NldAAAAAt1c2VyQWRkcmVzcwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAKJWQlZCVzJXNfXwUAAAATaW50ZXJuYWxBbW91bnRBc3NldAIAAAACX18FAAAAEmludGVybmFsUHJpY2VBc3NldAIAAAACX18FAAAAC3VzZXJBZGRyZXNzAgAAAAhfX2xvY2tlZAEAAAASa2V5UHV0QWN0aW9uQnlVc2VyAAAAAgAAAAt1c2VyQWRkcmVzcwAAAAR0eElkCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAslcyVzJXNfX1BfXwUAAAALdXNlckFkZHJlc3MCAAAAAl9fBQAAAAR0eElkAQAAABJrZXlHZXRBY3Rpb25CeVVzZXIAAAACAAAAC3VzZXJBZGRyZXNzAAAABHR4SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACyVzJXMlc19fR19fBQAAAAt1c2VyQWRkcmVzcwIAAAACX18FAAAABHR4SWQBAAAADmtleUFtb3VudEFzc2V0AAAAAAIAAAAPJXNfX2Ftb3VudEFzc2V0AQAAAA1rZXlQcmljZUFzc2V0AAAAAAIAAAAOJXNfX3ByaWNlQXNzZXQBAAAAEGtleUZhY3RvcnlDb25maWcAAAAAAgAAABElc19fZmFjdG9yeUNvbmZpZwEAAAApa2V5TWFwcGluZ1Bvb2xDb250cmFjdEFkZHJlc3NUb1Bvb2xBc3NldHMAAAABAAAAE3Bvb2xDb250cmFjdEFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAAAglcyVzJXNfXwUAAAATcG9vbENvbnRyYWN0QWRkcmVzcwIAAAAgX19tYXBwaW5nc19fcG9vbENvbnRyYWN0MkxwQXNzZXQBAAAADWtleVBvb2xDb25maWcAAAACAAAAE2Ftb3VudEFzc2V0SW50ZXJuYWwAAAAScHJpY2VBc3NldEludGVybmFsCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACCVkJWQlc19fBQAAABNhbW91bnRBc3NldEludGVybmFsAgAAAAJfXwUAAAAScHJpY2VBc3NldEludGVybmFsAgAAAAhfX2NvbmZpZwEAAAAfa2V5TWFwcGluZ3NCYXNlQXNzZXQyaW50ZXJuYWxJZAAAAAEAAAAMYmFzZUFzc2V0U3RyCQABLAAAAAICAAAAKCVzJXMlc19fbWFwcGluZ3NfX2Jhc2VBc3NldDJpbnRlcm5hbElkX18FAAAADGJhc2VBc3NldFN0cgEAAAATa2V5QWxsUG9vbHNTaHV0ZG93bgAAAAACAAAADCVzX19zaHV0ZG93bgEAAAANa2V5UG9vbFdlaWdodAAAAAEAAAAPY29udHJhY3RBZGRyZXNzCQABLAAAAAICAAAAEiVzJWRfX3Bvb2xXZWlnaHRfXwUAAAAPY29udHJhY3RBZGRyZXNzAQAAABBpc0dsb2JhbFNodXRkb3duAAAAAAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBsAAAACBQAAAA9mYWN0b3J5Q29udHJhY3QJAQAAABNrZXlBbGxQb29sc1NodXRkb3duAAAAAAcBAAAADWdldFBvb2xDb25maWcAAAAABAAAAA9wb29sQW1vdW50QXNzZXQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzCQEAAAAOa2V5QW1vdW50QXNzZXQAAAAAAgAAACBObyBjb25maWcgZm9yIGFtb3VudCBhc3NldCBmb3VuZAQAAAAOcG9vbFByaWNlQXNzZXQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAR0aGlzCQEAAAANa2V5UHJpY2VBc3NldAAAAAACAAAAH05vIGNvbmZpZyBmb3IgcHJpY2UgYXNzZXQgZm91bmQEAAAAFnBvb2xQcmljZUFzc2V0SW50ZXJuYWwJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA9mYWN0b3J5Q29udHJhY3QJAQAAAB9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkAAAAAQUAAAAOcG9vbFByaWNlQXNzZXQCAAAAKE5vIGNvbmZpZyBmb3IgaW50ZXJuYWwgcHJpY2UgYXNzZXQgZm91bmQEAAAAF3Bvb2xBbW91bnRBc3NldEludGVybmFsCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAPZmFjdG9yeUNvbnRyYWN0CQEAAAAfa2V5TWFwcGluZ3NCYXNlQXNzZXQyaW50ZXJuYWxJZAAAAAEFAAAAD3Bvb2xBbW91bnRBc3NldAIAAAApTm8gY29uZmlnIGZvciBpbnRlcm5hbCBhbW91bnQgYXNzZXQgZm91bmQJAAS1AAAAAgkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAAD2ZhY3RvcnlDb250cmFjdAkBAAAADWtleVBvb2xDb25maWcAAAACCQABpAAAAAEFAAAAF3Bvb2xBbW91bnRBc3NldEludGVybmFsCQABpAAAAAEFAAAAFnBvb2xQcmljZUFzc2V0SW50ZXJuYWwCAAAAKE5vIGZhY3RvcnkgY29uZmlnIGZvdW5kIGZvciBwb29sIGFzc2V0cy4FAAAAA1NFUAEAAAAQZ2V0RmFjdG9yeUNvbmZpZwAAAAAJAAS1AAAAAgkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAAD2ZhY3RvcnlDb250cmFjdAkBAAAAEGtleUZhY3RvcnlDb25maWcAAAAAAgAAABhObyBmYWN0b3J5IGNvbmZpZyBmb3VuZC4FAAAAA1NFUAEAAAAQZ2V0UG9vbExpcXVpZGl0eQAAAAIAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkAAAAFHByaWNlQXNzZXRJbnRlcm5hbElkBAAAABljdXJyZW50UG9vbExpcXVpZGl0eVZhbHVlCQAEHQAAAAIFAAAABHRoaXMJAQAAABBrZXlQb29sTGlxdWlkaXR5AAAAAgUAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkBQAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAMJAQAAAAlpc0RlZmluZWQAAAABBQAAABljdXJyZW50UG9vbExpcXVpZGl0eVZhbHVlCQAEtQAAAAIJAQAAAAV2YWx1ZQAAAAEFAAAAGWN1cnJlbnRQb29sTGlxdWlkaXR5VmFsdWUFAAAAA1NFUAkABEwAAAACAgAAAAAJAARMAAAAAgIAAAABMAkABEwAAAACAgAAAAEwCQAETAAAAAICAAAAATAFAAAAA25pbAEAAAAWZ2V0UG9vbExpcXVpZGl0eUJ5VXNlcgAAAAMAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkAAAAFHByaWNlQXNzZXRJbnRlcm5hbElkAAAAC3VzZXJBZGRyZXNzBAAAABljdXJyZW50UG9vbExpcXVpZGl0eVZhbHVlCQAEHQAAAAIFAAAABHRoaXMJAQAAABZrZXlQb29sTGlxdWlkaXR5QnlVc2VyAAAAAwUAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkBQAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAUAAAALdXNlckFkZHJlc3MDCQEAAAAJaXNEZWZpbmVkAAAAAQUAAAAZY3VycmVudFBvb2xMaXF1aWRpdHlWYWx1ZQkABLUAAAACCQEAAAAFdmFsdWUAAAABBQAAABljdXJyZW50UG9vbExpcXVpZGl0eVZhbHVlBQAAAANTRVAJAARMAAAAAgIAAAAACQAETAAAAAICAAAAATAJAARMAAAAAgIAAAABMAkABEwAAAACAgAAAAEwCQAETAAAAAICAAAAATAFAAAAA25pbAEAAAARZGF0YVBvb2xMaXF1aWRpdHkAAAADAAAAEWFtb3VudEFzc2V0TG9ja2VkAAAAEHByaWNlQXNzZXRMb2NrZWQAAAANbHBUb2tlbkxvY2tlZAkABLkAAAACCQAETAAAAAICAAAABiVkJWQlZAkABEwAAAACCQABpAAAAAEFAAAAEWFtb3VudEFzc2V0TG9ja2VkCQAETAAAAAIJAAGkAAAAAQUAAAAQcHJpY2VBc3NldExvY2tlZAkABEwAAAACCQABpAAAAAEFAAAADWxwVG9rZW5Mb2NrZWQFAAAAA25pbAUAAAADU0VQAQAAABdkYXRhUG9vbExpcXVpZGl0eUJ5VXNlcgAAAAQAAAARYW1vdW50QXNzZXRMb2NrZWQAAAAQcHJpY2VBc3NldExvY2tlZAAAAA1scFRva2VuTG9ja2VkAAAAC3VzZXJBZGRyZXNzCQAEuQAAAAIJAARMAAAAAgIAAAAGJWQlZCVkCQAETAAAAAIJAAGkAAAAAQUAAAARYW1vdW50QXNzZXRMb2NrZWQJAARMAAAAAgkAAaQAAAABBQAAABBwcmljZUFzc2V0TG9ja2VkCQAETAAAAAIJAAGkAAAAAQUAAAANbHBUb2tlbkxvY2tlZAUAAAADbmlsBQAAAANTRVABAAAAEWRhdGFQdXRBY3Rpb25JbmZvAAAACAAAABBpbkFtb3VudEFzc2V0QW10AAAAD2luUHJpY2VBc3NldEFtdAAAAAhvdXRMcEFtdAAAAAVwcmljZQAAAB1zbGlwcGFnZVRvbGVyYW5jZVBhc3NlZEJ5VXNlcgAAABVzbGlwcGFnZVRvbGVyYW5jZVJlYWwAAAAIdHhIZWlnaHQAAAALdHhUaW1lc3RhbXAJAAS5AAAAAgkABEwAAAACAgAAAA4lZCVkJWQlZCVkJWQlZAkABEwAAAACCQABpAAAAAEFAAAAEGluQW1vdW50QXNzZXRBbXQJAARMAAAAAgkAAaQAAAABBQAAAA9pblByaWNlQXNzZXRBbXQJAARMAAAAAgkAAaQAAAABBQAAAAhvdXRMcEFtdAkABEwAAAACCQABpAAAAAEFAAAABXByaWNlCQAETAAAAAIJAAGkAAAAAQUAAAAdc2xpcHBhZ2VUb2xlcmFuY2VQYXNzZWRCeVVzZXIJAARMAAAAAgkAAaQAAAABBQAAABVzbGlwcGFnZVRvbGVyYW5jZVJlYWwJAARMAAAAAgkAAaQAAAABBQAAAAh0eEhlaWdodAkABEwAAAACCQABpAAAAAEFAAAAC3R4VGltZXN0YW1wBQAAAANuaWwFAAAAA1NFUAEAAAARZGF0YUdldEFjdGlvbkluZm8AAAAGAAAAEW91dEFtb3VudEFzc2V0QW10AAAAEG91dFByaWNlQXNzZXRBbXQAAAAHaW5McEFtdAAAAAVwcmljZQAAAAh0eEhlaWdodAAAAAt0eFRpbWVzdGFtcAkABLkAAAACCQAETAAAAAICAAAADCVkJWQlZCVkJWQlZAkABEwAAAACCQABpAAAAAEFAAAAEW91dEFtb3VudEFzc2V0QW10CQAETAAAAAIJAAGkAAAAAQUAAAAQb3V0UHJpY2VBc3NldEFtdAkABEwAAAACCQABpAAAAAEFAAAAB2luTHBBbXQJAARMAAAAAgkAAaQAAAABBQAAAAVwcmljZQkABEwAAAACCQABpAAAAAEFAAAACHR4SGVpZ2h0CQAETAAAAAIJAAGkAAAAAQUAAAALdHhUaW1lc3RhbXAFAAAAA25pbAUAAAADU0VQAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMAAAAGYW1vdW50AAAAC3Jlc3VsdFNjYWxlAAAADGN1cnJlbnRTY2FsZQkAAGsAAAADBQAAAAZhbW91bnQFAAAAC3Jlc3VsdFNjYWxlBQAAAAxjdXJyZW50U2NhbGUBAAAAFGNhbGN1bGF0ZVByaWNlQmlnSW50AAAAAgAAABNwcmljZUFzc2V0TG9ja2VkQW10AAAAFWFtb3VudEFzc2V0bExvY2tlZEFtdAQAAAALcHJpY2VCaWdJbnQJAAE8AAAAAwkAATYAAAABBQAAABNwcmljZUFzc2V0TG9ja2VkQW10BQAAAAdzY2FsZTE4CQABNgAAAAEFAAAAFWFtb3VudEFzc2V0bExvY2tlZEFtdAkAAaAAAAABCQABPAAAAAMFAAAAC3ByaWNlQmlnSW50CQABNgAAAAEFAAAABnNjYWxlOAUAAAAHc2NhbGUxOAEAAAAOY2FsY3VsYXRlUHJpY2UAAAACAAAAE3ByaWNlQXNzZXRMb2NrZWRBbXQAAAAVYW1vdW50QXNzZXRsTG9ja2VkQW10CQAAawAAAAMFAAAAE3ByaWNlQXNzZXRMb2NrZWRBbXQFAAAABnNjYWxlOAUAAAAVYW1vdW50QXNzZXRsTG9ja2VkQW10AQAAABVwcml2YXRlQ2FsY3VsYXRlUHJpY2UAAAAEAAAAEmFtb3V0QXNzZXREZWNpbWFscwAAABJwcmljZUFzc2V0RGVjaW1hbHMAAAAOYW1vdW50QXNzZXRBbXQAAAANcHJpY2VBc3NldEFtdAQAAAAUYW1vdW50QXNzZXRBbXRDYXN0ZWQJAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMFAAAADmFtb3VudEFzc2V0QW10BQAAAAZzY2FsZTgFAAAAEmFtb3V0QXNzZXREZWNpbWFscwQAAAATcHJpY2VBc3NldEFtdENhc3RlZAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAANcHJpY2VBc3NldEFtdAUAAAAGc2NhbGU4BQAAABJwcmljZUFzc2V0RGVjaW1hbHMJAQAAAA5jYWxjdWxhdGVQcmljZQAAAAIFAAAAE3ByaWNlQXNzZXRBbXRDYXN0ZWQFAAAAFGFtb3VudEFzc2V0QW10Q2FzdGVkAQAAABhwcml2YXRlR2V0QWNjb3VudEJhbGFuY2UAAAABAAAAB2Fzc2V0SWQDCQAAAAAAAAIFAAAAB2Fzc2V0SWQCAAAABVdBVkVTCAkAA+8AAAABBQAAAAR0aGlzAAAACWF2YWlsYWJsZQkAA/AAAAACBQAAAAR0aGlzCQACWQAAAAEFAAAAB2Fzc2V0SWQBAAAACWdldFByaWNlcwAAAAMAAAAOYW1vdW50QXNzZXRBbXQAAAANcHJpY2VBc3NldEFtdAAAAAhscEFtb3VudAQAAAAScG9vbENvbmZpZ0RhdGFMaXN0CQEAAAANZ2V0UG9vbENvbmZpZwAAAAAEAAAAEmFtb3V0QXNzZXREZWNpbWFscwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAWaWR4QW1vdW50QXNzZXREZWNpbWFscwQAAAAScHJpY2VBc3NldERlY2ltYWxzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABVpZHhQcmljZUFzc2V0RGVjaW1hbHMEAAAACXBvb2xQcmljZQkBAAAAFXByaXZhdGVDYWxjdWxhdGVQcmljZQAAAAQFAAAAEmFtb3V0QXNzZXREZWNpbWFscwUAAAAScHJpY2VBc3NldERlY2ltYWxzBQAAAA5hbW91bnRBc3NldEFtdAUAAAANcHJpY2VBc3NldEFtdAQAAAAYYW1vdW50QXNzZXRQb29sTG9ja2VkQW10CQEAAAAUcHJpdmF0ZUNhc3RUb1NjYWxlT2YAAAADBQAAAA5hbW91bnRBc3NldEFtdAUAAAAGc2NhbGU4BQAAABJhbW91dEFzc2V0RGVjaW1hbHMEAAAAF3ByaWNlQXNzZXRQb29sTG9ja2VkQW10CQEAAAAUcHJpdmF0ZUNhc3RUb1NjYWxlT2YAAAADBQAAAA1wcmljZUFzc2V0QW10BQAAAAZzY2FsZTgFAAAAEnByaWNlQXNzZXREZWNpbWFscwQAAAAUbHBQcmljZUluQW1vdW50QXNzZXQJAQAAAA5jYWxjdWxhdGVQcmljZQAAAAIFAAAAGGFtb3VudEFzc2V0UG9vbExvY2tlZEFtdAUAAAAIbHBBbW91bnQEAAAAE2xwUHJpY2VJblByaWNlQXNzZXQJAQAAAA5jYWxjdWxhdGVQcmljZQAAAAIFAAAAF3ByaWNlQXNzZXRQb29sTG9ja2VkQW10BQAAAAhscEFtb3VudAkABEwAAAACBQAAAAlwb29sUHJpY2UJAARMAAAAAgUAAAAUbHBQcmljZUluQW1vdW50QXNzZXQJAARMAAAAAgUAAAATbHBQcmljZUluUHJpY2VBc3NldAUAAAADbmlsAQAAABtwcml2YXRlRXN0aW1hdGVHZXRPcGVyYXRpb24AAAADAAAAEHBheW1lbnRMcEFzc2V0SWQAAAAPcGF5bWVudExwQW1vdW50AAAAC3VzZXJBZGRyZXNzBAAAAA5wb29sQ29uZmlnTGlzdAkBAAAADWdldFBvb2xDb25maWcAAAAABAAAAAlscEFzc2V0SWQJAAGRAAAAAgUAAAAOcG9vbENvbmZpZ0xpc3QFAAAAEGlkeFBvb2xMUEFzc2V0SWQEAAAADWFtb3VudEFzc2V0SWQJAAGRAAAAAgUAAAAOcG9vbENvbmZpZ0xpc3QFAAAAEGlkeEFtb3VudEFzc2V0SWQEAAAADHByaWNlQXNzZXRJZAkAAZEAAAACBQAAAA5wb29sQ29uZmlnTGlzdAUAAAAPaWR4UHJpY2VBc3NldElkBAAAABVhbW91bnRBc3NldEludGVybmFsSWQJAAGRAAAAAgUAAAAOcG9vbENvbmZpZ0xpc3QFAAAAGGlkeEFtb3VudEFzc2V0SW50ZXJuYWxJZAQAAAAUcHJpY2VBc3NldEludGVybmFsSWQJAAGRAAAAAgUAAAAOcG9vbENvbmZpZ0xpc3QFAAAAF2lkeFByaWNlQXNzZXRJbnRlcm5hbElkBAAAABJhbW91dEFzc2V0RGVjaW1hbHMJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAA5wb29sQ29uZmlnTGlzdAUAAAAWaWR4QW1vdW50QXNzZXREZWNpbWFscwQAAAAScHJpY2VBc3NldERlY2ltYWxzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAOcG9vbENvbmZpZ0xpc3QFAAAAFWlkeFByaWNlQXNzZXREZWNpbWFscwQAAAAKcG9vbFN0YXR1cwkAAZEAAAACBQAAAA5wb29sQ29uZmlnTGlzdAUAAAANaWR4UG9vbFN0YXR1cwQAAAARdXNlckxpcXVpZGl0eUxpc3QJAQAAABZnZXRQb29sTGlxdWlkaXR5QnlVc2VyAAAAAwUAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkBQAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAUAAAALdXNlckFkZHJlc3MEAAAADXVzZXJMUEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABF1c2VyTGlxdWlkaXR5TGlzdAUAAAARaWR4UG9vbExQQXNzZXRBbXQEAAAAFnVzZXJBbW91bnRBc3NldEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABF1c2VyTGlxdWlkaXR5TGlzdAUAAAAVaWR4UG9vbEFtb3VudEFzc2V0QW10BAAAABV1c2VyUHJpY2VBc3NldEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABF1c2VyTGlxdWlkaXR5TGlzdAUAAAAUaWR4UG9vbFByaWNlQXNzZXRBbXQEAAAAEXBvb2xMaXF1aWRpdHlMaXN0CQEAAAAQZ2V0UG9vbExpcXVpZGl0eQAAAAIFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQEAAAADXBvb2xMUEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABFwb29sTGlxdWlkaXR5TGlzdAUAAAARaWR4UG9vbExQQXNzZXRBbXQEAAAAFnBvb2xBbW91bnRBc3NldEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABFwb29sTGlxdWlkaXR5TGlzdAUAAAAVaWR4UG9vbEFtb3VudEFzc2V0QW10BAAAABVwb29sUHJpY2VBc3NldEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABFwb29sTGlxdWlkaXR5TGlzdAUAAAAUaWR4UG9vbFByaWNlQXNzZXRBbXQDCQEAAAACIT0AAAACBQAAAAlscEFzc2V0SWQFAAAAEHBheW1lbnRMcEFzc2V0SWQJAAACAAAAAQIAAAAVSW52YWxpZCBhc3NldCBwYXNzZWQuBAAAABlhY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlCQEAAAAYcHJpdmF0ZUdldEFjY291bnRCYWxhbmNlAAAAAQUAAAANYW1vdW50QXNzZXRJZAQAAAAYYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlCQEAAAAYcHJpdmF0ZUdldEFjY291bnRCYWxhbmNlAAAAAQUAAAAMcHJpY2VBc3NldElkBAAAABhhbW91bnRBc3NldFBvb2xMb2NrZWRBbXQJAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMFAAAAGWFjY291bnRBbW91bnRBc3NldEJhbGFuY2UFAAAABnNjYWxlOAUAAAASYW1vdXRBc3NldERlY2ltYWxzBAAAABdwcmljZUFzc2V0UG9vbExvY2tlZEFtdAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAAYYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlBQAAAAZzY2FsZTgFAAAAEnByaWNlQXNzZXREZWNpbWFscwQAAAARb3V0QW1vdW50QXNzZXRBbXQJAABrAAAAAwUAAAAYYW1vdW50QXNzZXRQb29sTG9ja2VkQW10BQAAAA9wYXltZW50THBBbW91bnQFAAAADXBvb2xMUEJhbGFuY2UEAAAAEG91dFByaWNlQXNzZXRBbXQJAABrAAAAAwUAAAAXcHJpY2VBc3NldFBvb2xMb2NrZWRBbXQFAAAAD3BheW1lbnRMcEFtb3VudAUAAAANcG9vbExQQmFsYW5jZQQAAAAWb3V0QW1vdW50QXNzZXRBbXRGaW5hbAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAARb3V0QW1vdW50QXNzZXRBbXQFAAAAEmFtb3V0QXNzZXREZWNpbWFscwUAAAAGc2NhbGU4BAAAABVvdXRQcmljZUFzc2V0QW10RmluYWwJAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMFAAAAEG91dFByaWNlQXNzZXRBbXQFAAAAEnByaWNlQXNzZXREZWNpbWFscwUAAAAGc2NhbGU4BAAAAAxjdXJyZW50UHJpY2UJAQAAAA5jYWxjdWxhdGVQcmljZQAAAAIFAAAAF3ByaWNlQXNzZXRQb29sTG9ja2VkQW10BQAAABhhbW91bnRBc3NldFBvb2xMb2NrZWRBbXQJAAUgAAAADgUAAAAWb3V0QW1vdW50QXNzZXRBbXRGaW5hbAUAAAAVb3V0UHJpY2VBc3NldEFtdEZpbmFsBQAAABVhbW91bnRBc3NldEludGVybmFsSWQFAAAAFHByaWNlQXNzZXRJbnRlcm5hbElkBQAAABZ1c2VyQW1vdW50QXNzZXRCYWxhbmNlBQAAAA1hbW91bnRBc3NldElkBQAAABV1c2VyUHJpY2VBc3NldEJhbGFuY2UFAAAADHByaWNlQXNzZXRJZAUAAAANdXNlckxQQmFsYW5jZQUAAAAWcG9vbEFtb3VudEFzc2V0QmFsYW5jZQUAAAAVcG9vbFByaWNlQXNzZXRCYWxhbmNlBQAAAA1wb29sTFBCYWxhbmNlBQAAAAxjdXJyZW50UHJpY2UFAAAACnBvb2xTdGF0dXMBAAAAG3ByaXZhdGVFc3RpbWF0ZVB1dE9wZXJhdGlvbgAAAAYAAAARc2xpcHBhZ2VUb2xlcmFuY2UAAAAQaW5BbW91bnRBc3NldEFtdAAAAA9pbkFtb3VudEFzc2V0SWQAAAAPaW5QcmljZUFzc2V0QW10AAAADmluUHJpY2VBc3NldElkAAAAC3VzZXJBZGRyZXNzBAAAABJwb29sQ29uZmlnRGF0YUxpc3QJAQAAAA1nZXRQb29sQ29uZmlnAAAAAAQAAAAJbHBBc3NldElkCQACWQAAAAEJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABBpZHhQb29sTFBBc3NldElkBAAAAA1hbW91bnRBc3NldElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAQaWR4QW1vdW50QXNzZXRJZAQAAAAMcHJpY2VBc3NldElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAPaWR4UHJpY2VBc3NldElkBAAAABVhbW91bnRBc3NldEludGVybmFsSWQJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABhpZHhBbW91bnRBc3NldEludGVybmFsSWQEAAAAFHByaWNlQXNzZXRJbnRlcm5hbElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAXaWR4UHJpY2VBc3NldEludGVybmFsSWQEAAAAEmFtb3V0QXNzZXREZWNpbWFscwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAWaWR4QW1vdW50QXNzZXREZWNpbWFscwQAAAAScHJpY2VBc3NldERlY2ltYWxzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABVpZHhQcmljZUFzc2V0RGVjaW1hbHMEAAAACnBvb2xTdGF0dXMJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAAA1pZHhQb29sU3RhdHVzBAAAABVwb29sTGlxdWlkaXR5RGF0YUxpc3QJAQAAABBnZXRQb29sTGlxdWlkaXR5AAAAAgUAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkBQAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAQAAAAWcG9vbEFtb3VudEFzc2V0QmFsYW5jZQkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAFXBvb2xMaXF1aWRpdHlEYXRhTGlzdAUAAAAVaWR4UG9vbEFtb3VudEFzc2V0QW10BAAAABVwb29sUHJpY2VBc3NldEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABVwb29sTGlxdWlkaXR5RGF0YUxpc3QFAAAAFGlkeFBvb2xQcmljZUFzc2V0QW10BAAAAA1wb29sTFBCYWxhbmNlCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAVcG9vbExpcXVpZGl0eURhdGFMaXN0BQAAABFpZHhQb29sTFBBc3NldEFtdAQAAAAVdXNlckxpcXVpZGl0eURhdGFMaXN0CQEAAAAWZ2V0UG9vbExpcXVpZGl0eUJ5VXNlcgAAAAMFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQFAAAAC3VzZXJBZGRyZXNzBAAAABZ1c2VyQW1vdW50QXNzZXRCYWxhbmNlCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAVdXNlckxpcXVpZGl0eURhdGFMaXN0BQAAABVpZHhQb29sQW1vdW50QXNzZXRBbXQEAAAAFXVzZXJQcmljZUFzc2V0QmFsYW5jZQkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAFXVzZXJMaXF1aWRpdHlEYXRhTGlzdAUAAAAUaWR4UG9vbFByaWNlQXNzZXRBbXQEAAAADXVzZXJMUEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABV1c2VyTGlxdWlkaXR5RGF0YUxpc3QFAAAAEWlkeFBvb2xMUEFzc2V0QW10AwMJAQAAAAIhPQAAAAIFAAAADWFtb3VudEFzc2V0SWQFAAAAD2luQW1vdW50QXNzZXRJZAYJAQAAAAIhPQAAAAIFAAAADHByaWNlQXNzZXRJZAUAAAAOaW5QcmljZUFzc2V0SWQJAAACAAAAAQIAAAAlSW52YWxpZCBhbW91bnQgb3IgcHJpY2UgYXNzZXQgcGFzc2VkLgQAAAAZYWNjb3VudEFtb3VudEFzc2V0QmFsYW5jZQkBAAAAGHByaXZhdGVHZXRBY2NvdW50QmFsYW5jZQAAAAEFAAAADWFtb3VudEFzc2V0SWQEAAAAGGFjY291bnRQcmljZUFzc2V0QmFsYW5jZQkBAAAAGHByaXZhdGVHZXRBY2NvdW50QmFsYW5jZQAAAAEFAAAADHByaWNlQXNzZXRJZAQAAAAaaW5BbW91bnRBc3NldEFtdENhbGN1bGF0ZWQJAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMFAAAAEGluQW1vdW50QXNzZXRBbXQFAAAABnNjYWxlOAUAAAASYW1vdXRBc3NldERlY2ltYWxzBAAAABlpblByaWNlQXNzZXRBbXRDYWxjdWxhdGVkCQEAAAAUcHJpdmF0ZUNhc3RUb1NjYWxlT2YAAAADBQAAAA9pblByaWNlQXNzZXRBbXQFAAAABnNjYWxlOAUAAAAScHJpY2VBc3NldERlY2ltYWxzBAAAAAl1c2VyUHJpY2UJAQAAAA5jYWxjdWxhdGVQcmljZQAAAAIFAAAAGWluUHJpY2VBc3NldEFtdENhbGN1bGF0ZWQFAAAAGmluQW1vdW50QXNzZXRBbXRDYWxjdWxhdGVkBAAAABhhbW91bnRBc3NldFBvb2xMb2NrZWRBbXQJAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMFAAAAGWFjY291bnRBbW91bnRBc3NldEJhbGFuY2UFAAAABnNjYWxlOAUAAAASYW1vdXRBc3NldERlY2ltYWxzBAAAABdwcmljZUFzc2V0UG9vbExvY2tlZEFtdAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAAYYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlBQAAAAZzY2FsZTgFAAAAEnByaWNlQXNzZXREZWNpbWFscwQAAAALY3VyZW50UHJpY2UDCQAAAAAAAAIFAAAADXBvb2xMUEJhbGFuY2UAAAAAAAAAAAAAAAAAAAAAAAAJAQAAAA5jYWxjdWxhdGVQcmljZQAAAAIFAAAAF3ByaWNlQXNzZXRQb29sTG9ja2VkQW10BQAAABhhbW91bnRBc3NldFBvb2xMb2NrZWRBbXQEAAAACHNsaXBwYWdlAwkAAAAAAAACBQAAAAtjdXJlbnRQcmljZQAAAAAAAAAAAAAAAAAAAAAAAAMJAABmAAAAAgUAAAALY3VyZW50UHJpY2UFAAAACXVzZXJQcmljZQkAAGsAAAADCQAAZQAAAAIFAAAAC2N1cmVudFByaWNlBQAAAAl1c2VyUHJpY2UAAAAAAAAAAGQFAAAAC2N1cmVudFByaWNlCQAAawAAAAMJAABlAAAAAgUAAAAJdXNlclByaWNlBQAAAAtjdXJlbnRQcmljZQAAAAAAAAAAZAUAAAALY3VyZW50UHJpY2UDAwkBAAAAAiE9AAAAAgUAAAALY3VyZW50UHJpY2UAAAAAAAAAAAAJAABmAAAAAgkAAGgAAAACBQAAAAhzbGlwcGFnZQUAAAAGc2NhbGU4BQAAABFzbGlwcGFnZVRvbGVyYW5jZQcJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAPUHJpY2Ugc2xpcHBhZ2UgCQABpAAAAAEJAABoAAAAAgUAAAAIc2xpcHBhZ2UFAAAABnNjYWxlOAIAAAAeIGV4Y2VlZGVkIHRoZSBwYXNzZWQgbGltaXQgb2YgCQABpAAAAAEFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBAAAAApmaW5hbFByaWNlCQEAAAAOY2FsY3VsYXRlUHJpY2UAAAACCQAAZAAAAAIFAAAAF3ByaWNlQXNzZXRQb29sTG9ja2VkQW10BQAAABlpblByaWNlQXNzZXRBbXRDYWxjdWxhdGVkCQAAZAAAAAIFAAAAGGFtb3VudEFzc2V0UG9vbExvY2tlZEFtdAUAAAAaaW5BbW91bnRBc3NldEFtdENhbGN1bGF0ZWQEAAAAC291dExwQW1vdW50AwkAAAAAAAACBQAAAA1wb29sTFBCYWxhbmNlAAAAAAAAAAAABAAAAAVwYXJ0QQkAAGwAAAAGBQAAABppbkFtb3VudEFzc2V0QW10Q2FsY3VsYXRlZAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAQAAAAAAAAAAAAUAAAAERE9XTgQAAAAFcGFydEIJAABsAAAABgUAAAAZaW5QcmljZUFzc2V0QW10Q2FsY3VsYXRlZAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAQAAAAAAAAAAAAUAAAAERE9XTgkAAGgAAAACBQAAAAVwYXJ0QQUAAAAFcGFydEIEAAAAEmxwQW10QnlBbW91bnRBc3NldAkAAGsAAAADBQAAAA1wb29sTFBCYWxhbmNlBQAAABppbkFtb3VudEFzc2V0QW10Q2FsY3VsYXRlZAUAAAAYYW1vdW50QXNzZXRQb29sTG9ja2VkQW10BAAAABFscEFtdEJ5UHJpY2VBc3NldAkAAGsAAAADBQAAAA1wb29sTFBCYWxhbmNlBQAAABlpblByaWNlQXNzZXRBbXRDYWxjdWxhdGVkBQAAABdwcmljZUFzc2V0UG9vbExvY2tlZEFtdAMJAABmAAAAAgUAAAARbHBBbXRCeVByaWNlQXNzZXQFAAAAEmxwQW10QnlBbW91bnRBc3NldAUAAAASbHBBbXRCeUFtb3VudEFzc2V0BQAAABFscEFtdEJ5UHJpY2VBc3NldAkABR8AAAANBQAAAAtvdXRMcEFtb3VudAUAAAAKZmluYWxQcmljZQUAAAAWdXNlckFtb3VudEFzc2V0QmFsYW5jZQUAAAAVdXNlclByaWNlQXNzZXRCYWxhbmNlBQAAAA11c2VyTFBCYWxhbmNlBQAAABZwb29sQW1vdW50QXNzZXRCYWxhbmNlBQAAABVwb29sUHJpY2VBc3NldEJhbGFuY2UFAAAADXBvb2xMUEJhbGFuY2UFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQFAAAACWxwQXNzZXRJZAUAAAAIc2xpcHBhZ2UFAAAACnBvb2xTdGF0dXMBAAAAG3ZhbGlkYXRlTWF0Y2hlck9yZGVyQWxsb3dlZAAAAAEAAAAFb3JkZXIEAAAAEnBvb2xDb25maWdEYXRhTGlzdAkBAAAADWdldFBvb2xDb25maWcAAAAABAAAAA1hbW91bnRBc3NldElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAQaWR4QW1vdW50QXNzZXRJZAQAAAAMcHJpY2VBc3NldElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAPaWR4UHJpY2VBc3NldElkBAAAAApwb29sU3RhdHVzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAAA1pZHhQb29sU3RhdHVzBAAAABNtYXRjaGVyUHVibGljS2V5U3RyCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAATaWR4TWF0Y2hlclB1YmxpY0tleQQAAAATYW1vdW50QXNzZXREZWNpbWFscwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAWaWR4QW1vdW50QXNzZXREZWNpbWFscwQAAAAScHJpY2VBc3NldERlY2ltYWxzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABVpZHhQcmljZUFzc2V0RGVjaW1hbHMEAAAAGWFjY291bnRBbW91bnRBc3NldEJhbGFuY2UJAQAAABhwcml2YXRlR2V0QWNjb3VudEJhbGFuY2UAAAABBQAAAA1hbW91bnRBc3NldElkBAAAABhhY2NvdW50UHJpY2VBc3NldEJhbGFuY2UJAQAAABhwcml2YXRlR2V0QWNjb3VudEJhbGFuY2UAAAABBQAAAAxwcmljZUFzc2V0SWQEAAAADGN1cnJlbnRQcmljZQMJAAAAAAAAAggFAAAABW9yZGVyAAAACW9yZGVyVHlwZQUAAAADQnV5CQEAAAAVcHJpdmF0ZUNhbGN1bGF0ZVByaWNlAAAABAUAAAATYW1vdW50QXNzZXREZWNpbWFscwUAAAAScHJpY2VBc3NldERlY2ltYWxzCQAAZAAAAAIFAAAAGWFjY291bnRBbW91bnRBc3NldEJhbGFuY2UIBQAAAAVvcmRlcgAAAAZhbW91bnQFAAAAGGFjY291bnRQcmljZUFzc2V0QmFsYW5jZQkBAAAAFXByaXZhdGVDYWxjdWxhdGVQcmljZQAAAAQFAAAAE2Ftb3VudEFzc2V0RGVjaW1hbHMFAAAAEnByaWNlQXNzZXREZWNpbWFscwkAAGQAAAACBQAAABlhY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlCAUAAAAFb3JkZXIAAAAGYW1vdW50BQAAABhhY2NvdW50UHJpY2VBc3NldEJhbGFuY2UEAAAAEWlzUG9vbFN0YXR1c1ZhbGlkAwMDCQEAAAAQaXNHbG9iYWxTaHV0ZG93bgAAAAAGCQAAAAAAAAIFAAAACnBvb2xTdGF0dXMFAAAAE1Bvb2xNYXRjaGVyRGlzYWJsZWQGCQAAAAAAAAIFAAAACnBvb2xTdGF0dXMFAAAADFBvb2xTaHV0ZG93bgcGBAAAABJpc1ZhbGlkTWF0Y2hlclNpZ24JAAH0AAAAAwgFAAAABW9yZGVyAAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAAFb3JkZXIAAAAGcHJvb2ZzAAAAAAAAAAAACQACWQAAAAEFAAAAE21hdGNoZXJQdWJsaWNLZXlTdHIEAAAAEG9yZGVyQW1vdW50QXNzZXQICAUAAAAFb3JkZXIAAAAJYXNzZXRQYWlyAAAAC2Ftb3VudEFzc2V0BAAAABNvcmRlckFtb3VudEFzc2V0U3RyAwkAAAAAAAACBQAAABBvcmRlckFtb3VudEFzc2V0BQAAAAR1bml0AgAAAAVXQVZFUwkAAlgAAAABCQEAAAAFdmFsdWUAAAABBQAAABBvcmRlckFtb3VudEFzc2V0BAAAAA9vcmRlclByaWNlQXNzZXQICAUAAAAFb3JkZXIAAAAJYXNzZXRQYWlyAAAACnByaWNlQXNzZXQEAAAAEm9yZGVyUHJpY2VBc3NldFN0cgMJAAAAAAAAAgUAAAAPb3JkZXJQcmljZUFzc2V0BQAAAAR1bml0AgAAAAVXQVZFUwkAAlgAAAABCQEAAAAFdmFsdWUAAAABBQAAAA9vcmRlclByaWNlQXNzZXQEAAAAEGlzVmFsaWRBc3NldFBhaXIDAwkBAAAAAiE9AAAAAgUAAAATb3JkZXJBbW91bnRBc3NldFN0cgUAAAANYW1vdW50QXNzZXRJZAYJAQAAAAIhPQAAAAIFAAAAEm9yZGVyUHJpY2VBc3NldFN0cgUAAAAMcHJpY2VBc3NldElkBwYEAAAACm9yZGVyUHJpY2UIBQAAAAVvcmRlcgAAAAVwcmljZQQAAAANcHJpY2VEZWNpbWFscwkAAGsAAAADBQAAAAZzY2FsZTgFAAAAEnByaWNlQXNzZXREZWNpbWFscwUAAAATYW1vdW50QXNzZXREZWNpbWFscwQAAAAQY2FzdGVkT3JkZXJQcmljZQkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAAKb3JkZXJQcmljZQUAAAAGc2NhbGU4BQAAAA1wcmljZURlY2ltYWxzBAAAABFpc09yZGVyUHJpY2VWYWxpZAMJAAAAAAAAAggFAAAABW9yZGVyAAAACW9yZGVyVHlwZQUAAAADQnV5CQAAZwAAAAIFAAAADGN1cnJlbnRQcmljZQUAAAAQY2FzdGVkT3JkZXJQcmljZQkAAGcAAAACBQAAABBjYXN0ZWRPcmRlclByaWNlBQAAAAxjdXJyZW50UHJpY2UJAARMAAAAAgMDAwUAAAAQaXNWYWxpZEFzc2V0UGFpcgUAAAASaXNWYWxpZE1hdGNoZXJTaWduBwUAAAARaXNQb29sU3RhdHVzVmFsaWQHBQAAABFpc09yZGVyUHJpY2VWYWxpZAcFAAAAA25pbAAAAAgAAAABaQEAAAADcHV0AAAAAgAAABFzbGlwcGFnZVRvbGVyYW5jZQAAAA9zaG91bGRBdXRvU3Rha2UEAAAAEWZhY3RvcnlDb25maWdMaXN0CQEAAAAQZ2V0RmFjdG9yeUNvbmZpZwAAAAAEAAAAD3N0YWtpbmdDb250cmFjdAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEJgAAAAEJAAGRAAAAAgUAAAARZmFjdG9yeUNvbmZpZ0xpc3QFAAAAGWlkeEZhY3RvcnlTdGFraW5nQ29udHJhY3QCAAAAIUVycm9yLiBJbmNvcnJlY3Qgc3Rha2luZyBhZGRyZXNzLgQAAAAOcG10QW1vdW50QXNzZXQJAQAAAAV2YWx1ZQAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAAEGluQW1vdW50QXNzZXRBbXQIBQAAAA5wbXRBbW91bnRBc3NldAAAAAZhbW91bnQEAAAAD2luQW1vdW50QXNzZXRJZAMJAQAAAAEhAAAAAQkBAAAACWlzRGVmaW5lZAAAAAEIBQAAAA5wbXRBbW91bnRBc3NldAAAAAdhc3NldElkCQACWQAAAAECAAAABVdBVkVTCQEAAAAFdmFsdWUAAAABCAUAAAAOcG10QW1vdW50QXNzZXQAAAAHYXNzZXRJZAQAAAANcG10UHJpY2VBc3NldAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQQAAAAPaW5QcmljZUFzc2V0QW10CAUAAAANcG10UHJpY2VBc3NldAAAAAZhbW91bnQEAAAADmluUHJpY2VBc3NldElkAwkBAAAAASEAAAABCQEAAAAJaXNEZWZpbmVkAAAAAQgFAAAADXBtdFByaWNlQXNzZXQAAAAHYXNzZXRJZAkAAlkAAAABAgAAAAVXQVZFUwkBAAAABXZhbHVlAAAAAQgFAAAADXBtdFByaWNlQXNzZXQAAAAHYXNzZXRJZAQAAAATZXN0aW1hdGVkUHV0UmVzdWx0cwkBAAAAG3ByaXZhdGVFc3RpbWF0ZVB1dE9wZXJhdGlvbgAAAAYFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABBpbkFtb3VudEFzc2V0QW10CQACWAAAAAEFAAAAD2luQW1vdW50QXNzZXRJZAUAAAAPaW5QcmljZUFzc2V0QW10CQACWAAAAAEFAAAADmluUHJpY2VBc3NldElkCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAALb3V0THBBbW91bnQIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl8xBAAAAAtjdXJlbnRQcmljZQgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzIEAAAAFnVzZXJBbW91bnRBc3NldEJhbGFuY2UIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl8zBAAAABV1c2VyUHJpY2VBc3NldEJhbGFuY2UIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl80BAAAAA11c2VyTFBCYWxhbmNlCAUAAAATZXN0aW1hdGVkUHV0UmVzdWx0cwAAAAJfNQQAAAAWcG9vbEFtb3VudEFzc2V0QmFsYW5jZQgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzYEAAAAFXBvb2xQcmljZUFzc2V0QmFsYW5jZQgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzcEAAAADXBvb2xMUEJhbGFuY2UIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl84BAAAABVhbW91bnRBc3NldEludGVybmFsSWQIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl85BAAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAADXzEwBAAAAAlscEFzc2V0SWQIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAA18xMQQAAAASc2xpcHBhZ2VDYWxjdWxhdGVkCAUAAAATZXN0aW1hdGVkUHV0UmVzdWx0cwAAAANfMTIEAAAACnBvb2xTdGF0dXMJAQAAAA1wYXJzZUludFZhbHVlAAAAAQgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAADXzEzAwMDCQEAAAAQaXNHbG9iYWxTaHV0ZG93bgAAAAAGCQAAAAAAAAIFAAAACnBvb2xTdGF0dXMFAAAAD1Bvb2xQdXREaXNhYmxlZAYJAAAAAAAAAgUAAAAKcG9vbFN0YXR1cwUAAAAMUG9vbFNodXRkb3duCQAAAgAAAAEJAAEsAAAAAgIAAAAsUHV0IG9wZXJhdGlvbiBpcyBibG9ja2VkIGJ5IGFkbWluLiBTdGF0dXMgPSAJAAGkAAAAAQUAAAAKcG9vbFN0YXR1cwQAAAAUZW1pdExQQXNzZXRPbkZhY3RvcnkJAAP8AAAABAUAAAAPZmFjdG9yeUNvbnRyYWN0AgAAAARlbWl0CQAETAAAAAIFAAAAC291dExwQW1vdW50BQAAAANuaWwFAAAAA25pbAMJAAAAAAAAAgUAAAAUZW1pdExQQXNzZXRPbkZhY3RvcnkFAAAAFGVtaXRMUEFzc2V0T25GYWN0b3J5AwkBAAAAAiE9AAAAAgUAAAAUZW1pdExQQXNzZXRPbkZhY3RvcnkCAAAAB3N1Y2Nlc3MJAAACAAAAAQIAAAA0TFAgYXNzZXQgcmVpc3N1ZSBmYWlsZWQgZHVyaW5nIGVtaXQgY2FsbCBvbiBmYWN0b3J5LgQAAAAHcmVzdWx0cwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAMa2V5UHJpY2VMYXN0AAAAAAkAASwAAAACAgAAAAQlc19fCQABpAAAAAEFAAAAC2N1cmVudFByaWNlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAA9rZXlQcmljZUhpc3RvcnkAAAACBQAAAAZoZWlnaHQIBQAAAAlsYXN0QmxvY2sAAAAJdGltZXN0YW1wCQABLAAAAAICAAAABCVzX18JAAGkAAAAAQUAAAALY3VyZW50UHJpY2UJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEmtleVB1dEFjdGlvbkJ5VXNlcgAAAAIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyCQACWAAAAAEIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQJAQAAABFkYXRhUHV0QWN0aW9uSW5mbwAAAAgFAAAAEGluQW1vdW50QXNzZXRBbXQFAAAAD2luUHJpY2VBc3NldEFtdAUAAAALb3V0THBBbW91bnQFAAAAC2N1cmVudFByaWNlBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAASc2xpcHBhZ2VDYWxjdWxhdGVkBQAAAAZoZWlnaHQIBQAAAAlsYXN0QmxvY2sAAAAJdGltZXN0YW1wCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABZrZXlQb29sTGlxdWlkaXR5QnlVc2VyAAAAAwUAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkBQAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIJAQAAABFkYXRhUG9vbExpcXVpZGl0eQAAAAMJAABkAAAAAgUAAAAWdXNlckFtb3VudEFzc2V0QmFsYW5jZQUAAAAQaW5BbW91bnRBc3NldEFtdAkAAGQAAAACBQAAABV1c2VyUHJpY2VBc3NldEJhbGFuY2UFAAAAD2luUHJpY2VBc3NldEFtdAkAAGQAAAACBQAAAA11c2VyTFBCYWxhbmNlBQAAAAtvdXRMcEFtb3VudAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAQa2V5UG9vbExpcXVpZGl0eQAAAAIFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQJAQAAABFkYXRhUG9vbExpcXVpZGl0eQAAAAMJAABkAAAAAgUAAAAWcG9vbEFtb3VudEFzc2V0QmFsYW5jZQUAAAAQaW5BbW91bnRBc3NldEFtdAkAAGQAAAACBQAAABVwb29sUHJpY2VBc3NldEJhbGFuY2UFAAAAD2luUHJpY2VBc3NldEFtdAkAAGQAAAACBQAAAA1wb29sTFBCYWxhbmNlBQAAAAtvdXRMcEFtb3VudAUAAAADbmlsAwUAAAAPc2hvdWxkQXV0b1N0YWtlBAAAAAVzdGFrZQkAA/wAAAAEBQAAAA9zdGFraW5nQ29udHJhY3QCAAAABXN0YWtlBQAAAANuaWwJAARMAAAAAgkBAAAAD0F0dGFjaGVkUGF5bWVudAAAAAIFAAAACWxwQXNzZXRJZAUAAAALb3V0THBBbW91bnQFAAAAA25pbAMJAAAAAAAAAgUAAAAFc3Rha2UFAAAABXN0YWtlBQAAAAdyZXN1bHRzCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkABE0AAAACBQAAAAdyZXN1bHRzCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAC291dExwQW1vdW50BQAAAAlscEFzc2V0SWQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAA2dldAAAAAAEAAAADnBtdEFtb3VudEFzc2V0CQEAAAAFdmFsdWUAAAABCQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAABAAAAApwbXRBc3NldElkCQEAAAAFdmFsdWUAAAABCAUAAAAOcG10QW1vdW50QXNzZXQAAAAHYXNzZXRJZAQAAAAOcG10QXNzZXRBbW91bnQIBQAAAA5wbXRBbW91bnRBc3NldAAAAAZhbW91bnQEAAAAB3Jlc3VsdHMJAQAAABtwcml2YXRlRXN0aW1hdGVHZXRPcGVyYXRpb24AAAADCQACWAAAAAEFAAAACnBtdEFzc2V0SWQFAAAADnBtdEFzc2V0QW1vdW50CQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAARb3V0QW1vdW50QXNzZXRBbXQIBQAAAAdyZXN1bHRzAAAAAl8xBAAAABBvdXRQcmljZUFzc2V0QW10CAUAAAAHcmVzdWx0cwAAAAJfMgQAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkCAUAAAAHcmVzdWx0cwAAAAJfMwQAAAAUcHJpY2VBc3NldEludGVybmFsSWQIBQAAAAdyZXN1bHRzAAAAAl80BAAAABZ1c2VyQW1vdW50QXNzZXRCYWxhbmNlCAUAAAAHcmVzdWx0cwAAAAJfNQQAAAANYW1vdW50QXNzZXRJZAgFAAAAB3Jlc3VsdHMAAAACXzYEAAAAFXVzZXJQcmljZUFzc2V0QmFsYW5jZQgFAAAAB3Jlc3VsdHMAAAACXzcEAAAADHByaWNlQXNzZXRJZAgFAAAAB3Jlc3VsdHMAAAACXzgEAAAADXVzZXJMUEJhbGFuY2UIBQAAAAdyZXN1bHRzAAAAAl85BAAAABZwb29sQW1vdW50QXNzZXRCYWxhbmNlCAUAAAAHcmVzdWx0cwAAAANfMTAEAAAAFXBvb2xQcmljZUFzc2V0QmFsYW5jZQgFAAAAB3Jlc3VsdHMAAAADXzExBAAAAA1wb29sTFBCYWxhbmNlCAUAAAAHcmVzdWx0cwAAAANfMTIEAAAADGN1cnJlbnRQcmljZQgFAAAAB3Jlc3VsdHMAAAADXzEzBAAAAApwb29sU3RhdHVzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEIBQAAAAdyZXN1bHRzAAAAA18xNAMDCQEAAAAQaXNHbG9iYWxTaHV0ZG93bgAAAAAGCQAAAAAAAAIFAAAACnBvb2xTdGF0dXMFAAAADFBvb2xTaHV0ZG93bgkAAAIAAAABCQABLAAAAAICAAAALEdldCBvcGVyYXRpb24gaXMgYmxvY2tlZCBieSBhZG1pbi4gU3RhdHVzID0gCQABpAAAAAEFAAAACnBvb2xTdGF0dXMEAAAAFGJ1cm5MUEFzc2V0T25GYWN0b3J5CQAD/AAAAAQFAAAAD2ZhY3RvcnlDb250cmFjdAIAAAAEYnVybgkABEwAAAACBQAAAA5wbXRBc3NldEFtb3VudAUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAApwbXRBc3NldElkBQAAAA5wbXRBc3NldEFtb3VudAUAAAADbmlsAwkAAAAAAAACBQAAABRidXJuTFBBc3NldE9uRmFjdG9yeQUAAAAUYnVybkxQQXNzZXRPbkZhY3RvcnkDCQEAAAACIT0AAAACBQAAABRidXJuTFBBc3NldE9uRmFjdG9yeQIAAAAHc3VjY2VzcwkAAAIAAAABAgAAADFMUCBhc3NldCBidXJuIGZhaWxlZCBkdXJpbmcgZW1pdCBjYWxsIG9uIGZhY3RvcnkuCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAARb3V0QW1vdW50QXNzZXRBbXQDCQAAAAAAAAIFAAAADWFtb3VudEFzc2V0SWQCAAAABVdBVkVTBQAAAAR1bml0CQACWQAAAAEFAAAADWFtb3VudEFzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABBvdXRQcmljZUFzc2V0QW10CQACWQAAAAEFAAAADHByaWNlQXNzZXRJZAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAWa2V5UG9vbExpcXVpZGl0eUJ5VXNlcgAAAAMFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyCQEAAAARZGF0YVBvb2xMaXF1aWRpdHkAAAADCQAAZQAAAAIFAAAAFnVzZXJBbW91bnRBc3NldEJhbGFuY2UFAAAAEW91dEFtb3VudEFzc2V0QW10CQAAZQAAAAIFAAAAFXVzZXJQcmljZUFzc2V0QmFsYW5jZQUAAAAQb3V0UHJpY2VBc3NldEFtdAkAAGUAAAACBQAAAA11c2VyTFBCYWxhbmNlBQAAAA5wbXRBc3NldEFtb3VudAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAQa2V5UG9vbExpcXVpZGl0eQAAAAIFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQJAQAAABFkYXRhUG9vbExpcXVpZGl0eQAAAAMJAABlAAAAAgUAAAAWcG9vbEFtb3VudEFzc2V0QmFsYW5jZQUAAAARb3V0QW1vdW50QXNzZXRBbXQJAABlAAAAAgUAAAAVcG9vbFByaWNlQXNzZXRCYWxhbmNlBQAAABBvdXRQcmljZUFzc2V0QW10CQAAZQAAAAIFAAAADXBvb2xMUEJhbGFuY2UFAAAADnBtdEFzc2V0QW1vdW50CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABJrZXlHZXRBY3Rpb25CeVVzZXIAAAACCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkCQEAAAARZGF0YUdldEFjdGlvbkluZm8AAAAGBQAAABFvdXRBbW91bnRBc3NldEFtdAUAAAAQb3V0UHJpY2VBc3NldEFtdAUAAAAOcG10QXNzZXRBbW91bnQFAAAADGN1cnJlbnRQcmljZQUAAAAGaGVpZ2h0CAUAAAAJbGFzdEJsb2NrAAAACXRpbWVzdGFtcAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAMa2V5UHJpY2VMYXN0AAAAAAkAASwAAAACAgAAAAQlc19fCQABpAAAAAEFAAAADGN1cnJlbnRQcmljZQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPa2V5UHJpY2VIaXN0b3J5AAAAAgUAAAAGaGVpZ2h0CAUAAAAJbGFzdEJsb2NrAAAACXRpbWVzdGFtcAkAASwAAAACAgAAAAQlc19fCQABpAAAAAEFAAAADGN1cnJlbnRQcmljZQUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAhhY3RpdmF0ZQAAAAIAAAAOYW1vdW50QXNzZXRTdHIAAAANcHJpY2VBc3NldFN0cgMJAQAAAAIhPQAAAAIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyCQAEJQAAAAEFAAAAD2ZhY3RvcnlDb250cmFjdAkAAAIAAAABAgAAABJwZXJtaXNzaW9ucyBkZW5pZWQJAAUUAAAAAgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAOa2V5QW1vdW50QXNzZXQAAAAABQAAAA5hbW91bnRBc3NldFN0cgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAANa2V5UHJpY2VBc3NldAAAAAAFAAAADXByaWNlQXNzZXRTdHIFAAAAA25pbAIAAAAHc3VjY2VzcwAAAAFpAQAAAA1zdGF0c1JFQURPTkxZAAAAAAQAAAAScG9vbENvbmZpZ0RhdGFMaXN0CQEAAAANZ2V0UG9vbENvbmZpZwAAAAAEAAAACWxwQXNzZXRJZAkAAlkAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAQaWR4UG9vbExQQXNzZXRJZAQAAAANYW1vdW50QXNzZXRJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAEGlkeEFtb3VudEFzc2V0SWQEAAAADHByaWNlQXNzZXRJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAD2lkeFByaWNlQXNzZXRJZAQAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAYaWR4QW1vdW50QXNzZXRJbnRlcm5hbElkBAAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAF2lkeFByaWNlQXNzZXRJbnRlcm5hbElkBAAAABJhbW91dEFzc2V0RGVjaW1hbHMJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAFmlkeEFtb3VudEFzc2V0RGVjaW1hbHMEAAAAEnByaWNlQXNzZXREZWNpbWFscwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAVaWR4UHJpY2VBc3NldERlY2ltYWxzBAAAABVwb29sTGlxdWlkaXR5RGF0YUxpc3QJAQAAABBnZXRQb29sTGlxdWlkaXR5AAAAAgUAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkBQAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAQAAAANcG9vbExQQmFsYW5jZQkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAFXBvb2xMaXF1aWRpdHlEYXRhTGlzdAUAAAARaWR4UG9vbExQQXNzZXRBbXQEAAAAGWFjY291bnRBbW91bnRBc3NldEJhbGFuY2UJAQAAABhwcml2YXRlR2V0QWNjb3VudEJhbGFuY2UAAAABBQAAAA1hbW91bnRBc3NldElkBAAAABhhY2NvdW50UHJpY2VBc3NldEJhbGFuY2UJAQAAABhwcml2YXRlR2V0QWNjb3VudEJhbGFuY2UAAAABBQAAAAxwcmljZUFzc2V0SWQEAAAACnByaWNlc0xpc3QJAQAAAAlnZXRQcmljZXMAAAADBQAAABlhY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlBQAAABhhY2NvdW50UHJpY2VBc3NldEJhbGFuY2UFAAAADXBvb2xMUEJhbGFuY2UEAAAADGN1cnJlbnRQcmljZQkAAZEAAAACBQAAAApwcmljZXNMaXN0AAAAAAAAAAAABAAAABRscFByaWNlSW5BbW91bnRBc3NldAkAAZEAAAACBQAAAApwcmljZXNMaXN0AAAAAAAAAAABBAAAABNscFByaWNlSW5QcmljZUFzc2V0CQABkQAAAAIFAAAACnByaWNlc0xpc3QAAAAAAAAAAAIEAAAACnBvb2xXZWlnaHQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA9mYWN0b3J5Q29udHJhY3QJAQAAAA1rZXlQb29sV2VpZ2h0AAAAAQkABCUAAAABBQAAAAR0aGlzAgAAABlQb29sIGRvZXNuJ3QgaGF2ZSB3ZWlnaHQuCQAFFAAAAAIFAAAAA25pbAkABLkAAAACCQAETAAAAAICAAAADiVkJWQlZCVkJWQlZCVkCQAETAAAAAIJAAGkAAAAAQUAAAAZYWNjb3VudEFtb3VudEFzc2V0QmFsYW5jZQkABEwAAAACCQABpAAAAAEFAAAAGGFjY291bnRQcmljZUFzc2V0QmFsYW5jZQkABEwAAAACCQABpAAAAAEFAAAADXBvb2xMUEJhbGFuY2UJAARMAAAAAgkAAaQAAAABBQAAAAxjdXJyZW50UHJpY2UJAARMAAAAAgkAAaQAAAABBQAAABRscFByaWNlSW5BbW91bnRBc3NldAkABEwAAAACCQABpAAAAAEFAAAAE2xwUHJpY2VJblByaWNlQXNzZXQJAARMAAAAAgkAAaQAAAABBQAAAApwb29sV2VpZ2h0BQAAAANuaWwFAAAAA1NFUAAAAAFpAQAAACBldmFsdWF0ZVB1dEJ5QW1vdW50QXNzZXRSRUFET05MWQAAAAMAAAARc2xpcHBhZ2VUb2xlcmFuY2UAAAAQaW5BbW91bnRBc3NldEFtdAAAAAt1c2VyQWRkcmVzcwQAAAAScG9vbENvbmZpZ0RhdGFMaXN0CQEAAAANZ2V0UG9vbENvbmZpZwAAAAAEAAAACWxwQXNzZXRJZAkAAlkAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAQaWR4UG9vbExQQXNzZXRJZAQAAAANYW1vdW50QXNzZXRJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAEGlkeEFtb3VudEFzc2V0SWQEAAAADHByaWNlQXNzZXRJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAD2lkeFByaWNlQXNzZXRJZAQAAAAVYW1vdW50QXNzZXRJbnRlcm5hbElkCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAYaWR4QW1vdW50QXNzZXRJbnRlcm5hbElkBAAAABRwcmljZUFzc2V0SW50ZXJuYWxJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAF2lkeFByaWNlQXNzZXRJbnRlcm5hbElkBAAAABJhbW91dEFzc2V0RGVjaW1hbHMJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAFmlkeEFtb3VudEFzc2V0RGVjaW1hbHMEAAAAEnByaWNlQXNzZXREZWNpbWFscwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAAVaWR4UHJpY2VBc3NldERlY2ltYWxzBAAAAApwb29sU3RhdHVzCQABkQAAAAIFAAAAEnBvb2xDb25maWdEYXRhTGlzdAUAAAANaWR4UG9vbFN0YXR1cwQAAAAVcG9vbExpcXVpZGl0eURhdGFMaXN0CQEAAAAQZ2V0UG9vbExpcXVpZGl0eQAAAAIFAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAUAAAAUcHJpY2VBc3NldEludGVybmFsSWQEAAAADXBvb2xMUEJhbGFuY2UJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABVwb29sTGlxdWlkaXR5RGF0YUxpc3QFAAAAEWlkeFBvb2xMUEFzc2V0QW10BAAAABlhY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlCQEAAAAYcHJpdmF0ZUdldEFjY291bnRCYWxhbmNlAAAAAQUAAAANYW1vdW50QXNzZXRJZAQAAAAYYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlCQEAAAAYcHJpdmF0ZUdldEFjY291bnRCYWxhbmNlAAAAAQUAAAAMcHJpY2VBc3NldElkBAAAAB9hY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlQ2FzdGVkCQEAAAAUcHJpdmF0ZUNhc3RUb1NjYWxlT2YAAAADBQAAABlhY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlBQAAAAZzY2FsZTgFAAAAEmFtb3V0QXNzZXREZWNpbWFscwQAAAAeYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlQ2FzdGVkCQEAAAAUcHJpdmF0ZUNhc3RUb1NjYWxlT2YAAAADBQAAABhhY2NvdW50UHJpY2VBc3NldEJhbGFuY2UFAAAABnNjYWxlOAUAAAAScHJpY2VBc3NldERlY2ltYWxzBAAAAAtjdXJlbnRQcmljZQMJAAAAAAAAAgUAAAANcG9vbExQQmFsYW5jZQAAAAAAAAAAAAAAAAAAAAAAAAkBAAAADmNhbGN1bGF0ZVByaWNlAAAAAgUAAAAeYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlQ2FzdGVkBQAAAB9hY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlQ2FzdGVkBAAAABlpblByaWNlQXNzZXRBbXRDYWxjdWxhdGVkCQAAawAAAAMFAAAAEGluQW1vdW50QXNzZXRBbXQFAAAAC2N1cmVudFByaWNlBQAAAAZzY2FsZTgEAAAAD2luUHJpY2VBc3NldEFtdAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAAZaW5QcmljZUFzc2V0QW10Q2FsY3VsYXRlZAUAAAAScHJpY2VBc3NldERlY2ltYWxzBQAAAAZzY2FsZTgEAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMJAQAAABtwcml2YXRlRXN0aW1hdGVQdXRPcGVyYXRpb24AAAAGBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAAQaW5BbW91bnRBc3NldEFtdAUAAAANYW1vdW50QXNzZXRJZAUAAAAPaW5QcmljZUFzc2V0QW10BQAAAAxwcmljZUFzc2V0SWQFAAAAC3VzZXJBZGRyZXNzBAAAAA9vdXRMcEFtb3VudENhbGMIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl8xBAAAAA9jdXJlbnRQcmljZUNhbGMIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl8yBAAAABpwb29sQW1vdW50QXNzZXRCYWxhbmNlQ2FsYwgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzYEAAAAGXBvb2xQcmljZUFzc2V0QmFsYW5jZUNBbGMIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAAl83BAAAABFwb29sTFBCYWxhbmNlQ2FsYwgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzgEAAAADnBvb2xTdGF0dXNDYWxjCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEIBQAAABNlc3RpbWF0ZWRQdXRSZXN1bHRzAAAAA18xMwkABRQAAAACBQAAAANuaWwJAAS5AAAAAgkABEwAAAACAgAAAAwlZCVkJWQlZCVkJWQJAARMAAAAAgkAAaQAAAABBQAAAA9vdXRMcEFtb3VudENhbGMJAARMAAAAAgkAAaQAAAABBQAAAA9jdXJlbnRQcmljZUNhbGMJAARMAAAAAgkAAaQAAAABBQAAABpwb29sQW1vdW50QXNzZXRCYWxhbmNlQ2FsYwkABEwAAAACCQABpAAAAAEFAAAAGXBvb2xQcmljZUFzc2V0QmFsYW5jZUNBbGMJAARMAAAAAgkAAaQAAAABBQAAABFwb29sTFBCYWxhbmNlQ2FsYwkABEwAAAACCQABpAAAAAEFAAAADnBvb2xTdGF0dXNDYWxjBQAAAANuaWwFAAAAA1NFUAAAAAFpAQAAAB9ldmFsdWF0ZVB1dEJ5UHJpY2VBc3NldFJFQURPTkxZAAAAAwAAABFzbGlwcGFnZVRvbGVyYW5jZQAAAA9pblByaWNlQXNzZXRBbXQAAAALdXNlckFkZHJlc3MEAAAAEnBvb2xDb25maWdEYXRhTGlzdAkBAAAADWdldFBvb2xDb25maWcAAAAABAAAAAlscEFzc2V0SWQJAAJZAAAAAQkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAEGlkeFBvb2xMUEFzc2V0SWQEAAAADWFtb3VudEFzc2V0SWQJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABBpZHhBbW91bnRBc3NldElkBAAAAAxwcmljZUFzc2V0SWQJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAAA9pZHhQcmljZUFzc2V0SWQEAAAAFWFtb3VudEFzc2V0SW50ZXJuYWxJZAkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAGGlkeEFtb3VudEFzc2V0SW50ZXJuYWxJZAQAAAAUcHJpY2VBc3NldEludGVybmFsSWQJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABdpZHhQcmljZUFzc2V0SW50ZXJuYWxJZAQAAAASYW1vdXRBc3NldERlY2ltYWxzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAScG9vbENvbmZpZ0RhdGFMaXN0BQAAABZpZHhBbW91bnRBc3NldERlY2ltYWxzBAAAABJwcmljZUFzc2V0RGVjaW1hbHMJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAAFWlkeFByaWNlQXNzZXREZWNpbWFscwQAAAAKcG9vbFN0YXR1cwkAAZEAAAACBQAAABJwb29sQ29uZmlnRGF0YUxpc3QFAAAADWlkeFBvb2xTdGF0dXMEAAAAFXBvb2xMaXF1aWRpdHlEYXRhTGlzdAkBAAAAEGdldFBvb2xMaXF1aWRpdHkAAAACBQAAABVhbW91bnRBc3NldEludGVybmFsSWQFAAAAFHByaWNlQXNzZXRJbnRlcm5hbElkBAAAAA1wb29sTFBCYWxhbmNlCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAVcG9vbExpcXVpZGl0eURhdGFMaXN0BQAAABFpZHhQb29sTFBBc3NldEFtdAQAAAAZYWNjb3VudEFtb3VudEFzc2V0QmFsYW5jZQkBAAAAGHByaXZhdGVHZXRBY2NvdW50QmFsYW5jZQAAAAEFAAAADWFtb3VudEFzc2V0SWQEAAAAGGFjY291bnRQcmljZUFzc2V0QmFsYW5jZQkBAAAAGHByaXZhdGVHZXRBY2NvdW50QmFsYW5jZQAAAAEFAAAADHByaWNlQXNzZXRJZAQAAAAfYWNjb3VudEFtb3VudEFzc2V0QmFsYW5jZUNhc3RlZAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAAZYWNjb3VudEFtb3VudEFzc2V0QmFsYW5jZQUAAAAGc2NhbGU4BQAAABJhbW91dEFzc2V0RGVjaW1hbHMEAAAAHmFjY291bnRQcmljZUFzc2V0QmFsYW5jZUNhc3RlZAkBAAAAFHByaXZhdGVDYXN0VG9TY2FsZU9mAAAAAwUAAAAYYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlBQAAAAZzY2FsZTgFAAAAEnByaWNlQXNzZXREZWNpbWFscwQAAAAeaW5QcmljZUFzc2V0QW10Q2FsY3VsYXRlZFR1cGxlCQEAAAAUcHJpdmF0ZUNhc3RUb1NjYWxlT2YAAAADBQAAAA9pblByaWNlQXNzZXRBbXQFAAAABnNjYWxlOAUAAAAScHJpY2VBc3NldERlY2ltYWxzBAAAAAtjdXJlbnRQcmljZQMJAAAAAAAAAgUAAAANcG9vbExQQmFsYW5jZQAAAAAAAAAAAAAAAAAAAAAAAAkBAAAADmNhbGN1bGF0ZVByaWNlAAAAAgUAAAAeYWNjb3VudFByaWNlQXNzZXRCYWxhbmNlQ2FzdGVkBQAAAB9hY2NvdW50QW1vdW50QXNzZXRCYWxhbmNlQ2FzdGVkBAAAABppbkFtb3VudEFzc2V0QW10Q2FsY3VsYXRlZAkAAGsAAAADBQAAAB5hY2NvdW50UHJpY2VBc3NldEJhbGFuY2VDYXN0ZWQFAAAABnNjYWxlOAUAAAALY3VyZW50UHJpY2UEAAAAEGluQW1vdW50QXNzZXRBbXQJAQAAABRwcml2YXRlQ2FzdFRvU2NhbGVPZgAAAAMFAAAAGmluQW1vdW50QXNzZXRBbXRDYWxjdWxhdGVkBQAAABJhbW91dEFzc2V0RGVjaW1hbHMFAAAABnNjYWxlOAQAAAATZXN0aW1hdGVkUHV0UmVzdWx0cwkBAAAAG3ByaXZhdGVFc3RpbWF0ZVB1dE9wZXJhdGlvbgAAAAYFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAABBpbkFtb3VudEFzc2V0QW10BQAAAA1hbW91bnRBc3NldElkBQAAAA9pblByaWNlQXNzZXRBbXQFAAAADHByaWNlQXNzZXRJZAUAAAALdXNlckFkZHJlc3MEAAAAD291dExwQW1vdW50Q2FsYwgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzEEAAAAD2N1cmVudFByaWNlQ2FsYwgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzIEAAAAGnBvb2xBbW91bnRBc3NldEJhbGFuY2VDYWxjCAUAAAATZXN0aW1hdGVkUHV0UmVzdWx0cwAAAAJfNgQAAAAZcG9vbFByaWNlQXNzZXRCYWxhbmNlQ0FsYwgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAACXzcEAAAAEXBvb2xMUEJhbGFuY2VDYWxjCAUAAAATZXN0aW1hdGVkUHV0UmVzdWx0cwAAAAJfOAQAAAAOcG9vbFN0YXR1c0NhbGMJAQAAAA1wYXJzZUludFZhbHVlAAAAAQgFAAAAE2VzdGltYXRlZFB1dFJlc3VsdHMAAAADXzEzCQAFFAAAAAIFAAAAA25pbAkABLkAAAACCQAETAAAAAICAAAADCVkJWQlZCVkJWQlZAkABEwAAAACCQABpAAAAAEFAAAAD291dExwQW1vdW50Q2FsYwkABEwAAAACCQABpAAAAAEFAAAAD2N1cmVudFByaWNlQ2FsYwkABEwAAAACCQABpAAAAAEFAAAAGnBvb2xBbW91bnRBc3NldEJhbGFuY2VDYWxjCQAETAAAAAIJAAGkAAAAAQUAAAAZcG9vbFByaWNlQXNzZXRCYWxhbmNlQ0FsYwkABEwAAAACCQABpAAAAAEFAAAAEXBvb2xMUEJhbGFuY2VDYWxjCQAETAAAAAIJAAGkAAAAAQUAAAAOcG9vbFN0YXR1c0NhbGMFAAAAA25pbAUAAAADU0VQAAAAAWkBAAAAE2V2YWx1YXRlR2V0UkVBRE9OTFkAAAADAAAAEHBheW1lbnRMcEFzc2V0SWQAAAAPcGF5bWVudExwQW1vdW50AAAAC3VzZXJBZGRyZXNzBAAAAAdyZXN1bHRzCQEAAAAbcHJpdmF0ZUVzdGltYXRlR2V0T3BlcmF0aW9uAAAAAwUAAAAQcGF5bWVudExwQXNzZXRJZAUAAAAPcGF5bWVudExwQW1vdW50BQAAAAt1c2VyQWRkcmVzcwQAAAARb3V0QW1vdW50QXNzZXRBbXQIBQAAAAdyZXN1bHRzAAAAAl8xBAAAABBvdXRQcmljZUFzc2V0QW10CAUAAAAHcmVzdWx0cwAAAAJfMgQAAAAWcG9vbEFtb3VudEFzc2V0QmFsYW5jZQgFAAAAB3Jlc3VsdHMAAAADXzEwBAAAABVwb29sUHJpY2VBc3NldEJhbGFuY2UIBQAAAAdyZXN1bHRzAAAAA18xMQQAAAANcG9vbExQQmFsYW5jZQgFAAAAB3Jlc3VsdHMAAAADXzEyBAAAAAxjdXJyZW50UHJpY2UIBQAAAAdyZXN1bHRzAAAAA18xMwQAAAAKcG9vbFN0YXR1cwkBAAAADXBhcnNlSW50VmFsdWUAAAABCAUAAAAHcmVzdWx0cwAAAANfMTQJAAUUAAAAAgUAAAADbmlsCQAEuQAAAAIJAARMAAAAAgIAAAAOJWQlZCVkJWQlZCVkJWQJAARMAAAAAgkAAaQAAAABBQAAABFvdXRBbW91bnRBc3NldEFtdAkABEwAAAACCQABpAAAAAEFAAAAEG91dFByaWNlQXNzZXRBbXQJAARMAAAAAgkAAaQAAAABBQAAABZwb29sQW1vdW50QXNzZXRCYWxhbmNlCQAETAAAAAIJAAGkAAAAAQUAAAAVcG9vbFByaWNlQXNzZXRCYWxhbmNlCQAETAAAAAIJAAGkAAAAAQUAAAANcG9vbExQQmFsYW5jZQkABEwAAAACCQABpAAAAAEFAAAADGN1cnJlbnRQcmljZQkABEwAAAACCQABpAAAAAEFAAAACnBvb2xTdGF0dXMFAAAAA25pbAUAAAADU0VQAAAAAWkBAAAADGhhc2hSRUFET05MWQAAAAAJAAUUAAAAAgUAAAADbmlsCQACWgAAAAEJAQAAAAV2YWx1ZQAAAAEJAAPxAAAAAQUAAAAEdGhpcwAAAAEAAAACdHgBAAAABnZlcmlmeQAAAAAEAAAAByRtYXRjaDAFAAAAAnR4AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAVPcmRlcgQAAAAFb3JkZXIFAAAAByRtYXRjaDAJAAGRAAAAAgkBAAAAG3ZhbGlkYXRlTWF0Y2hlck9yZGVyQWxsb3dlZAAAAAEFAAAABW9yZGVyAAAAAAAAAAABCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAgFAAAAAnR4AAAAD3NlbmRlclB1YmxpY0tleZakPPQ=", "height": 1695590, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 9kF2r8pqgY7eEHj4FG9yKd4jE7rNuigYL1tJgbNmGgg6 Next: 9qzdXmV43u6umJfwtxUCFcvoPCyJbXmWCpNHEAiUkR8j Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let factoryAddressString = "3MxueHaGvWmdk5crtn9HwtkSAAZScTWoHaC"
4+let factoryContract = Address(base58'3N798qptwQzjjC6TGUGJz4bsm22JvjqmjCF')
55
66 let lPdecimals = 8
77
8-let decimalsMultPrice = ((100 * 1000) * 1000)
8+let scale8 = 100000000
9+
10+let scale18 = toBigInt(1000000000000000000)
911
1012 let SEP = "__"
1113
1618 let PoolMatcherDisabled = 3
1719
1820 let PoolShutdown = 4
19-
20-let buyOrderType = 0
21-
22-let sellOrderType = 1
2321
2422 let idxPoolAddress = 1
2523
4947
5048 let idxPoolLPAssetAmt = 3
5149
50+let idxFactoryStakingContract = 1
51+
52+let idxFactoryBoostingConfig = 2
53+
5254 func keyPriceLast () = "%s%s__price__last"
5355
5456
7375 func keyPriceAsset () = "%s__priceAsset"
7476
7577
78+func keyFactoryConfig () = "%s__factoryConfig"
79+
80+
7681 func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
7782
7883
8893 func keyPoolWeight (contractAddress) = ("%s%d__poolWeight__" + contractAddress)
8994
9095
91-func isGlobalShutdown () = valueOrElse(getBoolean(value(addressFromString(factoryAddressString)), keyAllPoolsShutdown()), false)
96+func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
9297
9398
9499 func getPoolConfig () = {
95- let poolAmountAsset = valueOrErrorMessage(getString(keyAmountAsset()), "No config for amount asset found")
96- let poolPriceAsset = valueOrErrorMessage(getString(keyPriceAsset()), "No config for price asset found")
97- let poolPriceAssetInternal = valueOrErrorMessage(getInteger(value(addressFromString(factoryAddressString)), keyMappingsBaseAsset2internalId(poolPriceAsset)), "No config for internal price asset found")
98- let poolAmountAssetInternal = valueOrErrorMessage(getInteger(value(addressFromString(factoryAddressString)), keyMappingsBaseAsset2internalId(poolAmountAsset)), "No config for internal amount asset found")
99- split(valueOrErrorMessage(getString(addressFromStringValue(factoryAddressString), keyPoolConfig(toString(poolAmountAssetInternal), toString(poolPriceAssetInternal))), "No factory config found for pool assets."), SEP)
100+ let poolAmountAsset = valueOrErrorMessage(getString(this, keyAmountAsset()), "No config for amount asset found")
101+ let poolPriceAsset = valueOrErrorMessage(getString(this, keyPriceAsset()), "No config for price asset found")
102+ let poolPriceAssetInternal = valueOrErrorMessage(getInteger(factoryContract, keyMappingsBaseAsset2internalId(poolPriceAsset)), "No config for internal price asset found")
103+ let poolAmountAssetInternal = valueOrErrorMessage(getInteger(factoryContract, keyMappingsBaseAsset2internalId(poolAmountAsset)), "No config for internal amount asset found")
104+ split(valueOrErrorMessage(getString(factoryContract, keyPoolConfig(toString(poolAmountAssetInternal), toString(poolPriceAssetInternal))), "No factory config found for pool assets."), SEP)
100105 }
101106
102107
108+func getFactoryConfig () = split(valueOrErrorMessage(getString(factoryContract, keyFactoryConfig()), "No factory config found."), SEP)
109+
110+
103111 func getPoolLiquidity (amountAssetInternalId,priceAssetInternalId) = {
104- let currentPoolLiquidityValue = getString(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId))
105- if (!(isDefined(currentPoolLiquidityValue)))
106- then ["", "0", "0", "0"]
107- else split(value(currentPoolLiquidityValue), SEP)
112+ let currentPoolLiquidityValue = getString(this, keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId))
113+ if (isDefined(currentPoolLiquidityValue))
114+ then split(value(currentPoolLiquidityValue), SEP)
115+ else ["", "0", "0", "0"]
108116 }
109117
110118
111119 func getPoolLiquidityByUser (amountAssetInternalId,priceAssetInternalId,userAddress) = {
112- let currentPoolLiquidityValue = getString(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, userAddress))
113- if (!(isDefined(currentPoolLiquidityValue)))
114- then ["", "0", "0", "0", "0"]
115- else split(value(currentPoolLiquidityValue), SEP)
120+ let currentPoolLiquidityValue = getString(this, keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, userAddress))
121+ if (isDefined(currentPoolLiquidityValue))
122+ then split(value(currentPoolLiquidityValue), SEP)
123+ else ["", "0", "0", "0", "0"]
116124 }
117125
118126
128136 func dataGetActionInfo (outAmountAssetAmt,outPriceAssetAmt,inLpAmt,price,txHeight,txTimestamp) = makeString(["%d%d%d%d%d%d", toString(outAmountAssetAmt), toString(outPriceAssetAmt), toString(inLpAmt), toString(price), toString(txHeight), toString(txTimestamp)], SEP)
129137
130138
131-func privateCastAssetToMaxDecimals (assetDecimals,assetAmount) = fraction(assetAmount, decimalsMultPrice, assetDecimals)
139+func privateCastToScaleOf (amount,resultScale,currentScale) = fraction(amount, resultScale, currentScale)
132140
133141
134-func privateCastAssetToOriginDecimals (assetDecimals,assetAmount) = fraction(assetAmount, assetDecimals, decimalsMultPrice)
142+func calculatePriceBigInt (priceAssetLockedAmt,amountAssetlLockedAmt) = {
143+ let priceBigInt = fraction(toBigInt(priceAssetLockedAmt), scale18, toBigInt(amountAssetlLockedAmt))
144+ toInt(fraction(priceBigInt, toBigInt(scale8), scale18))
145+ }
135146
136147
137-func calculatePrice (priceAssetLockedAmt,amountAssetlLockedAmt) = fraction(priceAssetLockedAmt, decimalsMultPrice, amountAssetlLockedAmt)
148+func calculatePrice (priceAssetLockedAmt,amountAssetlLockedAmt) = fraction(priceAssetLockedAmt, scale8, amountAssetlLockedAmt)
138149
139150
140151 func privateCalculatePrice (amoutAssetDecimals,priceAssetDecimals,amountAssetAmt,priceAssetAmt) = {
141- let amountAssetAmtCasted = privateCastAssetToMaxDecimals(amoutAssetDecimals, amountAssetAmt)
142- let priceAssetAmtCasted = privateCastAssetToMaxDecimals(priceAssetDecimals, priceAssetAmt)
152+ let amountAssetAmtCasted = privateCastToScaleOf(amountAssetAmt, scale8, amoutAssetDecimals)
153+ let priceAssetAmtCasted = privateCastToScaleOf(priceAssetAmt, scale8, priceAssetDecimals)
143154 calculatePrice(priceAssetAmtCasted, amountAssetAmtCasted)
144155 }
145156
147158 func privateGetAccountBalance (assetId) = if ((assetId == "WAVES"))
148159 then wavesBalance(this).available
149160 else assetBalance(this, fromBase58String(assetId))
161+
162+
163+func getPrices (amountAssetAmt,priceAssetAmt,lpAmount) = {
164+ let poolConfigDataList = getPoolConfig()
165+ let amoutAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
166+ let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
167+ let poolPrice = privateCalculatePrice(amoutAssetDecimals, priceAssetDecimals, amountAssetAmt, priceAssetAmt)
168+ let amountAssetPoolLockedAmt = privateCastToScaleOf(amountAssetAmt, scale8, amoutAssetDecimals)
169+ let priceAssetPoolLockedAmt = privateCastToScaleOf(priceAssetAmt, scale8, priceAssetDecimals)
170+ let lpPriceInAmountAsset = calculatePrice(amountAssetPoolLockedAmt, lpAmount)
171+ let lpPriceInPriceAsset = calculatePrice(priceAssetPoolLockedAmt, lpAmount)
172+[poolPrice, lpPriceInAmountAsset, lpPriceInPriceAsset]
173+ }
150174
151175
152176 func privateEstimateGetOperation (paymentLpAssetId,paymentLpAmount,userAddress) = {
172196 else {
173197 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
174198 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
175- let amountAssetPoolLockedAmt = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
176- let priceAssetPoolLockedAmt = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
199+ let amountAssetPoolLockedAmt = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
200+ let priceAssetPoolLockedAmt = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
177201 let outAmountAssetAmt = fraction(amountAssetPoolLockedAmt, paymentLpAmount, poolLPBalance)
178202 let outPriceAssetAmt = fraction(priceAssetPoolLockedAmt, paymentLpAmount, poolLPBalance)
179- let outAmountAssetAmtFinal = privateCastAssetToOriginDecimals(amoutAssetDecimals, outAmountAssetAmt)
180- let outPriceAssetAmtFinal = privateCastAssetToOriginDecimals(priceAssetDecimals, outPriceAssetAmt)
203+ let outAmountAssetAmtFinal = privateCastToScaleOf(outAmountAssetAmt, amoutAssetDecimals, scale8)
204+ let outPriceAssetAmtFinal = privateCastToScaleOf(outPriceAssetAmt, priceAssetDecimals, scale8)
181205 let currentPrice = calculatePrice(priceAssetPoolLockedAmt, amountAssetPoolLockedAmt)
182206 $Tuple14(outAmountAssetAmtFinal, outPriceAssetAmtFinal, amountAssetInternalId, priceAssetInternalId, userAmountAssetBalance, amountAssetId, userPriceAssetBalance, priceAssetId, userLPBalance, poolAmountAssetBalance, poolPriceAssetBalance, poolLPBalance, currentPrice, poolStatus)
183207 }
209233 else {
210234 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
211235 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
212- let inAmountAssetAmtCalculated = privateCastAssetToMaxDecimals(amoutAssetDecimals, inAmountAssetAmt)
213- let inPriceAssetAmtCalculated = privateCastAssetToMaxDecimals(priceAssetDecimals, inPriceAssetAmt)
236+ let inAmountAssetAmtCalculated = privateCastToScaleOf(inAmountAssetAmt, scale8, amoutAssetDecimals)
237+ let inPriceAssetAmtCalculated = privateCastToScaleOf(inPriceAssetAmt, scale8, priceAssetDecimals)
214238 let userPrice = calculatePrice(inPriceAssetAmtCalculated, inAmountAssetAmtCalculated)
215- let amountAssetPoolLockedAmt = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
216- let priceAssetPoolLockedAmt = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
239+ let amountAssetPoolLockedAmt = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
240+ let priceAssetPoolLockedAmt = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
217241 let curentPrice = if ((poolLPBalance == 0))
218242 then 0
219243 else calculatePrice(priceAssetPoolLockedAmt, amountAssetPoolLockedAmt)
223247 then fraction((curentPrice - userPrice), 100, curentPrice)
224248 else fraction((userPrice - curentPrice), 100, curentPrice)
225249 if (if ((curentPrice != 0))
226- then ((slippage * decimalsMultPrice) > slippageTolerance)
250+ then ((slippage * scale8) > slippageTolerance)
227251 else false)
228- then throw(((("Price slippage " + toString((slippage * decimalsMultPrice))) + " exceeded the passed limit of ") + toString(slippageTolerance)))
252+ then throw(((("Price slippage " + toString((slippage * scale8))) + " exceeded the passed limit of ") + toString(slippageTolerance)))
229253 else {
230254 let finalPrice = calculatePrice((priceAssetPoolLockedAmt + inPriceAssetAmtCalculated), (amountAssetPoolLockedAmt + inAmountAssetAmtCalculated))
231255 let outLpAmount = if ((poolLPBalance == 0))
282306 then false
283307 else true
284308 let orderPrice = order.price
285- let priceDecimals = fraction(decimalsMultPrice, priceAssetDecimals, amountAssetDecimals)
286- let castedOrderPrice = privateCastAssetToMaxDecimals(priceDecimals, orderPrice)
309+ let priceDecimals = fraction(scale8, priceAssetDecimals, amountAssetDecimals)
310+ let castedOrderPrice = privateCastToScaleOf(orderPrice, scale8, priceDecimals)
287311 let isOrderPriceValid = if ((order.orderType == Buy))
288312 then (currentPrice >= castedOrderPrice)
289313 else (castedOrderPrice >= currentPrice)
298322
299323
300324 @Callable(i)
301-func put (slippageTolerance) = {
325+func put (slippageTolerance,shouldAutoStake) = {
326+ let factoryConfigList = getFactoryConfig()
327+ let stakingContract = valueOrErrorMessage(addressFromString(factoryConfigList[idxFactoryStakingContract]), "Error. Incorrect staking address.")
302328 let pmtAmountAsset = value(i.payments[0])
303329 let inAmountAssetAmt = pmtAmountAsset.amount
304330 let inAmountAssetId = if (!(isDefined(pmtAmountAsset.assetId)))
330356 else (poolStatus == PoolShutdown))
331357 then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
332358 else {
333- let emitLPAssetOnFactory = invoke(addressFromStringValue(factoryAddressString), "emit", [outLpAmount], nil)
359+ let emitLPAssetOnFactory = invoke(factoryContract, "emit", [outLpAmount], nil)
334360 if ((emitLPAssetOnFactory == emitLPAssetOnFactory))
335361 then if ((emitLPAssetOnFactory != "success"))
336362 then throw("LP asset reissue failed during emit call on factory.")
337- else [StringEntry(keyPriceLast(), ("%s__" + toString(curentPrice))), StringEntry(keyPriceHistory(height, lastBlock.timestamp), ("%s__" + toString(curentPrice))), StringEntry(keyPutActionByUser(toString(i.caller), toBase58String(i.transactionId)), dataPutActionInfo(inAmountAssetAmt, inPriceAssetAmt, outLpAmount, curentPrice, slippageTolerance, slippageCalculated, height, lastBlock.timestamp)), StringEntry(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, toString(i.caller)), dataPoolLiquidity((userAmountAssetBalance + inAmountAssetAmt), (userPriceAssetBalance + inPriceAssetAmt), (userLPBalance + outLpAmount))), StringEntry(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId), dataPoolLiquidity((poolAmountAssetBalance + inAmountAssetAmt), (poolPriceAssetBalance + inPriceAssetAmt), (poolLPBalance + outLpAmount))), ScriptTransfer(i.caller, outLpAmount, lpAssetId)]
363+ else {
364+ let results = [StringEntry(keyPriceLast(), ("%s__" + toString(curentPrice))), StringEntry(keyPriceHistory(height, lastBlock.timestamp), ("%s__" + toString(curentPrice))), StringEntry(keyPutActionByUser(toString(i.caller), toBase58String(i.transactionId)), dataPutActionInfo(inAmountAssetAmt, inPriceAssetAmt, outLpAmount, curentPrice, slippageTolerance, slippageCalculated, height, lastBlock.timestamp)), StringEntry(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, toString(i.caller)), dataPoolLiquidity((userAmountAssetBalance + inAmountAssetAmt), (userPriceAssetBalance + inPriceAssetAmt), (userLPBalance + outLpAmount))), StringEntry(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId), dataPoolLiquidity((poolAmountAssetBalance + inAmountAssetAmt), (poolPriceAssetBalance + inPriceAssetAmt), (poolLPBalance + outLpAmount)))]
365+ if (shouldAutoStake)
366+ then {
367+ let stake = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, outLpAmount)])
368+ if ((stake == stake))
369+ then results
370+ else throw("Strict value is not equal to itself.")
371+ }
372+ else (results :+ ScriptTransfer(i.caller, outLpAmount, lpAssetId))
373+ }
338374 else throw("Strict value is not equal to itself.")
339375 }
340376 }
366402 else (poolStatus == PoolShutdown))
367403 then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
368404 else {
369- let burnLPAssetOnFactory = invoke(addressFromStringValue(factoryAddressString), "burn", [pmtAssetAmount], [AttachedPayment(pmtAssetId, pmtAssetAmount)])
405+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAssetAmount], [AttachedPayment(pmtAssetId, pmtAssetAmount)])
370406 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
371407 then if ((burnLPAssetOnFactory != "success"))
372408 then throw("LP asset burn failed during emit call on factory.")
380416
381417
382418 @Callable(i)
383-func activate (amountAssetStr,priceAssetStr) = if ((toString(i.caller) != factoryAddressString))
419+func activate (amountAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
384420 then throw("permissions denied")
385421 else $Tuple2([StringEntry(keyAmountAsset(), amountAssetStr), StringEntry(keyPriceAsset(), priceAssetStr)], "success")
386422
400436 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
401437 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
402438 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
403- let amountAssetPoolLockedAmt = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
404- let priceAssetPoolLockedAmt = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
405- let lpPriceInAmountAsset = fraction(amountAssetPoolLockedAmt, decimalsMultPrice, poolLPBalance)
406- let lpPriceInPriceAsset = fraction(priceAssetPoolLockedAmt, decimalsMultPrice, poolLPBalance)
407- let currentPrice = privateCalculatePrice(amoutAssetDecimals, priceAssetDecimals, accountAmountAssetBalance, accountPriceAssetBalance)
408- let poolWeight = valueOrErrorMessage(getInteger(value(addressFromString(factoryAddressString)), keyPoolWeight(toString(this))), "Pool doesn't have weight.")
439+ let pricesList = getPrices(accountAmountAssetBalance, accountPriceAssetBalance, poolLPBalance)
440+ let currentPrice = pricesList[0]
441+ let lpPriceInAmountAsset = pricesList[1]
442+ let lpPriceInPriceAsset = pricesList[2]
443+ let poolWeight = valueOrErrorMessage(getInteger(factoryContract, keyPoolWeight(toString(this))), "Pool doesn't have weight.")
409444 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accountAmountAssetBalance), toString(accountPriceAssetBalance), toString(poolLPBalance), toString(currentPrice), toString(lpPriceInAmountAsset), toString(lpPriceInPriceAsset), toString(poolWeight)], SEP))
410445 }
411446
426461 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
427462 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
428463 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
429- let accountAmountAssetBalanceCasted = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
430- let accountPriceAssetBalanceCasted = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
464+ let accountAmountAssetBalanceCasted = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
465+ let accountPriceAssetBalanceCasted = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
431466 let curentPrice = if ((poolLPBalance == 0))
432467 then 0
433468 else calculatePrice(accountPriceAssetBalanceCasted, accountAmountAssetBalanceCasted)
434- let inPriceAssetAmtCalculated = fraction(inAmountAssetAmt, curentPrice, decimalsMultPrice)
435- let inPriceAssetAmt = privateCastAssetToOriginDecimals(priceAssetDecimals, inPriceAssetAmtCalculated)
436- let results = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
437- $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(results._1), toString(results._2), toString(results._6), toString(results._7), toString(results._8), results._13], SEP))
469+ let inPriceAssetAmtCalculated = fraction(inAmountAssetAmt, curentPrice, scale8)
470+ let inPriceAssetAmt = privateCastToScaleOf(inPriceAssetAmtCalculated, priceAssetDecimals, scale8)
471+ let estimatedPutResults = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
472+ let outLpAmountCalc = estimatedPutResults._1
473+ let curentPriceCalc = estimatedPutResults._2
474+ let poolAmountAssetBalanceCalc = estimatedPutResults._6
475+ let poolPriceAssetBalanceCAlc = estimatedPutResults._7
476+ let poolLPBalanceCalc = estimatedPutResults._8
477+ let poolStatusCalc = parseIntValue(estimatedPutResults._13)
478+ $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(outLpAmountCalc), toString(curentPriceCalc), toString(poolAmountAssetBalanceCalc), toString(poolPriceAssetBalanceCAlc), toString(poolLPBalanceCalc), toString(poolStatusCalc)], SEP))
438479 }
439480
440481
454495 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
455496 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
456497 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
457- let accountAmountAssetBalanceCasted = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
458- let accountPriceAssetBalanceCasted = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
459- let inPriceAssetAmtCalculatedTuple = privateCastAssetToMaxDecimals(priceAssetDecimals, inPriceAssetAmt)
498+ let accountAmountAssetBalanceCasted = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
499+ let accountPriceAssetBalanceCasted = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
500+ let inPriceAssetAmtCalculatedTuple = privateCastToScaleOf(inPriceAssetAmt, scale8, priceAssetDecimals)
460501 let curentPrice = if ((poolLPBalance == 0))
461502 then 0
462503 else calculatePrice(accountPriceAssetBalanceCasted, accountAmountAssetBalanceCasted)
463- let inAmountAssetAmtCalculated = fraction(accountPriceAssetBalanceCasted, decimalsMultPrice, curentPrice)
464- let inAmountAssetAmt = privateCastAssetToOriginDecimals(amoutAssetDecimals, inAmountAssetAmtCalculated)
465- let results = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
466- $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(results._1), toString(results._2), toString(results._6), toString(results._7), toString(results._8), results._13], SEP))
504+ let inAmountAssetAmtCalculated = fraction(accountPriceAssetBalanceCasted, scale8, curentPrice)
505+ let inAmountAssetAmt = privateCastToScaleOf(inAmountAssetAmtCalculated, amoutAssetDecimals, scale8)
506+ let estimatedPutResults = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
507+ let outLpAmountCalc = estimatedPutResults._1
508+ let curentPriceCalc = estimatedPutResults._2
509+ let poolAmountAssetBalanceCalc = estimatedPutResults._6
510+ let poolPriceAssetBalanceCAlc = estimatedPutResults._7
511+ let poolLPBalanceCalc = estimatedPutResults._8
512+ let poolStatusCalc = parseIntValue(estimatedPutResults._13)
513+ $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(outLpAmountCalc), toString(curentPriceCalc), toString(poolAmountAssetBalanceCalc), toString(poolPriceAssetBalanceCAlc), toString(poolLPBalanceCalc), toString(poolStatusCalc)], SEP))
467514 }
468515
469516
471518 @Callable(i)
472519 func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmount,userAddress) = {
473520 let results = privateEstimateGetOperation(paymentLpAssetId, paymentLpAmount, userAddress)
474- $Tuple2(nil, makeString(["%d%d%d%d%d%s%d%s%d%d%s%d%d", toString(results._1), toString(results._2), toString(results._10), toString(results._11), toString(results._12), toString(results._13), results._14], SEP))
521+ let outAmountAssetAmt = results._1
522+ let outPriceAssetAmt = results._2
523+ let poolAmountAssetBalance = results._10
524+ let poolPriceAssetBalance = results._11
525+ let poolLPBalance = results._12
526+ let currentPrice = results._13
527+ let poolStatus = parseIntValue(results._14)
528+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmountAssetAmt), toString(outPriceAssetAmt), toString(poolAmountAssetBalance), toString(poolPriceAssetBalance), toString(poolLPBalance), toString(currentPrice), toString(poolStatus)], SEP))
475529 }
476530
477531
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let factoryAddressString = "3MxueHaGvWmdk5crtn9HwtkSAAZScTWoHaC"
4+let factoryContract = Address(base58'3N798qptwQzjjC6TGUGJz4bsm22JvjqmjCF')
55
66 let lPdecimals = 8
77
8-let decimalsMultPrice = ((100 * 1000) * 1000)
8+let scale8 = 100000000
9+
10+let scale18 = toBigInt(1000000000000000000)
911
1012 let SEP = "__"
1113
1214 let PoolActive = 1
1315
1416 let PoolPutDisabled = 2
1517
1618 let PoolMatcherDisabled = 3
1719
1820 let PoolShutdown = 4
19-
20-let buyOrderType = 0
21-
22-let sellOrderType = 1
2321
2422 let idxPoolAddress = 1
2523
2624 let idxPoolStatus = 2
2725
2826 let idxPoolLPAssetId = 3
2927
3028 let idxAmountAssetId = 4
3129
3230 let idxPriceAssetId = 5
3331
3432 let idxAmountAssetDecimals = 6
3533
3634 let idxPriceAssetDecimals = 7
3735
3836 let idxAmountAssetInternalId = 8
3937
4038 let idxPriceAssetInternalId = 9
4139
4240 let idxLPAssetDecimals = 10
4341
4442 let idxMatcherPublicKey = 11
4543
4644 let idxPoolAmountAssetAmt = 1
4745
4846 let idxPoolPriceAssetAmt = 2
4947
5048 let idxPoolLPAssetAmt = 3
5149
50+let idxFactoryStakingContract = 1
51+
52+let idxFactoryBoostingConfig = 2
53+
5254 func keyPriceLast () = "%s%s__price__last"
5355
5456
5557 func keyPriceHistory (h,timestamp) = makeString(["%s%s%d%d__price__history", toString(h), toString(timestamp)], SEP)
5658
5759
5860 func keyPoolLiquidity (internalAmountAsset,internalPriceAsset) = (((("%d%d%s__" + internalAmountAsset) + "__") + internalPriceAsset) + "__locked")
5961
6062
6163 func keyPoolLiquidityByUser (internalAmountAsset,internalPriceAsset,userAddress) = (((((("%d%d%s%s__" + internalAmountAsset) + "__") + internalPriceAsset) + "__") + userAddress) + "__locked")
6264
6365
6466 func keyPutActionByUser (userAddress,txId) = ((("%s%s%s__P__" + userAddress) + "__") + txId)
6567
6668
6769 func keyGetActionByUser (userAddress,txId) = ((("%s%s%s__G__" + userAddress) + "__") + txId)
6870
6971
7072 func keyAmountAsset () = "%s__amountAsset"
7173
7274
7375 func keyPriceAsset () = "%s__priceAsset"
7476
7577
78+func keyFactoryConfig () = "%s__factoryConfig"
79+
80+
7681 func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
7782
7883
7984 func keyPoolConfig (amountAssetInternal,priceAssetInternal) = (((("%d%d%s__" + amountAssetInternal) + "__") + priceAssetInternal) + "__config")
8085
8186
8287 func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
8388
8489
8590 func keyAllPoolsShutdown () = "%s__shutdown"
8691
8792
8893 func keyPoolWeight (contractAddress) = ("%s%d__poolWeight__" + contractAddress)
8994
9095
91-func isGlobalShutdown () = valueOrElse(getBoolean(value(addressFromString(factoryAddressString)), keyAllPoolsShutdown()), false)
96+func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
9297
9398
9499 func getPoolConfig () = {
95- let poolAmountAsset = valueOrErrorMessage(getString(keyAmountAsset()), "No config for amount asset found")
96- let poolPriceAsset = valueOrErrorMessage(getString(keyPriceAsset()), "No config for price asset found")
97- let poolPriceAssetInternal = valueOrErrorMessage(getInteger(value(addressFromString(factoryAddressString)), keyMappingsBaseAsset2internalId(poolPriceAsset)), "No config for internal price asset found")
98- let poolAmountAssetInternal = valueOrErrorMessage(getInteger(value(addressFromString(factoryAddressString)), keyMappingsBaseAsset2internalId(poolAmountAsset)), "No config for internal amount asset found")
99- split(valueOrErrorMessage(getString(addressFromStringValue(factoryAddressString), keyPoolConfig(toString(poolAmountAssetInternal), toString(poolPriceAssetInternal))), "No factory config found for pool assets."), SEP)
100+ let poolAmountAsset = valueOrErrorMessage(getString(this, keyAmountAsset()), "No config for amount asset found")
101+ let poolPriceAsset = valueOrErrorMessage(getString(this, keyPriceAsset()), "No config for price asset found")
102+ let poolPriceAssetInternal = valueOrErrorMessage(getInteger(factoryContract, keyMappingsBaseAsset2internalId(poolPriceAsset)), "No config for internal price asset found")
103+ let poolAmountAssetInternal = valueOrErrorMessage(getInteger(factoryContract, keyMappingsBaseAsset2internalId(poolAmountAsset)), "No config for internal amount asset found")
104+ split(valueOrErrorMessage(getString(factoryContract, keyPoolConfig(toString(poolAmountAssetInternal), toString(poolPriceAssetInternal))), "No factory config found for pool assets."), SEP)
100105 }
101106
102107
108+func getFactoryConfig () = split(valueOrErrorMessage(getString(factoryContract, keyFactoryConfig()), "No factory config found."), SEP)
109+
110+
103111 func getPoolLiquidity (amountAssetInternalId,priceAssetInternalId) = {
104- let currentPoolLiquidityValue = getString(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId))
105- if (!(isDefined(currentPoolLiquidityValue)))
106- then ["", "0", "0", "0"]
107- else split(value(currentPoolLiquidityValue), SEP)
112+ let currentPoolLiquidityValue = getString(this, keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId))
113+ if (isDefined(currentPoolLiquidityValue))
114+ then split(value(currentPoolLiquidityValue), SEP)
115+ else ["", "0", "0", "0"]
108116 }
109117
110118
111119 func getPoolLiquidityByUser (amountAssetInternalId,priceAssetInternalId,userAddress) = {
112- let currentPoolLiquidityValue = getString(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, userAddress))
113- if (!(isDefined(currentPoolLiquidityValue)))
114- then ["", "0", "0", "0", "0"]
115- else split(value(currentPoolLiquidityValue), SEP)
120+ let currentPoolLiquidityValue = getString(this, keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, userAddress))
121+ if (isDefined(currentPoolLiquidityValue))
122+ then split(value(currentPoolLiquidityValue), SEP)
123+ else ["", "0", "0", "0", "0"]
116124 }
117125
118126
119127 func dataPoolLiquidity (amountAssetLocked,priceAssetLocked,lpTokenLocked) = makeString(["%d%d%d", toString(amountAssetLocked), toString(priceAssetLocked), toString(lpTokenLocked)], SEP)
120128
121129
122130 func dataPoolLiquidityByUser (amountAssetLocked,priceAssetLocked,lpTokenLocked,userAddress) = makeString(["%d%d%d", toString(amountAssetLocked), toString(priceAssetLocked), toString(lpTokenLocked)], SEP)
123131
124132
125133 func dataPutActionInfo (inAmountAssetAmt,inPriceAssetAmt,outLpAmt,price,slippageTolerancePassedByUser,slippageToleranceReal,txHeight,txTimestamp) = makeString(["%d%d%d%d%d%d%d", toString(inAmountAssetAmt), toString(inPriceAssetAmt), toString(outLpAmt), toString(price), toString(slippageTolerancePassedByUser), toString(slippageToleranceReal), toString(txHeight), toString(txTimestamp)], SEP)
126134
127135
128136 func dataGetActionInfo (outAmountAssetAmt,outPriceAssetAmt,inLpAmt,price,txHeight,txTimestamp) = makeString(["%d%d%d%d%d%d", toString(outAmountAssetAmt), toString(outPriceAssetAmt), toString(inLpAmt), toString(price), toString(txHeight), toString(txTimestamp)], SEP)
129137
130138
131-func privateCastAssetToMaxDecimals (assetDecimals,assetAmount) = fraction(assetAmount, decimalsMultPrice, assetDecimals)
139+func privateCastToScaleOf (amount,resultScale,currentScale) = fraction(amount, resultScale, currentScale)
132140
133141
134-func privateCastAssetToOriginDecimals (assetDecimals,assetAmount) = fraction(assetAmount, assetDecimals, decimalsMultPrice)
142+func calculatePriceBigInt (priceAssetLockedAmt,amountAssetlLockedAmt) = {
143+ let priceBigInt = fraction(toBigInt(priceAssetLockedAmt), scale18, toBigInt(amountAssetlLockedAmt))
144+ toInt(fraction(priceBigInt, toBigInt(scale8), scale18))
145+ }
135146
136147
137-func calculatePrice (priceAssetLockedAmt,amountAssetlLockedAmt) = fraction(priceAssetLockedAmt, decimalsMultPrice, amountAssetlLockedAmt)
148+func calculatePrice (priceAssetLockedAmt,amountAssetlLockedAmt) = fraction(priceAssetLockedAmt, scale8, amountAssetlLockedAmt)
138149
139150
140151 func privateCalculatePrice (amoutAssetDecimals,priceAssetDecimals,amountAssetAmt,priceAssetAmt) = {
141- let amountAssetAmtCasted = privateCastAssetToMaxDecimals(amoutAssetDecimals, amountAssetAmt)
142- let priceAssetAmtCasted = privateCastAssetToMaxDecimals(priceAssetDecimals, priceAssetAmt)
152+ let amountAssetAmtCasted = privateCastToScaleOf(amountAssetAmt, scale8, amoutAssetDecimals)
153+ let priceAssetAmtCasted = privateCastToScaleOf(priceAssetAmt, scale8, priceAssetDecimals)
143154 calculatePrice(priceAssetAmtCasted, amountAssetAmtCasted)
144155 }
145156
146157
147158 func privateGetAccountBalance (assetId) = if ((assetId == "WAVES"))
148159 then wavesBalance(this).available
149160 else assetBalance(this, fromBase58String(assetId))
161+
162+
163+func getPrices (amountAssetAmt,priceAssetAmt,lpAmount) = {
164+ let poolConfigDataList = getPoolConfig()
165+ let amoutAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
166+ let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
167+ let poolPrice = privateCalculatePrice(amoutAssetDecimals, priceAssetDecimals, amountAssetAmt, priceAssetAmt)
168+ let amountAssetPoolLockedAmt = privateCastToScaleOf(amountAssetAmt, scale8, amoutAssetDecimals)
169+ let priceAssetPoolLockedAmt = privateCastToScaleOf(priceAssetAmt, scale8, priceAssetDecimals)
170+ let lpPriceInAmountAsset = calculatePrice(amountAssetPoolLockedAmt, lpAmount)
171+ let lpPriceInPriceAsset = calculatePrice(priceAssetPoolLockedAmt, lpAmount)
172+[poolPrice, lpPriceInAmountAsset, lpPriceInPriceAsset]
173+ }
150174
151175
152176 func privateEstimateGetOperation (paymentLpAssetId,paymentLpAmount,userAddress) = {
153177 let poolConfigList = getPoolConfig()
154178 let lpAssetId = poolConfigList[idxPoolLPAssetId]
155179 let amountAssetId = poolConfigList[idxAmountAssetId]
156180 let priceAssetId = poolConfigList[idxPriceAssetId]
157181 let amountAssetInternalId = poolConfigList[idxAmountAssetInternalId]
158182 let priceAssetInternalId = poolConfigList[idxPriceAssetInternalId]
159183 let amoutAssetDecimals = parseIntValue(poolConfigList[idxAmountAssetDecimals])
160184 let priceAssetDecimals = parseIntValue(poolConfigList[idxPriceAssetDecimals])
161185 let poolStatus = poolConfigList[idxPoolStatus]
162186 let userLiquidityList = getPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, userAddress)
163187 let userLPBalance = parseIntValue(userLiquidityList[idxPoolLPAssetAmt])
164188 let userAmountAssetBalance = parseIntValue(userLiquidityList[idxPoolAmountAssetAmt])
165189 let userPriceAssetBalance = parseIntValue(userLiquidityList[idxPoolPriceAssetAmt])
166190 let poolLiquidityList = getPoolLiquidity(amountAssetInternalId, priceAssetInternalId)
167191 let poolLPBalance = parseIntValue(poolLiquidityList[idxPoolLPAssetAmt])
168192 let poolAmountAssetBalance = parseIntValue(poolLiquidityList[idxPoolAmountAssetAmt])
169193 let poolPriceAssetBalance = parseIntValue(poolLiquidityList[idxPoolPriceAssetAmt])
170194 if ((lpAssetId != paymentLpAssetId))
171195 then throw("Invalid asset passed.")
172196 else {
173197 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
174198 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
175- let amountAssetPoolLockedAmt = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
176- let priceAssetPoolLockedAmt = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
199+ let amountAssetPoolLockedAmt = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
200+ let priceAssetPoolLockedAmt = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
177201 let outAmountAssetAmt = fraction(amountAssetPoolLockedAmt, paymentLpAmount, poolLPBalance)
178202 let outPriceAssetAmt = fraction(priceAssetPoolLockedAmt, paymentLpAmount, poolLPBalance)
179- let outAmountAssetAmtFinal = privateCastAssetToOriginDecimals(amoutAssetDecimals, outAmountAssetAmt)
180- let outPriceAssetAmtFinal = privateCastAssetToOriginDecimals(priceAssetDecimals, outPriceAssetAmt)
203+ let outAmountAssetAmtFinal = privateCastToScaleOf(outAmountAssetAmt, amoutAssetDecimals, scale8)
204+ let outPriceAssetAmtFinal = privateCastToScaleOf(outPriceAssetAmt, priceAssetDecimals, scale8)
181205 let currentPrice = calculatePrice(priceAssetPoolLockedAmt, amountAssetPoolLockedAmt)
182206 $Tuple14(outAmountAssetAmtFinal, outPriceAssetAmtFinal, amountAssetInternalId, priceAssetInternalId, userAmountAssetBalance, amountAssetId, userPriceAssetBalance, priceAssetId, userLPBalance, poolAmountAssetBalance, poolPriceAssetBalance, poolLPBalance, currentPrice, poolStatus)
183207 }
184208 }
185209
186210
187211 func privateEstimatePutOperation (slippageTolerance,inAmountAssetAmt,inAmountAssetId,inPriceAssetAmt,inPriceAssetId,userAddress) = {
188212 let poolConfigDataList = getPoolConfig()
189213 let lpAssetId = fromBase58String(poolConfigDataList[idxPoolLPAssetId])
190214 let amountAssetId = poolConfigDataList[idxAmountAssetId]
191215 let priceAssetId = poolConfigDataList[idxPriceAssetId]
192216 let amountAssetInternalId = poolConfigDataList[idxAmountAssetInternalId]
193217 let priceAssetInternalId = poolConfigDataList[idxPriceAssetInternalId]
194218 let amoutAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
195219 let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
196220 let poolStatus = poolConfigDataList[idxPoolStatus]
197221 let poolLiquidityDataList = getPoolLiquidity(amountAssetInternalId, priceAssetInternalId)
198222 let poolAmountAssetBalance = parseIntValue(poolLiquidityDataList[idxPoolAmountAssetAmt])
199223 let poolPriceAssetBalance = parseIntValue(poolLiquidityDataList[idxPoolPriceAssetAmt])
200224 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
201225 let userLiquidityDataList = getPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, userAddress)
202226 let userAmountAssetBalance = parseIntValue(userLiquidityDataList[idxPoolAmountAssetAmt])
203227 let userPriceAssetBalance = parseIntValue(userLiquidityDataList[idxPoolPriceAssetAmt])
204228 let userLPBalance = parseIntValue(userLiquidityDataList[idxPoolLPAssetAmt])
205229 if (if ((amountAssetId != inAmountAssetId))
206230 then true
207231 else (priceAssetId != inPriceAssetId))
208232 then throw("Invalid amount or price asset passed.")
209233 else {
210234 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
211235 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
212- let inAmountAssetAmtCalculated = privateCastAssetToMaxDecimals(amoutAssetDecimals, inAmountAssetAmt)
213- let inPriceAssetAmtCalculated = privateCastAssetToMaxDecimals(priceAssetDecimals, inPriceAssetAmt)
236+ let inAmountAssetAmtCalculated = privateCastToScaleOf(inAmountAssetAmt, scale8, amoutAssetDecimals)
237+ let inPriceAssetAmtCalculated = privateCastToScaleOf(inPriceAssetAmt, scale8, priceAssetDecimals)
214238 let userPrice = calculatePrice(inPriceAssetAmtCalculated, inAmountAssetAmtCalculated)
215- let amountAssetPoolLockedAmt = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
216- let priceAssetPoolLockedAmt = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
239+ let amountAssetPoolLockedAmt = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
240+ let priceAssetPoolLockedAmt = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
217241 let curentPrice = if ((poolLPBalance == 0))
218242 then 0
219243 else calculatePrice(priceAssetPoolLockedAmt, amountAssetPoolLockedAmt)
220244 let slippage = if ((curentPrice == 0))
221245 then 0
222246 else if ((curentPrice > userPrice))
223247 then fraction((curentPrice - userPrice), 100, curentPrice)
224248 else fraction((userPrice - curentPrice), 100, curentPrice)
225249 if (if ((curentPrice != 0))
226- then ((slippage * decimalsMultPrice) > slippageTolerance)
250+ then ((slippage * scale8) > slippageTolerance)
227251 else false)
228- then throw(((("Price slippage " + toString((slippage * decimalsMultPrice))) + " exceeded the passed limit of ") + toString(slippageTolerance)))
252+ then throw(((("Price slippage " + toString((slippage * scale8))) + " exceeded the passed limit of ") + toString(slippageTolerance)))
229253 else {
230254 let finalPrice = calculatePrice((priceAssetPoolLockedAmt + inPriceAssetAmtCalculated), (amountAssetPoolLockedAmt + inAmountAssetAmtCalculated))
231255 let outLpAmount = if ((poolLPBalance == 0))
232256 then {
233257 let partA = pow(inAmountAssetAmtCalculated, 0, 5, 1, 0, DOWN)
234258 let partB = pow(inPriceAssetAmtCalculated, 0, 5, 1, 0, DOWN)
235259 (partA * partB)
236260 }
237261 else {
238262 let lpAmtByAmountAsset = fraction(poolLPBalance, inAmountAssetAmtCalculated, amountAssetPoolLockedAmt)
239263 let lpAmtByPriceAsset = fraction(poolLPBalance, inPriceAssetAmtCalculated, priceAssetPoolLockedAmt)
240264 if ((lpAmtByPriceAsset > lpAmtByAmountAsset))
241265 then lpAmtByAmountAsset
242266 else lpAmtByPriceAsset
243267 }
244268 $Tuple13(outLpAmount, finalPrice, userAmountAssetBalance, userPriceAssetBalance, userLPBalance, poolAmountAssetBalance, poolPriceAssetBalance, poolLPBalance, amountAssetInternalId, priceAssetInternalId, lpAssetId, slippage, poolStatus)
245269 }
246270 }
247271 }
248272
249273
250274 func validateMatcherOrderAllowed (order) = {
251275 let poolConfigDataList = getPoolConfig()
252276 let amountAssetId = poolConfigDataList[idxAmountAssetId]
253277 let priceAssetId = poolConfigDataList[idxPriceAssetId]
254278 let poolStatus = parseIntValue(poolConfigDataList[idxPoolStatus])
255279 let matcherPublicKeyStr = poolConfigDataList[idxMatcherPublicKey]
256280 let amountAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
257281 let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
258282 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
259283 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
260284 let currentPrice = if ((order.orderType == Buy))
261285 then privateCalculatePrice(amountAssetDecimals, priceAssetDecimals, (accountAmountAssetBalance + order.amount), accountPriceAssetBalance)
262286 else privateCalculatePrice(amountAssetDecimals, priceAssetDecimals, (accountAmountAssetBalance + order.amount), accountPriceAssetBalance)
263287 let isPoolStatusValid = if (if (if (isGlobalShutdown())
264288 then true
265289 else (poolStatus == PoolMatcherDisabled))
266290 then true
267291 else (poolStatus == PoolShutdown))
268292 then false
269293 else true
270294 let isValidMatcherSign = sigVerify(order.bodyBytes, order.proofs[0], fromBase58String(matcherPublicKeyStr))
271295 let orderAmountAsset = order.assetPair.amountAsset
272296 let orderAmountAssetStr = if ((orderAmountAsset == unit))
273297 then "WAVES"
274298 else toBase58String(value(orderAmountAsset))
275299 let orderPriceAsset = order.assetPair.priceAsset
276300 let orderPriceAssetStr = if ((orderPriceAsset == unit))
277301 then "WAVES"
278302 else toBase58String(value(orderPriceAsset))
279303 let isValidAssetPair = if (if ((orderAmountAssetStr != amountAssetId))
280304 then true
281305 else (orderPriceAssetStr != priceAssetId))
282306 then false
283307 else true
284308 let orderPrice = order.price
285- let priceDecimals = fraction(decimalsMultPrice, priceAssetDecimals, amountAssetDecimals)
286- let castedOrderPrice = privateCastAssetToMaxDecimals(priceDecimals, orderPrice)
309+ let priceDecimals = fraction(scale8, priceAssetDecimals, amountAssetDecimals)
310+ let castedOrderPrice = privateCastToScaleOf(orderPrice, scale8, priceDecimals)
287311 let isOrderPriceValid = if ((order.orderType == Buy))
288312 then (currentPrice >= castedOrderPrice)
289313 else (castedOrderPrice >= currentPrice)
290314 [if (if (if (isValidAssetPair)
291315 then isValidMatcherSign
292316 else false)
293317 then isPoolStatusValid
294318 else false)
295319 then isOrderPriceValid
296320 else false]
297321 }
298322
299323
300324 @Callable(i)
301-func put (slippageTolerance) = {
325+func put (slippageTolerance,shouldAutoStake) = {
326+ let factoryConfigList = getFactoryConfig()
327+ let stakingContract = valueOrErrorMessage(addressFromString(factoryConfigList[idxFactoryStakingContract]), "Error. Incorrect staking address.")
302328 let pmtAmountAsset = value(i.payments[0])
303329 let inAmountAssetAmt = pmtAmountAsset.amount
304330 let inAmountAssetId = if (!(isDefined(pmtAmountAsset.assetId)))
305331 then fromBase58String("WAVES")
306332 else value(pmtAmountAsset.assetId)
307333 let pmtPriceAsset = value(i.payments[1])
308334 let inPriceAssetAmt = pmtPriceAsset.amount
309335 let inPriceAssetId = if (!(isDefined(pmtPriceAsset.assetId)))
310336 then fromBase58String("WAVES")
311337 else value(pmtPriceAsset.assetId)
312338 let estimatedPutResults = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, toBase58String(inAmountAssetId), inPriceAssetAmt, toBase58String(inPriceAssetId), toString(i.caller))
313339 let outLpAmount = estimatedPutResults._1
314340 let curentPrice = estimatedPutResults._2
315341 let userAmountAssetBalance = estimatedPutResults._3
316342 let userPriceAssetBalance = estimatedPutResults._4
317343 let userLPBalance = estimatedPutResults._5
318344 let poolAmountAssetBalance = estimatedPutResults._6
319345 let poolPriceAssetBalance = estimatedPutResults._7
320346 let poolLPBalance = estimatedPutResults._8
321347 let amountAssetInternalId = estimatedPutResults._9
322348 let priceAssetInternalId = estimatedPutResults._10
323349 let lpAssetId = estimatedPutResults._11
324350 let slippageCalculated = estimatedPutResults._12
325351 let poolStatus = parseIntValue(estimatedPutResults._13)
326352 if (if (if (isGlobalShutdown())
327353 then true
328354 else (poolStatus == PoolPutDisabled))
329355 then true
330356 else (poolStatus == PoolShutdown))
331357 then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
332358 else {
333- let emitLPAssetOnFactory = invoke(addressFromStringValue(factoryAddressString), "emit", [outLpAmount], nil)
359+ let emitLPAssetOnFactory = invoke(factoryContract, "emit", [outLpAmount], nil)
334360 if ((emitLPAssetOnFactory == emitLPAssetOnFactory))
335361 then if ((emitLPAssetOnFactory != "success"))
336362 then throw("LP asset reissue failed during emit call on factory.")
337- else [StringEntry(keyPriceLast(), ("%s__" + toString(curentPrice))), StringEntry(keyPriceHistory(height, lastBlock.timestamp), ("%s__" + toString(curentPrice))), StringEntry(keyPutActionByUser(toString(i.caller), toBase58String(i.transactionId)), dataPutActionInfo(inAmountAssetAmt, inPriceAssetAmt, outLpAmount, curentPrice, slippageTolerance, slippageCalculated, height, lastBlock.timestamp)), StringEntry(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, toString(i.caller)), dataPoolLiquidity((userAmountAssetBalance + inAmountAssetAmt), (userPriceAssetBalance + inPriceAssetAmt), (userLPBalance + outLpAmount))), StringEntry(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId), dataPoolLiquidity((poolAmountAssetBalance + inAmountAssetAmt), (poolPriceAssetBalance + inPriceAssetAmt), (poolLPBalance + outLpAmount))), ScriptTransfer(i.caller, outLpAmount, lpAssetId)]
363+ else {
364+ let results = [StringEntry(keyPriceLast(), ("%s__" + toString(curentPrice))), StringEntry(keyPriceHistory(height, lastBlock.timestamp), ("%s__" + toString(curentPrice))), StringEntry(keyPutActionByUser(toString(i.caller), toBase58String(i.transactionId)), dataPutActionInfo(inAmountAssetAmt, inPriceAssetAmt, outLpAmount, curentPrice, slippageTolerance, slippageCalculated, height, lastBlock.timestamp)), StringEntry(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, toString(i.caller)), dataPoolLiquidity((userAmountAssetBalance + inAmountAssetAmt), (userPriceAssetBalance + inPriceAssetAmt), (userLPBalance + outLpAmount))), StringEntry(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId), dataPoolLiquidity((poolAmountAssetBalance + inAmountAssetAmt), (poolPriceAssetBalance + inPriceAssetAmt), (poolLPBalance + outLpAmount)))]
365+ if (shouldAutoStake)
366+ then {
367+ let stake = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, outLpAmount)])
368+ if ((stake == stake))
369+ then results
370+ else throw("Strict value is not equal to itself.")
371+ }
372+ else (results :+ ScriptTransfer(i.caller, outLpAmount, lpAssetId))
373+ }
338374 else throw("Strict value is not equal to itself.")
339375 }
340376 }
341377
342378
343379
344380 @Callable(i)
345381 func get () = {
346382 let pmtAmountAsset = value(i.payments[0])
347383 let pmtAssetId = value(pmtAmountAsset.assetId)
348384 let pmtAssetAmount = pmtAmountAsset.amount
349385 let results = privateEstimateGetOperation(toBase58String(pmtAssetId), pmtAssetAmount, toString(i.caller))
350386 let outAmountAssetAmt = results._1
351387 let outPriceAssetAmt = results._2
352388 let amountAssetInternalId = results._3
353389 let priceAssetInternalId = results._4
354390 let userAmountAssetBalance = results._5
355391 let amountAssetId = results._6
356392 let userPriceAssetBalance = results._7
357393 let priceAssetId = results._8
358394 let userLPBalance = results._9
359395 let poolAmountAssetBalance = results._10
360396 let poolPriceAssetBalance = results._11
361397 let poolLPBalance = results._12
362398 let currentPrice = results._13
363399 let poolStatus = parseIntValue(results._14)
364400 if (if (isGlobalShutdown())
365401 then true
366402 else (poolStatus == PoolShutdown))
367403 then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
368404 else {
369- let burnLPAssetOnFactory = invoke(addressFromStringValue(factoryAddressString), "burn", [pmtAssetAmount], [AttachedPayment(pmtAssetId, pmtAssetAmount)])
405+ let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAssetAmount], [AttachedPayment(pmtAssetId, pmtAssetAmount)])
370406 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
371407 then if ((burnLPAssetOnFactory != "success"))
372408 then throw("LP asset burn failed during emit call on factory.")
373409 else [ScriptTransfer(i.caller, outAmountAssetAmt, if ((amountAssetId == "WAVES"))
374410 then unit
375411 else fromBase58String(amountAssetId)), ScriptTransfer(i.caller, outPriceAssetAmt, fromBase58String(priceAssetId)), StringEntry(keyPoolLiquidityByUser(amountAssetInternalId, priceAssetInternalId, toString(i.caller)), dataPoolLiquidity((userAmountAssetBalance - outAmountAssetAmt), (userPriceAssetBalance - outPriceAssetAmt), (userLPBalance - pmtAssetAmount))), StringEntry(keyPoolLiquidity(amountAssetInternalId, priceAssetInternalId), dataPoolLiquidity((poolAmountAssetBalance - outAmountAssetAmt), (poolPriceAssetBalance - outPriceAssetAmt), (poolLPBalance - pmtAssetAmount))), StringEntry(keyGetActionByUser(toString(i.caller), toBase58String(i.transactionId)), dataGetActionInfo(outAmountAssetAmt, outPriceAssetAmt, pmtAssetAmount, currentPrice, height, lastBlock.timestamp)), StringEntry(keyPriceLast(), ("%s__" + toString(currentPrice))), StringEntry(keyPriceHistory(height, lastBlock.timestamp), ("%s__" + toString(currentPrice)))]
376412 else throw("Strict value is not equal to itself.")
377413 }
378414 }
379415
380416
381417
382418 @Callable(i)
383-func activate (amountAssetStr,priceAssetStr) = if ((toString(i.caller) != factoryAddressString))
419+func activate (amountAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
384420 then throw("permissions denied")
385421 else $Tuple2([StringEntry(keyAmountAsset(), amountAssetStr), StringEntry(keyPriceAsset(), priceAssetStr)], "success")
386422
387423
388424
389425 @Callable(i)
390426 func statsREADONLY () = {
391427 let poolConfigDataList = getPoolConfig()
392428 let lpAssetId = fromBase58String(poolConfigDataList[idxPoolLPAssetId])
393429 let amountAssetId = poolConfigDataList[idxAmountAssetId]
394430 let priceAssetId = poolConfigDataList[idxPriceAssetId]
395431 let amountAssetInternalId = poolConfigDataList[idxAmountAssetInternalId]
396432 let priceAssetInternalId = poolConfigDataList[idxPriceAssetInternalId]
397433 let amoutAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
398434 let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
399435 let poolLiquidityDataList = getPoolLiquidity(amountAssetInternalId, priceAssetInternalId)
400436 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
401437 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
402438 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
403- let amountAssetPoolLockedAmt = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
404- let priceAssetPoolLockedAmt = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
405- let lpPriceInAmountAsset = fraction(amountAssetPoolLockedAmt, decimalsMultPrice, poolLPBalance)
406- let lpPriceInPriceAsset = fraction(priceAssetPoolLockedAmt, decimalsMultPrice, poolLPBalance)
407- let currentPrice = privateCalculatePrice(amoutAssetDecimals, priceAssetDecimals, accountAmountAssetBalance, accountPriceAssetBalance)
408- let poolWeight = valueOrErrorMessage(getInteger(value(addressFromString(factoryAddressString)), keyPoolWeight(toString(this))), "Pool doesn't have weight.")
439+ let pricesList = getPrices(accountAmountAssetBalance, accountPriceAssetBalance, poolLPBalance)
440+ let currentPrice = pricesList[0]
441+ let lpPriceInAmountAsset = pricesList[1]
442+ let lpPriceInPriceAsset = pricesList[2]
443+ let poolWeight = valueOrErrorMessage(getInteger(factoryContract, keyPoolWeight(toString(this))), "Pool doesn't have weight.")
409444 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accountAmountAssetBalance), toString(accountPriceAssetBalance), toString(poolLPBalance), toString(currentPrice), toString(lpPriceInAmountAsset), toString(lpPriceInPriceAsset), toString(poolWeight)], SEP))
410445 }
411446
412447
413448
414449 @Callable(i)
415450 func evaluatePutByAmountAssetREADONLY (slippageTolerance,inAmountAssetAmt,userAddress) = {
416451 let poolConfigDataList = getPoolConfig()
417452 let lpAssetId = fromBase58String(poolConfigDataList[idxPoolLPAssetId])
418453 let amountAssetId = poolConfigDataList[idxAmountAssetId]
419454 let priceAssetId = poolConfigDataList[idxPriceAssetId]
420455 let amountAssetInternalId = poolConfigDataList[idxAmountAssetInternalId]
421456 let priceAssetInternalId = poolConfigDataList[idxPriceAssetInternalId]
422457 let amoutAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
423458 let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
424459 let poolStatus = poolConfigDataList[idxPoolStatus]
425460 let poolLiquidityDataList = getPoolLiquidity(amountAssetInternalId, priceAssetInternalId)
426461 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
427462 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
428463 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
429- let accountAmountAssetBalanceCasted = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
430- let accountPriceAssetBalanceCasted = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
464+ let accountAmountAssetBalanceCasted = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
465+ let accountPriceAssetBalanceCasted = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
431466 let curentPrice = if ((poolLPBalance == 0))
432467 then 0
433468 else calculatePrice(accountPriceAssetBalanceCasted, accountAmountAssetBalanceCasted)
434- let inPriceAssetAmtCalculated = fraction(inAmountAssetAmt, curentPrice, decimalsMultPrice)
435- let inPriceAssetAmt = privateCastAssetToOriginDecimals(priceAssetDecimals, inPriceAssetAmtCalculated)
436- let results = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
437- $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(results._1), toString(results._2), toString(results._6), toString(results._7), toString(results._8), results._13], SEP))
469+ let inPriceAssetAmtCalculated = fraction(inAmountAssetAmt, curentPrice, scale8)
470+ let inPriceAssetAmt = privateCastToScaleOf(inPriceAssetAmtCalculated, priceAssetDecimals, scale8)
471+ let estimatedPutResults = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
472+ let outLpAmountCalc = estimatedPutResults._1
473+ let curentPriceCalc = estimatedPutResults._2
474+ let poolAmountAssetBalanceCalc = estimatedPutResults._6
475+ let poolPriceAssetBalanceCAlc = estimatedPutResults._7
476+ let poolLPBalanceCalc = estimatedPutResults._8
477+ let poolStatusCalc = parseIntValue(estimatedPutResults._13)
478+ $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(outLpAmountCalc), toString(curentPriceCalc), toString(poolAmountAssetBalanceCalc), toString(poolPriceAssetBalanceCAlc), toString(poolLPBalanceCalc), toString(poolStatusCalc)], SEP))
438479 }
439480
440481
441482
442483 @Callable(i)
443484 func evaluatePutByPriceAssetREADONLY (slippageTolerance,inPriceAssetAmt,userAddress) = {
444485 let poolConfigDataList = getPoolConfig()
445486 let lpAssetId = fromBase58String(poolConfigDataList[idxPoolLPAssetId])
446487 let amountAssetId = poolConfigDataList[idxAmountAssetId]
447488 let priceAssetId = poolConfigDataList[idxPriceAssetId]
448489 let amountAssetInternalId = poolConfigDataList[idxAmountAssetInternalId]
449490 let priceAssetInternalId = poolConfigDataList[idxPriceAssetInternalId]
450491 let amoutAssetDecimals = parseIntValue(poolConfigDataList[idxAmountAssetDecimals])
451492 let priceAssetDecimals = parseIntValue(poolConfigDataList[idxPriceAssetDecimals])
452493 let poolStatus = poolConfigDataList[idxPoolStatus]
453494 let poolLiquidityDataList = getPoolLiquidity(amountAssetInternalId, priceAssetInternalId)
454495 let poolLPBalance = parseIntValue(poolLiquidityDataList[idxPoolLPAssetAmt])
455496 let accountAmountAssetBalance = privateGetAccountBalance(amountAssetId)
456497 let accountPriceAssetBalance = privateGetAccountBalance(priceAssetId)
457- let accountAmountAssetBalanceCasted = privateCastAssetToMaxDecimals(amoutAssetDecimals, accountAmountAssetBalance)
458- let accountPriceAssetBalanceCasted = privateCastAssetToMaxDecimals(priceAssetDecimals, accountPriceAssetBalance)
459- let inPriceAssetAmtCalculatedTuple = privateCastAssetToMaxDecimals(priceAssetDecimals, inPriceAssetAmt)
498+ let accountAmountAssetBalanceCasted = privateCastToScaleOf(accountAmountAssetBalance, scale8, amoutAssetDecimals)
499+ let accountPriceAssetBalanceCasted = privateCastToScaleOf(accountPriceAssetBalance, scale8, priceAssetDecimals)
500+ let inPriceAssetAmtCalculatedTuple = privateCastToScaleOf(inPriceAssetAmt, scale8, priceAssetDecimals)
460501 let curentPrice = if ((poolLPBalance == 0))
461502 then 0
462503 else calculatePrice(accountPriceAssetBalanceCasted, accountAmountAssetBalanceCasted)
463- let inAmountAssetAmtCalculated = fraction(accountPriceAssetBalanceCasted, decimalsMultPrice, curentPrice)
464- let inAmountAssetAmt = privateCastAssetToOriginDecimals(amoutAssetDecimals, inAmountAssetAmtCalculated)
465- let results = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
466- $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(results._1), toString(results._2), toString(results._6), toString(results._7), toString(results._8), results._13], SEP))
504+ let inAmountAssetAmtCalculated = fraction(accountPriceAssetBalanceCasted, scale8, curentPrice)
505+ let inAmountAssetAmt = privateCastToScaleOf(inAmountAssetAmtCalculated, amoutAssetDecimals, scale8)
506+ let estimatedPutResults = privateEstimatePutOperation(slippageTolerance, inAmountAssetAmt, amountAssetId, inPriceAssetAmt, priceAssetId, userAddress)
507+ let outLpAmountCalc = estimatedPutResults._1
508+ let curentPriceCalc = estimatedPutResults._2
509+ let poolAmountAssetBalanceCalc = estimatedPutResults._6
510+ let poolPriceAssetBalanceCAlc = estimatedPutResults._7
511+ let poolLPBalanceCalc = estimatedPutResults._8
512+ let poolStatusCalc = parseIntValue(estimatedPutResults._13)
513+ $Tuple2(nil, makeString(["%d%d%d%d%d%d", toString(outLpAmountCalc), toString(curentPriceCalc), toString(poolAmountAssetBalanceCalc), toString(poolPriceAssetBalanceCAlc), toString(poolLPBalanceCalc), toString(poolStatusCalc)], SEP))
467514 }
468515
469516
470517
471518 @Callable(i)
472519 func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmount,userAddress) = {
473520 let results = privateEstimateGetOperation(paymentLpAssetId, paymentLpAmount, userAddress)
474- $Tuple2(nil, makeString(["%d%d%d%d%d%s%d%s%d%d%s%d%d", toString(results._1), toString(results._2), toString(results._10), toString(results._11), toString(results._12), toString(results._13), results._14], SEP))
521+ let outAmountAssetAmt = results._1
522+ let outPriceAssetAmt = results._2
523+ let poolAmountAssetBalance = results._10
524+ let poolPriceAssetBalance = results._11
525+ let poolLPBalance = results._12
526+ let currentPrice = results._13
527+ let poolStatus = parseIntValue(results._14)
528+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmountAssetAmt), toString(outPriceAssetAmt), toString(poolAmountAssetBalance), toString(poolPriceAssetBalance), toString(poolLPBalance), toString(currentPrice), toString(poolStatus)], SEP))
475529 }
476530
477531
478532
479533 @Callable(i)
480534 func hashREADONLY () = $Tuple2(nil, toBase64String(value(scriptHash(this))))
481535
482536
483537 @Verifier(tx)
484538 func verify () = match tx {
485539 case order: Order =>
486540 validateMatcherOrderAllowed(order)[1]
487541 case _ =>
488542 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
489543 }
490544

github/deemru/w8io/169f3d6 
102.29 ms