2023.10.11 20:11 [3860104] smart account 3P8w8NXZUtYdCA13tHbDY5sW4mC27ZFJgG3 > SELF 0.00000000 Waves

{ "type": 13, "id": "J9KULedbcmqhz56d14WC1vaWZa3nmWTEB9xyY2peXXtK", "fee": 3100000, "feeAssetId": null, "timestamp": 1697047699549, "version": 2, "chainId": 87, "sender": "3P8w8NXZUtYdCA13tHbDY5sW4mC27ZFJgG3", "senderPublicKey": "6uKJV5r5qjqG9uVK4Q24W7zG5KZtGtKXz3NWRMwfZbB7", "proofs": [ "4YA6yePsWUk6rQLxYiifFZwhnFG7vkn6KfQ38bdJwoS7RbLVhhwusTxRQTfquggCbFckHiapnHwoygzQDNdHeU6G", "5cQeMEniGBSA3JjYH81EBs99eSYkk2zsdmh5YQPRnbbr5zPjWNYRYX5n3QiCT2AAH4vpQB5SNqhCi4YtjUDtJv32", "", "2oUK8X4LSxVvTS8CtfsLf2MEQ54GXDKHPiS2EgVxpbEQECBnVXgqNabmAq3X7ETKwQF4GRrKNZhN7zEMMraB5Kg6" ], "script": "base64:BgIzCAISBwoFCAgBAQgSBAoCAQESABIDCgEBEgASABIAEgASABIDCgEIEgQKAggBEgQKAggBYAALcmV2aXNpb25OdW0CAAAJc2VwYXJhdG9yAgJfXwADU0VQAgJfXwAFTVVMVDYAwIQ9AAVNVUxUOACAwtcvAAZNVUxUWDYJALYCAQUFTVVMVDYABk1VTFRYOAkAtgIBBQVNVUxUOAAHTVVMVFgxOAkAtgIBAICAkLu61q3wDQAKV0FWRVNJRFNUUgIFV0FWRVMAB1dBVkVTSUQJANkEAQUKV0FWRVNJRFNUUgAJREFZTUlMTElTAIC4mSkACU1BWEJBU0tFVAAJABlJZHhDb250cm9sQ2ZnTmV1dHJpbm9EYXBwAAEAGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAACABRJZHhDb250cm9sQ2ZnUnBkRGFwcAADABVJZHhDb250cm9sQ2ZnTWF0aERhcHAABAAcSWR4Q29udHJvbENmZ0xpcXVpZGF0aW9uRGFwcAAFABVJZHhDb250cm9sQ2ZnUmVzdERhcHAABgAdSWR4Q29udHJvbENmZ05vZGVSZWdpc3RyeURhcHAABwAcSWR4Q29udHJvbENmZ05zYnRTdGFraW5nRGFwcAAIABlJZHhDb250cm9sQ2ZnTWVkaWF0b3JEYXBwAAkAG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAANAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQCsAgIJAKwCAgkArAICCQCsAgICCm1hbmRhdG9yeSAJAKUIAQUHYWRkcmVzcwIBLgUDa2V5Ag8gaXMgbm90IGRlZmluZWQBHWtleUNmZ1gyR25zYnRPZmZlckhlaWdodFN0YXJ0AAIlJXMlc19fY29uZmlnX194Mkduc2J0T2ZmZXJIZWlnaHRTdGFydAEba2V5Q2ZnWDJHbnNidE9mZmVySGVpZ2h0RW5kAAIjJXMlc19fY29uZmlnX194Mkduc2J0T2ZmZXJIZWlnaHRFbmQBEWtleUNvbnRyb2xBZGRyZXNzAAIcJXMlc19fY29uZmlnX19jb250cm9sQWRkcmVzcwENa2V5Q29udHJvbENmZwACESVzX19jb250cm9sQ29uZmlnARRyZWFkQ29udHJvbENmZ09yRmFpbAEHY29udHJvbAkAvAkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUHY29udHJvbAkBDWtleUNvbnRyb2xDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIKY29udHJvbENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCmNvbnRyb2xDZmcFA2lkeAkArAICAi1Db250cm9sIGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AA9jb250cm9sQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBEWtleUNvbnRyb2xBZGRyZXNzAAIjM1A1QmZkNThQUGZOdkJNMkh5OFFmYmNEcU1lTnR6ZzdLZlAACmNvbnRyb2xDZmcJARRyZWFkQ29udHJvbENmZ09yRmFpbAEFD2NvbnRyb2xDb250cmFjdAAMbWF0aENvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUVSWR4Q29udHJvbENmZ01hdGhEYXBwABBuZXV0cmlub0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAAPYXVjdGlvbkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwAAtnb3ZDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAATbmV1dHJpbm9EYW9Db250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BFaWlKUmtWNjZUMU5XN01vWTNER2dDYXhvRFJDZXo4ZkwAElJFTkVXX1NUQVJUX0hFSUdIVAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEda2V5Q2ZnWDJHbnNidE9mZmVySGVpZ2h0U3RhcnQAAAAAEFJFTkVXX0VORF9IRUlHSFQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBG2tleUNmZ1gyR25zYnRPZmZlckhlaWdodEVuZAAAAAEMa2V5Qm9uZEFzc2V0AAINYm9uZF9hc3NldF9pZAEXa2V5VXNlckduc2J0UmVsZWFzZVRpbWUBCHVzZXJBZGRyCQCsAgICGyVzJXNfdXNlckduc2J0UmVsZWFzZVRpbWVfXwUIdXNlckFkZHIBGmtleU5ldXRyaW5vQ29udHJhY3RBZGRyZXNzAAIbJXNfX25ldXRyaW5vQ29udHJhY3RBZGRyZXNzARZrZXlNYXRoQ29udHJhY3RBZGRyZXNzAAIQJXNfX21hdGhDb250cmFjdAEQa2V5TWluTG9ja0Ftb3VudAACESVzX19taW5Mb2NrQW1vdW50AQtrZXlIYWxmTGlmZQACDCVzX19oYWxmTGlmZQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCAgZhbW91bnQFA25pbAUJc2VwYXJhdG9yARZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtwYXJhbUJ5VXNlcgkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICBXN0YXJ0BQNuaWwFCXNlcGFyYXRvcgEVa2V5TG9ja1BhcmFtVXNlckduc2J0AQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtwYXJhbUJ5VXNlcgkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICBWdOc2J0BQNuaWwFCXNlcGFyYXRvcgEZa2V5VXNlckNvbnNlbnRlZFRvWDJHbnNidAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCAhJjb25zZW50ZWRUb1gyR25zYnQFA25pbAUJc2VwYXJhdG9yARBrZXlIaXN0b3J5UmVjb3JkAwR0eXBlC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCAgdoaXN0b3J5CQDMCAIFBHR5cGUJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCCQDYBAEFBHR4SWQFA25pbAUJc2VwYXJhdG9yARdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAJALkJAgkAzAgCAgQlcyVzCQDMCAICBXN0YXRzCQDMCAICEWFjdGl2ZVRvdGFsTG9ja2VkBQNuaWwFCXNlcGFyYXRvcgEWa2V5TG9ja1BhcmFtVG90YWxHbnNidAAJALkJAgkAzAgCAgQlcyVzCQDMCAICBXN0YXRzCQDMCAICEGFjdGl2ZVRvdGFsR25zYnQFA25pbAUJc2VwYXJhdG9yARJrZXlTdGF0c0xvY2tzQ291bnQACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVzdGF0cwkAzAgCAgpsb2Nrc0NvdW50BQNuaWwFCXNlcGFyYXRvcgESa2V5U3RhdHNVc2Vyc0NvdW50AAkAuQkCCQDMCAICBCVzJXMJAMwIAgIFc3RhdHMJAMwIAgIQYWN0aXZlVXNlcnNDb3VudAUDbmlsBQlzZXBhcmF0b3IBF2tleVN0YXRzRGVwb3NpdEFtdEJ5RGF5AQl0aW1lc3RhbXAJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIFc3RhdHMJAMwIAgIPZGVwb3NpdEFtdEJ5RGF5CQDMCAIJAKQDAQUJdGltZXN0YW1wBQNuaWwFCXNlcGFyYXRvcgEYa2V5U3RhdHNEZXBvc2l0QW10VG90YWxzAAkAuQkCCQDMCAICBiVzJXMlZAkAzAgCAgVzdGF0cwkAzAgCAhBkZXBvc2l0QW10VG90YWxzBQNuaWwFCXNlcGFyYXRvcgENa2V5TmV4dFBlcmlvZAACDiVzX19uZXh0UGVyaW9kARhrZXlTdXBwb3J0ZWRSZXdhcmRBc3NldHMAAhVzdXBwb3J0ZWRSZXdhcmRBc3NldHMBEWtleURlcG9zaXROdW1MYXN0AAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgNkZXAJAMwIAgIHbGFzdE51bQUDbmlsBQlzZXBhcmF0b3IBG2tleVVzZXJSZXdhcmRGcm9tRGVwb3NpdE51bQELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIRdXNlclJ3ZEZyb21EZXBOdW0JAMwIAgULdXNlckFkZHJlc3MFA25pbAUJc2VwYXJhdG9yARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCCmRlcG9zaXROdW0DdGtuCQC5CQIJAMwIAgIEJXMlZAkAzAgCAhVyd2RQZXJOc2J0U3VtQnlEZXBOdW0JAMwIAgkApAMBBQpkZXBvc2l0TnVtCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBCWtleVJld2FyZAILdXNlckFkZHJlc3MDdGtuCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICA3J3ZAkAzAgCBQt1c2VyQWRkcmVzcwkAzAgCBQN0a24FA25pbAUJc2VwYXJhdG9yAQprZXlDbGFpbWVkAgt1c2VyQWRkcmVzcwN0a24JALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIDY2xtCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBF2tleU5vdERpc3RyaWJ1dGVkUmV3YXJkAQN0a24JALkJAgkAzAgCAgQlcyVzCQDMCAICDm5vdERpc3RyaWJ1dGVkCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBBXRvWDE4AgdvcmlnVmFsCG9yaWdNdWx0CQC8AgMJALYCAQUHb3JpZ1ZhbAUHTVVMVFgxOAUIb3JpZ011bHQBDGdldEludE9yWmVybwEDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQxnZXRJbnRPckVsc2UCA2tleQpkZWZhdWx0VmFsCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQUKZGVmYXVsdFZhbAEMZ2V0SW50T3JGYWlsAQNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQNrZXkJAKwCAgkArAICAg9NYW5kYXRvcnkgdGhpcy4FA2tleQIPIGlzIG5vdCBkZWZpbmVkAQxnZXRTdHJPckVsc2UCA2tleQpkZWZhdWx0VmFsCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQUKZGVmYXVsdFZhbAEPdG9BZGRyZXNzT3JGYWlsAQphZGRyZXNzU3RyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUKYWRkcmVzc1N0cgkArAICAiFjb3VsZG4ndCBwYXJzZSBwYXNzZWQgYWRkcmVzc1N0cj0FCmFkZHJlc3NTdHIBC3RvQXNzZXRWZWN0AQhhc3NldFN0cgMJAAACBQhhc3NldFN0cgUKV0FWRVNJRFNUUgUEdW5pdAkA2QQBBQhhc3NldFN0cgEFYXNJbnQBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACA0ludAQGdmFsSW50BQckbWF0Y2gwBQZ2YWxJbnQJAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBE2Zvcm1hdEhpc3RvcnlSZWNvcmQECW9sZEFtb3VudAhvbGRTdGFydAluZXdBbW91bnQIbmV3U3RhcnQJALkJAgkAzAgCAgwlZCVkJWQlZCVkJWQJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUJb2xkQW1vdW50CQDMCAIJAKQDAQUIb2xkU3RhcnQJAMwIAgkApAMBBQluZXdBbW91bnQJAMwIAgkApAMBBQhuZXdTdGFydAUDbmlsBQlzZXBhcmF0b3IBGGZvcm1hdENsYWltSGlzdG9yeVJlY29yZAIEdXNlcg5jbGFpbWVkUmV3YXJkcwkAuQkCCQDMCAICCCVzJWQlZCVzCQDMCAIFBHVzZXIJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIFDmNsYWltZWRSZXdhcmRzBQNuaWwFCXNlcGFyYXRvcgESSGlzdG9yeVJlY29yZEVudHJ5BwR0eXBlC3VzZXJBZGRyZXNzBHR4SWQJb2xkQW1vdW50CG9sZFN0YXJ0CW5ld0Ftb3VudAhuZXdTdGFydAkBC1N0cmluZ0VudHJ5AgkBEGtleUhpc3RvcnlSZWNvcmQDBQR0eXBlBQt1c2VyQWRkcmVzcwUEdHhJZAkBE2Zvcm1hdEhpc3RvcnlSZWNvcmQEBQlvbGRBbW91bnQFCG9sZFN0YXJ0BQluZXdBbW91bnQFCG5ld1N0YXJ0ARFDbGFpbUhpc3RvcnlFbnRyeQMLdXNlckFkZHJlc3MEdHhJZA5jbGFpbWVkUmV3YXJkcwkBC1N0cmluZ0VudHJ5AgkBEGtleUhpc3RvcnlSZWNvcmQDAgVjbGFpbQULdXNlckFkZHJlc3MFBHR4SWQJARhmb3JtYXRDbGFpbUhpc3RvcnlSZWNvcmQCCQClCAEFC3VzZXJBZGRyZXNzBQ5jbGFpbWVkUmV3YXJkcwELU3RhdHNSZXN1bHQEDnRvdGFsTG9ja2VkSW5jDGxvY2tDb3VudEluYw11c2Vyc0NvdW50SW5jDXRvdGFsR25zYnRJbmMECmxvY2tzQ291bnQJAQxnZXRJbnRPclplcm8BCQESa2V5U3RhdHNMb2Nrc0NvdW50AAQKdXNlcnNDb3VudAkBDGdldEludE9yWmVybwEJARJrZXlTdGF0c1VzZXJzQ291bnQABAt0b3RhbEFtb3VudAkBDGdldEludE9yWmVybwEJARdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAEDnRvdGFsQW1vdW50TmV3CQBkAgULdG90YWxBbW91bnQFDnRvdGFsTG9ja2VkSW5jBAp0b3RhbEduc2J0CQEMZ2V0SW50T3JFbHNlAgkBFmtleUxvY2tQYXJhbVRvdGFsR25zYnQABQt0b3RhbEFtb3VudAkAlQoDCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESa2V5U3RhdHNMb2Nrc0NvdW50AAkAZAIFCmxvY2tzQ291bnQFDGxvY2tDb3VudEluYwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleVN0YXRzVXNlcnNDb3VudAAJAGQCBQp1c2Vyc0NvdW50BQ11c2Vyc0NvdW50SW5jCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQABQ50b3RhbEFtb3VudE5ldwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUxvY2tQYXJhbVRvdGFsR25zYnQACQBkAgUKdG90YWxHbnNidAUNdG90YWxHbnNidEluYwUDbmlsBQt0b3RhbEFtb3VudAUOdG90YWxBbW91bnROZXcBD0xvY2tQYXJhbXNFbnRyeQQLdXNlckFkZHJlc3MKbnNidEFtb3VudAVzdGFydAtnTnNidEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBBQt1c2VyQWRkcmVzcwUKbnNidEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFWtleUxvY2tQYXJhbVVzZXJHbnNidAEFC3VzZXJBZGRyZXNzBQtnTnNidEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sBBQt1c2VyQWRkcmVzcwUFc3RhcnQFA25pbAEPZ2V0UGFyYW1zT3JGYWlsAAkAlQoDCQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFEG5ldXRyaW5vQ29udHJhY3QJAQxrZXlCb25kQXNzZXQACQEMZ2V0SW50T3JGYWlsAQkBEGtleU1pbkxvY2tBbW91bnQACQEMZ2V0SW50T3JGYWlsAQkBC2tleUhhbGZMaWZlAAEMaXNBY3RpdmVVc2VyAQt1c2VyQWRkcmVzcwkAZgIJAQxnZXRJbnRPckVsc2UCCQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEFC3VzZXJBZGRyZXNzAAAAAAENaXNCb251c1BlcmlvZAEBaAMJAGcCBQFoBRJSRU5FV19TVEFSVF9IRUlHSFQJAGcCBRBSRU5FV19FTkRfSEVJR0hUBQFoBwETZ2V0VXNlclBhcmFtc09yVW5pdAELdXNlckFkZHJlc3MDCQEMaXNBY3RpdmVVc2VyAQULdXNlckFkZHJlc3MEBmFtb3VudAkBDGdldEludE9yRmFpbAEJARZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AQULdXNlckFkZHJlc3MJAJYKBAcFBmFtb3VudAkBDGdldEludE9yRmFpbAEJARZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAQULdXNlckFkZHJlc3MJAQxnZXRJbnRPckVsc2UCCQEVa2V5TG9ja1BhcmFtVXNlckduc2J0AQULdXNlckFkZHJlc3MFBmFtb3VudAUEdW5pdAETZ2V0VXNlclBhcmFtc09yRmFpbAELdXNlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkArAICCQCsAgICBVVzZXIgCQClCAEFC3VzZXJBZGRyZXNzAg8gaXMgbm90IGRlZmluZWQAEnN1cHBvcnRlZEFzc2V0c1N0cgkBDGdldFN0ck9yRWxzZQIJARhrZXlTdXBwb3J0ZWRSZXdhcmRBc3NldHMAAgAAE3N1cHBvcnRlZEFzc2V0c0xpc3QJALUJAgUSc3VwcG9ydGVkQXNzZXRzU3RyAgFfAQpjYWxjUmV3YXJkBQt1c2VyQWRkcmVzcwdhc3NldElkDXN0YWtlZEFtb3VudFgOZGVwb3NpdE51bVVzZXIOZGVwb3NpdE51bUxhc3QEF3Jld2FyZFBlck5zYnRTdW1MYXN0S0VZCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bUxhc3QFB2Fzc2V0SWQECnN1bUxhc3RYMTgJAKcDAQkBDGdldFN0ck9yRWxzZQIJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ5kZXBvc2l0TnVtTGFzdAUHYXNzZXRJZAIBMAQKc3VtVXNlclgxOAkApwMBCQEMZ2V0U3RyT3JFbHNlAgkBFWtleVJld2FyZFBlck5zYnRTdW1BdAIFDmRlcG9zaXROdW1Vc2VyBQdhc3NldElkAgEwBBFyZXdhcmREeW5hbWljUGFydAkAoAMBCQC8AgMJALgCAgUKc3VtTGFzdFgxOAUKc3VtVXNlclgxOAUNc3Rha2VkQW1vdW50WAUHTVVMVFgxOAQTcmV3YXJkQ2FjaGVkUGFydEtFWQkBCWtleVJld2FyZAIFC3VzZXJBZGRyZXNzBQdhc3NldElkBBByZXdhcmRDYWNoZWRQYXJ0CQEMZ2V0SW50T3JFbHNlAgUTcmV3YXJkQ2FjaGVkUGFydEtFWQAACQCWCgQJAGQCBRByZXdhcmRDYWNoZWRQYXJ0BRFyZXdhcmREeW5hbWljUGFydAUQcmV3YXJkQ2FjaGVkUGFydAURcmV3YXJkRHluYW1pY1BhcnQFE3Jld2FyZENhY2hlZFBhcnRLRVkBDHRvU3RhcnRPZkRheQEJdGltZXN0YW1wCQBoAgkAaQIFCXRpbWVzdGFtcAUJREFZTUlMTElTBQlEQVlNSUxMSVMBE2ZpbmRFbGVtZW50UG9zaXRpb24DA3NyYwdlbGVtZW50A3NlcAQMZWxlbWVudFN0YXJ0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJALMJAgUDc3JjBQdlbGVtZW50CQCsAgIJAKwCAgkArAICAhZ0aGVyZSBpcyBubyBzdWJzdHJpbmcgBQdlbGVtZW50AgQgaW4gBQNzcmMDCQAAAgUMZWxlbWVudFN0YXJ0AAAAAAQEbGVmdAkArwICBQNzcmMFDGVsZW1lbnRTdGFydAkAZQIJAJADAQkAtQkCBQRsZWZ0BQNzZXAAAQATRGVwb3NpdFRvdGFsc1BSRUZJWAIkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkABFkZWZhdWx0VG90YWxzREFUQQkArAICBRNEZXBvc2l0VG90YWxzUFJFRklYAjZfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzBfXzABB3BhZExpc3QBAmluBAhjdXJyU2l6ZQkAZQIJAJADAQUCaW4AAQoBCmxpc3RQYWRkZXICA2FjYwNpZHgDCQBmAgUIY3VyclNpemUFA2lkeAUDYWNjCQDNCAIFA2FjYwIBMAoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQkAzAgCAAoJAMwIAgALCQDMCAIADAkAzAgCAA0JAMwIAgAOCQDMCAIADwkAzAgCABAJAMwIAgARBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQJpbgoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKbGlzdFBhZGRlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIBCXBhZFN0cmluZwECaW4ECGN1cnJTaXplCQBlAgkAkAMBCQC8CQIFAmluBQNTRVAAAQoBCXN0clBhZGRlcgIDYWNjA2lkeAMJAGYCBQhjdXJyU2l6ZQUDaWR4BQNhY2MJAKwCAgUDYWNjAgNfXzAKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwkAzAgCAAwJAMwIAgANCQDMCAIADgkAzAgCAA8JAMwIAgAQCQDMCAIAEQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUCaW4KAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCXN0clBhZGRlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIBDVJld2FyZEVudHJpZXMDCWlzTmV3VXNlcgt1c2VyQWRkcmVzcwxzdGFrZWRBbW91bnQEDXN0YWtlZEFtb3VudFgJALYCAQUMc3Rha2VkQW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQt1c2VyQWRkcmVzcwQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKARtmb3JFYWNoQXNzZXRDYWNoZVVzZXJSZXdhcmQCBWFjY3VtBWFzc2V0BA0kdDAxMTQ4MzExNjE4CQEKY2FsY1Jld2FyZAUFC3VzZXJBZGRyZXNzBQVhc3NldAUNc3Rha2VkQW1vdW50WAUOZGVwb3NpdE51bVVzZXIFDmRlcG9zaXROdW1MYXN0BAtyZXdhcmRUb3RhbAgFDSR0MDExNDgzMTE2MTgCXzEEBmNhY2hlZAgFDSR0MDExNDgzMTE2MTgCXzIEB2R5bmFtaWMIBQ0kdDAxMTQ4MzExNjE4Al8zBBNyZXdhcmRDYWNoZWRQYXJ0S0VZCAUNJHQwMTE0ODMxMTYxOAJfNAkAzQgCBQVhY2N1bQkBDEludGVnZXJFbnRyeQIFE3Jld2FyZENhY2hlZFBhcnRLRVkFC3Jld2FyZFRvdGFsAwMJAAACBQ5kZXBvc2l0TnVtTGFzdAD///////////8BCQAAAgUOZGVwb3NpdE51bVVzZXIA////////////AQcFA25pbAMDCQAAAgUOZGVwb3NpdE51bUxhc3QA////////////AQkAZgIFDmRlcG9zaXROdW1Vc2VyAP///////////wEHCQACAQIvaW52YWxpZCBkZXBvc2l0TnVtTGFzdCBhbmQgZGVwb3NpdE51bVVzZXIgc3RhdGUDAwkAZgIFDmRlcG9zaXROdW1MYXN0AP///////////wEJAGcCBQ5kZXBvc2l0TnVtVXNlcgD///////////8BBwMFCWlzTmV3VXNlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUbdXNlclJld2FyZEZyb21EZXBvc2l0TnVtS0VZBQ5kZXBvc2l0TnVtTGFzdAUDbmlsCQDNCAIKAAIkbAUTc3VwcG9ydGVkQXNzZXRzTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEbZm9yRWFjaEFzc2V0Q2FjaGVVc2VyUmV3YXJkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA5CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJCQEMSW50ZWdlckVudHJ5AgUbdXNlclJld2FyZEZyb21EZXBvc2l0TnVtS0VZBQ5kZXBvc2l0TnVtTGFzdAkAAgEJAKwCAgkArAICCQCsAgICJHVuY292ZXJlZCBjb25kaXRpb246IGRlcG9zaXROdW1MYXN0PQkApAMBBQ5kZXBvc2l0TnVtTGFzdAIQIGRlcG9zaXROdW1Vc2VyPQkApAMBBQ5kZXBvc2l0TnVtVXNlcgEiSW5jcmVtZW50Tm90RGlzdHJpYnV0ZWRSZXdhcmRFbnRyeQIDdGtuCWFtb3VudEluYwQXbm90RGlzdHJpYnV0ZWRSZXdhcmRLRVkJARdrZXlOb3REaXN0cmlidXRlZFJld2FyZAEFA3RrbgQUbm90RGlzdHJpYnV0ZWRSZXdhcmQJAQxnZXRJbnRPckVsc2UCBRdub3REaXN0cmlidXRlZFJld2FyZEtFWQAACQEMSW50ZWdlckVudHJ5AgUXbm90RGlzdHJpYnV0ZWRSZXdhcmRLRVkJAGQCBRRub3REaXN0cmlidXRlZFJld2FyZAUJYW1vdW50SW5jAQtjb21tb25DbGFpbQILdXNlckFkZHJlc3MBaQQOdXNlckFkZHJlc3NTdHIJAKUIAQULdXNlckFkZHJlc3MDCQBmAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIZcGF5bWVudHMgYXJlIG5vdCBhY2NlcHRlZAQNJHQwMTQ1NTkxNDY4MAkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlgoEBgAAAAAAAAQJaXNOZXdVc2VyCAUNJHQwMTQ1NTkxNDY4MAJfMQQMc3Rha2VkQW1vdW50CAUNJHQwMTQ1NTkxNDY4MAJfMgQMc3Rha2luZ1N0YXJ0CAUNJHQwMTQ1NTkxNDY4MAJfMwQLZ05zYnRBbW91bnQIBQ0kdDAxNDU1OTE0NjgwAl80BA1zdGFrZWRBbW91bnRYCQC2AgEFC2dOc2J0QW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQ51c2VyQWRkcmVzc1N0cgQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgVhY2N1bQVhc3NldAQNJHQwMTUwNTAxNTE4OAkBCmNhbGNSZXdhcmQFBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQ0kdDAxNTA1MDE1MTg4Al8xBAZjYWNoZWQIBQ0kdDAxNTA1MDE1MTg4Al8yBAdkeW5hbWljCAUNJHQwMTUwNTAxNTE4OAJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFDSR0MDE1MDUwMTUxODgCXzQECmNsYWltZWRLRVkJAQprZXlDbGFpbWVkAgUOdXNlckFkZHJlc3NTdHIFBWFzc2V0BA0kdDAxNTI0ODE1Mjg1BQVhY2N1bQQEZGF0YQgFDSR0MDE1MjQ4MTUyODUCXzEEEWNsYWltZWRBbXRCeUFzc2V0CAUNJHQwMTUyNDgxNTI4NQJfMgQHbmV3UGFydAkAuQkCCQDMCAIFBWFzc2V0CQDMCAIJAKQDAQULcmV3YXJkVG90YWwFA25pbAIBOgQUY2xhaW1lZEFtdEJ5QXNzZXROZXcJALkJAgkAzAgCBRFjbGFpbWVkQW10QnlBc3NldAkAzAgCBQduZXdQYXJ0BQNuaWwCAV8DCQBnAgAABQtyZXdhcmRUb3RhbAkAlAoCBQRkYXRhBRRjbGFpbWVkQW10QnlBc3NldE5ldwkAlAoCCQDNCAIJAM0IAgkAzQgCBQRkYXRhCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwULcmV3YXJkVG90YWwJAQt0b0Fzc2V0VmVjdAEFBWFzc2V0CQEMSW50ZWdlckVudHJ5AgUKY2xhaW1lZEtFWQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUKY2xhaW1lZEtFWQAABQtyZXdhcmRUb3RhbAkBDEludGVnZXJFbnRyeQIFE3Jld2FyZENhY2hlZFBhcnRLRVkAAAUUY2xhaW1lZEFtdEJ5QXNzZXROZXcEDSR0MDE1NzQ1MTU4NTgKAAIkbAUTc3VwcG9ydGVkQXNzZXRzTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBH2ZvckVhY2hBc3NldENhbGNVbmNsYWltZWRSZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDkJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkECXRyYW5zZmVycwgFDSR0MDE1NzQ1MTU4NTgCXzEEF2NsYWltZWRBbXRCeUFzc2V0UmVzdWx0CAUNJHQwMTU3NDUxNTg1OAJfMgMJAGcCAAAJAJADAQUJdHJhbnNmZXJzCQCUCgIFA25pbAAACQCUCgIJAM0IAgkAzQgCBQl0cmFuc2ZlcnMJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0CQERQ2xhaW1IaXN0b3J5RW50cnkDBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAkAsAICBRdjbGFpbWVkQW10QnlBc3NldFJlc3VsdAABCQCQAwEFCXRyYW5zZmVycwEYcmVhZFVzZXJDb25zZW50VG9YMkduc2J0AQt1c2VyQWRkcmVzcwQDa2V5CQEZa2V5VXNlckNvbnNlbnRlZFRvWDJHbnNidAEFC3VzZXJBZGRyZXNzBAN2YWwJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUDa2V5BwkAlAoCBQNrZXkFA3ZhbAENY29tbW9uWDJHbnNidAILdXNlckFkZHJlc3MBaQMJAQEhAQkBDWlzQm9udXNQZXJpb2QBBQZoZWlnaHQJAAIBAiZObyAnRG91YmxlIGdOU0JUIGFjdGlvbicgYXZhaWxhYmxlIG5vdwQNJHQwMTY0MjAxNjQ4MQkBC2NvbW1vbkNsYWltAgULdXNlckFkZHJlc3MFAWkEDGNsYWltQWN0aW9ucwgFDSR0MDE2NDIwMTY0ODECXzEEC2NsYWltUmVzdWx0CAUNJHQwMTY0MjAxNjQ4MQJfMgQNJHQwMTY0ODQxNjYwOQkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlgoEBgAAAP///////////wEAAAQJaXNOZXdVc2VyCAUNJHQwMTY0ODQxNjYwOQJfMQQKbG9ja0Ftb3VudAgFDSR0MDE2NDg0MTY2MDkCXzIED2xvY2tTdGFydEhlaWdodAgFDSR0MDE2NDg0MTY2MDkCXzMEDWN1cnJVc2VyR25zYnQIBQ0kdDAxNjQ4NDE2NjA5Al80AwUJaXNOZXdVc2VyCQACAQIbWW91IGhhdmUgbm90aGluZyB0byByZXN0YWtlBA5kZWx0YVVzZXJHbnNidAUNY3VyclVzZXJHbnNidAQMbmV3VXNlckduc2J0CQBkAgUNY3VyclVzZXJHbnNidAUOZGVsdGFVc2VyR25zYnQEEHVzZXJDb25zZW50VHVwbGUJARhyZWFkVXNlckNvbnNlbnRUb1gyR25zYnQBBQt1c2VyQWRkcmVzcwQZdXNlckNvbnNlbnRlZFRvWDJHbnNidEtFWQgFEHVzZXJDb25zZW50VHVwbGUCXzEEFnVzZXJDb25zZW50ZWRUb1gyR25zYnQIBRB1c2VyQ29uc2VudFR1cGxlAl8yAwUWdXNlckNvbnNlbnRlZFRvWDJHbnNidAkAAgECKFVzZXIgaGFzIGFscmVhZHkgZG91YmxlZCBpdHMgZ05TQlQgdmFsdWUEDSR0MDE3MDI2MTcxMTIJAQtTdGF0c1Jlc3VsdAQAAAAAAAAFDmRlbHRhVXNlckduc2J0BAxzdGF0c0VudHJpZXMIBQ0kdDAxNzAyNjE3MTEyAl8xBAt0b3RhbFN0YWtlZAgFDSR0MDE3MDI2MTcxMTICXzIEDnRvdGFsU3Rha2VkTmV3CAUNJHQwMTcwMjYxNzExMgJfMwkAlAoCCQDNCAIJAM4IAgkAzggCBQxjbGFpbUFjdGlvbnMJAQ9Mb2NrUGFyYW1zRW50cnkEBQt1c2VyQWRkcmVzcwUKbG9ja0Ftb3VudAUGaGVpZ2h0BQxuZXdVc2VyR25zYnQFDHN0YXRzRW50cmllcwkBDEJvb2xlYW5FbnRyeQIFGXVzZXJDb25zZW50ZWRUb1gyR25zYnRLRVkGBQtjbGFpbVJlc3VsdAwBaQENY29uc3RydWN0b3JWMQUXbmV1dHJpbm9Db250cmFjdEFkZHJlc3MTbWF0aENvbnRyYWN0QWRkcmVzcw1taW5Mb2NrQW1vdW50CGhhbGZMaWZlFXN1cHBvcnRlZFJld2FyZEFzc2V0cwMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEVBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARprZXlOZXV0cmlub0NvbnRyYWN0QWRkcmVzcwAFF25ldXRyaW5vQ29udHJhY3RBZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARZrZXlNYXRoQ29udHJhY3RBZGRyZXNzAAUTbWF0aENvbnRyYWN0QWRkcmVzcwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEGtleU1pbkxvY2tBbW91bnQABQ1taW5Mb2NrQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQELa2V5SGFsZkxpZmUABQhoYWxmTGlmZQkAzAgCCQELU3RyaW5nRW50cnkCCQEYa2V5U3VwcG9ydGVkUmV3YXJkQXNzZXRzAAUVc3VwcG9ydGVkUmV3YXJkQXNzZXRzBQNuaWwBaQENY29uc3RydWN0b3JWMgIXeDJHbnNidE9mZmVySGVpZ2h0U3RhcnQVeDJHbnNidE9mZmVySGVpZ2h0RW5kAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRUGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAR1rZXlDZmdYMkduc2J0T2ZmZXJIZWlnaHRTdGFydAAFF3gyR25zYnRPZmZlckhlaWdodFN0YXJ0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEba2V5Q2ZnWDJHbnNidE9mZmVySGVpZ2h0RW5kAAUVeDJHbnNidE9mZmVySGVpZ2h0RW5kBQNuaWwBaQEFc3Rha2UABA0kdDAxODIxODE4MjgwCQEPZ2V0UGFyYW1zT3JGYWlsAAQLYm9uZEFzc2V0SWQIBQ0kdDAxODIxODE4MjgwAl8xBA1taW5Mb2NrQW1vdW50CAUNJHQwMTgyMTgxODI4MAJfMgQIaGFsZkxpZmUIBQ0kdDAxODIxODE4MjgwAl8zAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIVSW52YWxpZCBwYXltZW50cyBzaXplBAdwYXltZW50CQCRAwIIBQFpCHBheW1lbnRzAAAEBmFtb3VudAgFB3BheW1lbnQGYW1vdW50BBNpbnZhbGlkQXNzZXRNZXNzYWdlCQCsAgIJAKwCAgIPSW52YWxpZCBhc3NldC4gCQDYBAEFC2JvbmRBc3NldElkAgwgaXMgZXhwZWN0ZWQEB2Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggFB3BheW1lbnQHYXNzZXRJZAUTaW52YWxpZEFzc2V0TWVzc2FnZQMJAQIhPQIFB2Fzc2V0SWQFC2JvbmRBc3NldElkCQACAQUTaW52YWxpZEFzc2V0TWVzc2FnZQQLdXNlckFkZHJlc3MIBQFpBmNhbGxlcgQOdXNlckFkZHJlc3NTdHIJAKUIAQgFAWkGY2FsbGVyBA0kdDAxODgyMjE4OTQ3CQELdmFsdWVPckVsc2UCCQETZ2V0VXNlclBhcmFtc09yVW5pdAEFC3VzZXJBZGRyZXNzCQCWCgQGAAAA////////////AQAABAlpc05ld1VzZXIIBQ0kdDAxODgyMjE4OTQ3Al8xBApsb2NrQW1vdW50CAUNJHQwMTg4MjIxODk0NwJfMgQPbG9ja1N0YXJ0SGVpZ2h0CAUNJHQwMTg4MjIxODk0NwJfMwQNY3VyclVzZXJHbnNidAgFDSR0MDE4ODIyMTg5NDcCXzQEDG1lcmdlZEFtb3VudAMFCWlzTmV3VXNlcgUGYW1vdW50CQBkAgUGYW1vdW50BQpsb2NrQW1vdW50BBFtZXJnZWRTdGFydEhlaWdodAMFCWlzTmV3VXNlcgUGaGVpZ2h0CQEFYXNJbnQBCQD8BwQFDG1hdGhDb250cmFjdAITbWVyZ2VTdGFrZXNSRUFET05MWQkAzAgCBQZhbW91bnQJAMwIAgUGaGVpZ2h0CQDMCAIFCmxvY2tBbW91bnQJAMwIAgUPbG9ja1N0YXJ0SGVpZ2h0CQDMCAIFCGhhbGZMaWZlBQNuaWwFA25pbAMJAGYCBQ1taW5Mb2NrQW1vdW50BQxtZXJnZWRBbW91bnQJAAIBCQCsAgICE01pbiBsb2NrIGFtb3VudCBpcyAJAKQDAQUNbWluTG9ja0Ftb3VudAQQdXNlckNvbnNlbnRUdXBsZQkBGHJlYWRVc2VyQ29uc2VudFRvWDJHbnNidAEFC3VzZXJBZGRyZXNzBBl1c2VyQ29uc2VudGVkVG9YMkduc2J0S0VZCAUQdXNlckNvbnNlbnRUdXBsZQJfMQQWdXNlckNvbnNlbnRlZFRvWDJHbnNidAgFEHVzZXJDb25zZW50VHVwbGUCXzIEDmRlbHRhVXNlckduc2J0AwMJAQ1pc0JvbnVzUGVyaW9kAQUGaGVpZ2h0AwUJaXNOZXdVc2VyBgUWdXNlckNvbnNlbnRlZFRvWDJHbnNidAcJAGgCAAIFBmFtb3VudAUGYW1vdW50BBN4Mkduc2J0Q29uc2VudEVudHJ5AwUJaXNOZXdVc2VyCQDMCAIJAQxCb29sZWFuRW50cnkCBRl1c2VyQ29uc2VudGVkVG9YMkduc2J0S0VZBgUDbmlsBQNuaWwEDSR0MDE5OTUxMjAwNjkJAQtTdGF0c1Jlc3VsdAQFBmFtb3VudAABAwUJaXNOZXdVc2VyAAEAAAUOZGVsdGFVc2VyR25zYnQEDHN0YXRzRW50cmllcwgFDSR0MDE5OTUxMjAwNjkCXzEEC3RvdGFsU3Rha2VkCAUNJHQwMTk5NTEyMDA2OQJfMgQOdG90YWxTdGFrZWROZXcIBQ0kdDAxOTk1MTIwMDY5Al8zCQDOCAIJAM4IAgkAzggCCQDOCAIJAMwIAgkBEkhpc3RvcnlSZWNvcmRFbnRyeQcCBXN0YWtlBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAUKbG9ja0Ftb3VudAUPbG9ja1N0YXJ0SGVpZ2h0BQxtZXJnZWRBbW91bnQFEW1lcmdlZFN0YXJ0SGVpZ2h0BQNuaWwJAQ1SZXdhcmRFbnRyaWVzAwUJaXNOZXdVc2VyBQ51c2VyQWRkcmVzc1N0cgUNY3VyclVzZXJHbnNidAkBD0xvY2tQYXJhbXNFbnRyeQQFC3VzZXJBZGRyZXNzBQxtZXJnZWRBbW91bnQFEW1lcmdlZFN0YXJ0SGVpZ2h0CQBkAgUNY3VyclVzZXJHbnNidAUOZGVsdGFVc2VyR25zYnQFDHN0YXRzRW50cmllcwUTeDJHbnNidENvbnNlbnRFbnRyeQFpAQd1bnN0YWtlAQZhbW91bnQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiN1bnN0YWtlIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudAQLdXNlckFkZHJlc3MIBQFpBmNhbGxlcgQOdXNlckFkZHJlc3NTdHIJAKUIAQULdXNlckFkZHJlc3MEDSR0MDIwNjE1MjA2NzcJAQ9nZXRQYXJhbXNPckZhaWwABAtib25kQXNzZXRJZAgFDSR0MDIwNjE1MjA2NzcCXzEEDW1pbkxvY2tBbW91bnQIBQ0kdDAyMDYxNTIwNjc3Al8yBAhoYWxmTGlmZQgFDSR0MDIwNjE1MjA2NzcCXzMEDSR0MDIwNjgwMjA3NjkJARNnZXRVc2VyUGFyYW1zT3JGYWlsAQULdXNlckFkZHJlc3MECWlzTmV3VXNlcggFDSR0MDIwNjgwMjA3NjkCXzEECmxvY2tBbW91bnQIBQ0kdDAyMDY4MDIwNzY5Al8yBAlsb2NrU3RhcnQIBQ0kdDAyMDY4MDIwNzY5Al8zBA1jdXJyVXNlckduc2J0CAUNJHQwMjA2ODAyMDc2OQJfNAMJAGcCAAAFCmxvY2tBbW91bnQJAAIBAhJOb3RoaW5nIHRvIHVuc3Rha2UDCQBmAgUGYW1vdW50BQpsb2NrQW1vdW50CQACAQkArAICCQCsAgIJAKwCAgIKUmVxdWVzdGVkIAkApAMBBQZhbW91bnQCEiwgYnV0IHN0YWtlZCBvbmx5IAkApAMBBQpsb2NrQW1vdW50BAF0CAkBBXZhbHVlAQkA7QcBBQZoZWlnaHQJdGltZXN0YW1wBAtyZWxlYXNlVGltZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQtnb3ZDb250cmFjdAkBF2tleVVzZXJHbnNidFJlbGVhc2VUaW1lAQUOdXNlckFkZHJlc3NTdHIAAAMJAGcCBQtyZWxlYXNlVGltZQUBdAkAAgEJAKwCAgI7WW91ciBnTnNidCBhcmUgdGFraW5nIHBhcnQgaW4gdm90aW5nLCBjYW5ub3QgdW5zdGFrZSB1bnRpbCAJAKQDAQULcmVsZWFzZVRpbWUED2NvbWlzc2lvbkFtb3VudAkBBWFzSW50AQkA/AcEBQxtYXRoQ29udHJhY3QCIWdldFVuc3Rha2VDb21pc3Npb25BbW91bnRSRUFET05MWQkAzAgCBQZhbW91bnQJAMwIAgUJbG9ja1N0YXJ0CQDMCAIFCGhhbGZMaWZlBQNuaWwFA25pbAQOYm9udXNHbnNidFBhcnQJAGUCBQ1jdXJyVXNlckduc2J0BQpsb2NrQW1vdW50BA9ib251c05zYnRBbW91bnQJAJcDAQkAzAgCBQZhbW91bnQJAMwIAgUOYm9udXNHbnNidFBhcnQFA25pbAQKZGVsdGFHbnNidAkAZAIFD2JvbnVzTnNidEFtb3VudAUGYW1vdW50BA0kdDAyMTYwNzIxNzc4CQELU3RhdHNSZXN1bHQECQEBLQEFBmFtb3VudAMJAAACBQZhbW91bnQFCmxvY2tBbW91bnQA////////////AQAAAwkAAAIFBmFtb3VudAUKbG9ja0Ftb3VudAD///////////8BAAAJAQEtAQUKZGVsdGFHbnNidAQMc3RhdHNFbnRyaWVzCAUNJHQwMjE2MDcyMTc3OAJfMQQLdG90YWxTdGFrZWQIBQ0kdDAyMTYwNzIxNzc4Al8yBA50b3RhbFN0YWtlZE5ldwgFDSR0MDIxNjA3MjE3NzgCXzMJAM4IAgkAzggCCQDOCAIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MJAGUCBQZhbW91bnQFD2NvbWlzc2lvbkFtb3VudAULYm9uZEFzc2V0SWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUTbmV1dHJpbm9EYW9Db250cmFjdAUPY29taXNzaW9uQW1vdW50BQtib25kQXNzZXRJZAkAzAgCCQESSGlzdG9yeVJlY29yZEVudHJ5BwIHdW5zdGFrZQULdXNlckFkZHJlc3MIBQFpDXRyYW5zYWN0aW9uSWQFCmxvY2tBbW91bnQFCWxvY2tTdGFydAkAZQIFCmxvY2tBbW91bnQFBmFtb3VudAUJbG9ja1N0YXJ0BQNuaWwJAQ1SZXdhcmRFbnRyaWVzAwcFDnVzZXJBZGRyZXNzU3RyBQ1jdXJyVXNlckduc2J0CQEPTG9ja1BhcmFtc0VudHJ5BAULdXNlckFkZHJlc3MJAGUCBQpsb2NrQW1vdW50BQZhbW91bnQFCWxvY2tTdGFydAkAZQIFDWN1cnJVc2VyR25zYnQFCmRlbHRhR25zYnQFDHN0YXRzRW50cmllcwFpAQdkZXBvc2l0AAQLdG90YWxTdGFrZWQJAQxnZXRJbnRPckVsc2UCCQEWa2V5TG9ja1BhcmFtVG90YWxHbnNidAAJAQxnZXRJbnRPckVsc2UCCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAAADCQBmAgAABQt0b3RhbFN0YWtlZAkAAgECG1RPRE86IGNhc2UgaXMgbm90IHN1cHBvcnRlZAQRZGVwb3NpdE51bUxhc3RLRVkJARFrZXlEZXBvc2l0TnVtTGFzdAAEDmRlcG9zaXROdW1MYXN0CQEMZ2V0SW50T3JFbHNlAgURZGVwb3NpdE51bUxhc3RLRVkA////////////AQQNZGVwb3NpdE51bU5ldwkAZAIFDmRlcG9zaXROdW1MYXN0AAEECXRvdGFsc0tFWQkBGGtleVN0YXRzRGVwb3NpdEFtdFRvdGFscwAECGJ5RGF5S0VZCQEXa2V5U3RhdHNEZXBvc2l0QW10QnlEYXkBCQEMdG9TdGFydE9mRGF5AQgFCWxhc3RCbG9jawl0aW1lc3RhbXAECmN1cnJUb3RhbHMJAQdwYWRMaXN0AQkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFCXRvdGFsc0tFWQURZGVmYXVsdFRvdGFsc0RBVEEFA1NFUAoBA2RlcAIDYWNjA3BtdAQGYW1vdW50CAUDcG10BmFtb3VudAQNcG10QXNzZXRJZFN0cgkA2AQBCQELdmFsdWVPckVsc2UCCAUDcG10B2Fzc2V0SWQFB1dBVkVTSUQDCQEBIQEJAQhjb250YWlucwIFEnN1cHBvcnRlZEFzc2V0c1N0cgUNcG10QXNzZXRJZFN0cgkAAgEJAKwCAgkArAICBRJzdXBwb3J0ZWRBc3NldHNTdHICESBkb2Vzbid0IGNvbnRhaW4gBQ1wbXRBc3NldElkU3RyAwkAAAIFC3RvdGFsU3Rha2VkAAAJAJYKBAkAzQgCCAUDYWNjAl8xCQEiSW5jcmVtZW50Tm90RGlzdHJpYnV0ZWRSZXdhcmRFbnRyeQIFDXBtdEFzc2V0SWRTdHIFBmFtb3VudAkAzQgCCAUDYWNjAl8yBQ1wbXRBc3NldElkU3RyCQDNCAIIBQNhY2MCXzMJALYCAQAACQDNCAIIBQNhY2MCXzQFBmFtb3VudAQQcmV3YXJkUGVyTnNidFgxOAkAvAIDCQC2AgEFBmFtb3VudAUHTVVMVFgxOAkAtgIBBQt0b3RhbFN0YWtlZAkAlgoECAUDYWNjAl8xCQDNCAIIBQNhY2MCXzIFDXBtdEFzc2V0SWRTdHIJAM0IAggFA2FjYwJfMwUQcmV3YXJkUGVyTnNidFgxOAkAzQgCCAUDYWNjAl80BQZhbW91bnQECnBtdHNSZXN1bHQKAAIkbAgFAWkIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCWCgQFA25pbAUDbmlsBQNuaWwFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEDZGVwAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCgEZcmVmcmVzaFJld2FyZFVwZGF0ZVRvdGFscwIFYWNjdW0JbmV4dEFzc2V0BAFrCAUFYWNjdW0CXzMECnN1bUxhc3RTdHIJAQxnZXRTdHJPckVsc2UCCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bUxhc3QFCW5leHRBc3NldAIBMAQDaWR4CQDPCAIIBQpwbXRzUmVzdWx0Al8yBQluZXh0QXNzZXQEA3N1bQMJAQlpc0RlZmluZWQBBQNpZHgEAWoJAQV2YWx1ZQEFA2lkeAQKc3RhdHNEZWx0YQkAkQMCCAUKcG10c1Jlc3VsdAJfNAUBagkAlAoCCQCmAwEJALcCAgkApwMBBQpzdW1MYXN0U3RyCQCRAwIIBQpwbXRzUmVzdWx0Al8zBQFqCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKY3VyclRvdGFscwkAZAIFAWsAAQUKc3RhdHNEZWx0YQkAlAoCBQpzdW1MYXN0U3RyCQCRAwIFCmN1cnJUb3RhbHMJAGQCBQFrAAEJAJUKAwkAzQgCCAUFYWNjdW0CXzEJAQtTdHJpbmdFbnRyeQIJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ1kZXBvc2l0TnVtTmV3BQluZXh0QXNzZXQIBQNzdW0CXzEJAKwCAgkArAICCAUFYWNjdW0CXzIFA1NFUAgFA3N1bQJfMgkAZAIFAWsAAQQMYXNzZXRzUmVzdWx0CgACJGwFE3N1cHBvcnRlZEFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCVCgMFA25pbAUTRGVwb3NpdFRvdGFsc1BSRUZJWAAACgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARlyZWZyZXNoUmV3YXJkVXBkYXRlVG90YWxzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYxXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA5CQEFJGYxXzICCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECCQEFJGYxXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJBAZ0b3RhbHMJAQlwYWRTdHJpbmcBCAUMYXNzZXRzUmVzdWx0Al8yCQCUCgIJAM0IAgkAzQgCCQDNCAIJAM4IAggFCnBtdHNSZXN1bHQCXzEIBQxhc3NldHNSZXN1bHQCXzEJAQxJbnRlZ2VyRW50cnkCBRFkZXBvc2l0TnVtTGFzdEtFWQUNZGVwb3NpdE51bU5ldwkBC1N0cmluZ0VudHJ5AgUJdG90YWxzS0VZBQZ0b3RhbHMJAQtTdHJpbmdFbnRyeQIFCGJ5RGF5S0VZBQZ0b3RhbHMFDWRlcG9zaXROdW1OZXcBaQEMY2xhaW1SZXdhcmRzAAkBC2NvbW1vbkNsYWltAggFAWkGY2FsbGVyBQFpAWkBGmNsYWltUmV3YXJkc0J5T3JpZ2luQ2FsbGVyAAkBC2NvbW1vbkNsYWltAggFAWkMb3JpZ2luQ2FsbGVyBQFpAWkBB3gyR25zYnQACQENY29tbW9uWDJHbnNidAIIBQFpBmNhbGxlcgUBaQFpARV4Mkduc2J0QnlPcmlnaW5DYWxsZXIACQENY29tbW9uWDJHbnNidAIIBQFpDG9yaWdpbkNhbGxlcgUBaQFpARh1bmNsYWltZWRSZXdhcmRzUkVBRE9OTFkBDnVzZXJBZGRyZXNzU3RyCgEWZm9yRWFjaEFzc2V0WmVyb1Jld2FyZAIFYWNjdW0FYXNzZXQJAKwCAgkArAICBQVhY2N1bQkAuQkCCQDMCAIFBWFzc2V0CQDMCAICATAJAMwIAgIBMAUDbmlsAgE6AgFfBBJ1bmNsYWltZWRSZXdhcmRTdHIDCQAAAgUOdXNlckFkZHJlc3NTdHICAAoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARZmb3JFYWNoQXNzZXRaZXJvUmV3YXJkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA5CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJBAt1c2VyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUOdXNlckFkZHJlc3NTdHIEDSR0MDI1ODQ5MjU5NjgJAQt2YWx1ZU9yRWxzZQIJARNnZXRVc2VyUGFyYW1zT3JVbml0AQULdXNlckFkZHJlc3MJAJYKBAYAAAAAAAAECWlzTmV3VXNlcggFDSR0MDI1ODQ5MjU5NjgCXzEEDHN0YWtlZEFtb3VudAgFDSR0MDI1ODQ5MjU5NjgCXzIEDHN0YWtpbmdTdGFydAgFDSR0MDI1ODQ5MjU5NjgCXzMECXVzZXJHbnNidAgFDSR0MDI1ODQ5MjU5NjgCXzQEDXN0YWtlZEFtb3VudFgJALYCAQUJdXNlckduc2J0BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQ51c2VyQWRkcmVzc1N0cgQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgVhY2N1bQVhc3NldAQNJHQwMjYzMTEyNjQ0OQkBCmNhbGNSZXdhcmQFBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQ0kdDAyNjMxMTI2NDQ5Al8xBAZjYWNoZWQIBQ0kdDAyNjMxMTI2NDQ5Al8yBAdkeW5hbWljCAUNJHQwMjYzMTEyNjQ0OQJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFDSR0MDI2MzExMjY0NDkCXzQEB2NsYWltZWQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBCmtleUNsYWltZWQCBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQAAAkArAICCQCsAgIFBWFjY3VtCQC5CQIJAMwIAgUFYXNzZXQJAMwIAgkApAMBBQtyZXdhcmRUb3RhbAkAzAgCCQCkAwEFB2NsYWltZWQFA25pbAIBOgIBXwoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA5CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJCQCUCgIFA25pbAkAswICBRJ1bmNsYWltZWRSZXdhcmRTdHIAAQFpARhuc2J0VW5zdGFraW5nU1lTUkVBRE9OTFkCFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQt1bnN0YWtlQW10UAQLcmVzdWx0QXJyYXkDCQAAAgUVdXNlckFkZHJlc3NTdHJPckVtcHR5AgAJAMwIAgAACQDMCAIAAAkAzAgCAAAJAMwIAgAABQNuaWwEC3VzZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkEB2NmZ0RBVEEJAQ9nZXRQYXJhbXNPckZhaWwABAtuc2J0QXNzZXRJZAgFB2NmZ0RBVEECXzEEDW1pbkxvY2tBbW91bnQIBQdjZmdEQVRBAl8yBAhoYWxmTGlmZQgFB2NmZ0RBVEECXzMECHVzZXJEQVRBCQELdmFsdWVPckVsc2UCCQETZ2V0VXNlclBhcmFtc09yVW5pdAEFC3VzZXJBZGRyZXNzCQCWCgQGAAAAAAAABAlpc05ld1VzZXIIBQh1c2VyREFUQQJfMQQMc3Rha2VkQW1vdW50CAUIdXNlckRBVEECXzIECWxvY2tTdGFydAgFCHVzZXJEQVRBAl8zBAp1bnN0YWtlQW10AwkAZgIFC3Vuc3Rha2VBbXRQBQxzdGFrZWRBbW91bnQFDHN0YWtlZEFtb3VudAULdW5zdGFrZUFtdFAED3N0YWtlZEFtb3VudE5FVwkAZQIFDHN0YWtlZEFtb3VudAUKdW5zdGFrZUFtdAQPY29taXNzaW9uQW1vdW50AwkAAAIFCnVuc3Rha2VBbXQAAAAACQEFYXNJbnQBCQD8BwQFDG1hdGhDb250cmFjdAIhZ2V0VW5zdGFrZUNvbWlzc2lvbkFtb3VudFJFQURPTkxZCQDMCAIFCnVuc3Rha2VBbXQJAMwIAgUJbG9ja1N0YXJ0CQDMCAIFCGhhbGZMaWZlBQNuaWwFA25pbAQNcmVjZWl2ZUFtb3VudAkAZQIFCnVuc3Rha2VBbXQFD2NvbWlzc2lvbkFtb3VudAkAzAgCBQxzdGFrZWRBbW91bnQJAMwIAgUPc3Rha2VkQW1vdW50TkVXCQDMCAIFDXJlY2VpdmVBbW91bnQJAMwIAgUPY29taXNzaW9uQW1vdW50BQNuaWwJAJQKAgUDbmlsBQtyZXN1bHRBcnJheQFpARZuc2J0U3Rha2luZ1NZU1JFQURPTkxZAg51c2VyQWRkcmVzc1N0cghuc2J0RGlmZgQMdG90YWxOc2J0QW10CQEMZ2V0SW50T3JFbHNlAgkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAAABAp0b3RhbEduc2J0CQEMZ2V0SW50T3JFbHNlAgkBFmtleUxvY2tQYXJhbVRvdGFsR25zYnQABQx0b3RhbE5zYnRBbXQDCQAAAgUOdXNlckFkZHJlc3NTdHICAAkAlAoCBQNuaWwJAMwIAgAACQDMCAIFDHRvdGFsTnNidEFtdAkAzAgCAAAJAMwIAgAACQDMCAIFCnRvdGFsR25zYnQFA25pbAQLdXNlckFkZHJlc3MJAQ90b0FkZHJlc3NPckZhaWwBBQ51c2VyQWRkcmVzc1N0cgQNJHQwMjgyMzkyODM2NAkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlgoEBgAAAAAAAAQJaXNOZXdVc2VyCAUNJHQwMjgyMzkyODM2NAJfMQQLdXNlck5zYnRBbXQIBQ0kdDAyODIzOTI4MzY0Al8yBAxzdGFraW5nU3RhcnQIBQ0kdDAyODIzOTI4MzY0Al8zBBBjdXJyZW50VXNlckduc2J0CAUNJHQwMjgyMzkyODM2NAJfNAQQdXNlckNvbnNlbnRUdXBsZQkBGHJlYWRVc2VyQ29uc2VudFRvWDJHbnNidAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDnVzZXJBZGRyZXNzU3RyBBl1c2VyQ29uc2VudGVkVG9YMkduc2J0S0VZCAUQdXNlckNvbnNlbnRUdXBsZQJfMQQWdXNlckNvbnNlbnRlZFRvWDJHbnNidAgFEHVzZXJDb25zZW50VHVwbGUCXzIEDmRlbHRhVXNlckduc2J0AwMJAQ1pc0JvbnVzUGVyaW9kAQUGaGVpZ2h0AwUJaXNOZXdVc2VyBgUWdXNlckNvbnNlbnRlZFRvWDJHbnNidAcJAGgCAAIFCG5zYnREaWZmBQhuc2J0RGlmZgkAlAoCBQNuaWwJAMwIAgULdXNlck5zYnRBbXQJAMwIAgUMdG90YWxOc2J0QW10CQDMCAIFDHN0YWtpbmdTdGFydAkAzAgCBRBjdXJyZW50VXNlckduc2J0CQDMCAIFCnRvdGFsR25zYnQJAMwIAgUOZGVsdGFVc2VyR25zYnQFA25pbAECdHgBBnZlcmlmeQAEE3B1YktleUFkbWluc0xpc3RTdHIJALkJAgkAzAgCAixHSmRMU2FMaXY1Szd4dWVqYWM4bWNSY0hveW8zZFByRVNydmt0RzNhNk1BUgkAzAgCAixFWXdabVVSZDVLS2FRUkJqc1ZhNmc4RFBpc0ZvUzZTb3ZSSnRGaUw1Z01IVQkAzAgCAixEdG1BZnVEZENySEs4c3BkQWVBWXpxNk1zWmVnZUQ5Z25zcnB1VFJrQ2JWQQkAzAgCAiw1V1JYRlNqd2NUYk5mS2NKczhacVhtU1NXWXNTVkpVdE12TXFaajVoSDROYwUDbmlsBQNTRVAEEHB1YktleUFkbWluc0xpc3QJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9jb250cm9sQ29udHJhY3QCDCVzX19tdWx0aXNpZwUTcHViS2V5QWRtaW5zTGlzdFN0cgUDU0VQBAVjb3VudAkAZAIJAGQCCQBkAgMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAAAAQAAAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAQkA2QQBCQCRAwIFEHB1YktleUFkbWluc0xpc3QAAQABAAADCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwACCQDZBAEJAJEDAgUQcHViS2V5QWRtaW5zTGlzdAACAAEAAAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAMJANkEAQkAkQMCBRBwdWJLZXlBZG1pbnNMaXN0AAMAAgAACQBnAgUFY291bnQAA72Hn9g=", "height": 3860104, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 28MNVd1pzQ2SYPQFqEcdY4rqFJW1C4w3THonYdSnsJWZ Next: AfpEi7zLmx7g617RrcUR1NgDLi9RSoDWJirTh9jAtTYe Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let revisionNum = "c27a8255bd9ce31a9d41b545f3fc0ad26dd2c105"
4+let revisionNum = ""
55
66 let separator = "__"
77
4848 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
4949
5050
51+func keyCfgX2GnsbtOfferHeightStart () = "%s%s__config__x2GnsbtOfferHeightStart"
52+
53+
54+func keyCfgX2GnsbtOfferHeightEnd () = "%s%s__config__x2GnsbtOfferHeightEnd"
55+
56+
5157 func keyControlAddress () = "%s%s__config__controlAddress"
5258
5359
7177 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
7278
7379 let govContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
80+
81+let neutrinoDaoContract = addressFromStringValue("3PEiiJRkV66T1NW7MoY3DGgCaxoDRCez8fL")
82+
83+let RENEW_START_HEIGHT = valueOrElse(getInteger(this, keyCfgX2GnsbtOfferHeightStart()), 0)
84+
85+let RENEW_END_HEIGHT = valueOrElse(getInteger(this, keyCfgX2GnsbtOfferHeightEnd()), 0)
7486
7587 func keyBondAsset () = "bond_asset_id"
7688
96108 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
97109
98110
111+func keyLockParamUserGnsbt (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "gNsbt"], separator)
112+
113+
114+func keyUserConsentedToX2Gnsbt (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "consentedToX2Gnsbt"], separator)
115+
116+
99117 func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
100118
101119
102120 func keyLockParamTotalAmount () = makeString(["%s%s", "stats", "activeTotalLocked"], separator)
121+
122+
123+func keyLockParamTotalGnsbt () = makeString(["%s%s", "stats", "activeTotalGnsbt"], separator)
103124
104125
105126 func keyStatsLocksCount () = makeString(["%s%s", "stats", "locksCount"], separator)
181202 func ClaimHistoryEntry (userAddress,txId,claimedRewards) = StringEntry(keyHistoryRecord("claim", userAddress, txId), formatClaimHistoryRecord(toString(userAddress), claimedRewards))
182203
183204
184-func StatsResult (totalLockedInc,lockCountInc,usersCountInc) = {
205+func StatsResult (totalLockedInc,lockCountInc,usersCountInc,totalGnsbtInc) = {
185206 let locksCount = getIntOrZero(keyStatsLocksCount())
186207 let usersCount = getIntOrZero(keyStatsUsersCount())
187208 let totalAmount = getIntOrZero(keyLockParamTotalAmount())
188209 let totalAmountNew = (totalAmount + totalLockedInc)
189- $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew)], totalAmount, totalAmountNew)
210+ let totalGnsbt = getIntOrElse(keyLockParamTotalGnsbt(), totalAmount)
211+ $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew), IntegerEntry(keyLockParamTotalGnsbt(), (totalGnsbt + totalGnsbtInc))], totalAmount, totalAmountNew)
190212 }
191213
192214
193-func LockParamsEntry (userAddress,amount,start) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
215+func LockParamsEntry (userAddress,nsbtAmount,start,gNsbtAmount) = [IntegerEntry(keyLockParamUserAmount(userAddress), nsbtAmount), IntegerEntry(keyLockParamUserGnsbt(userAddress), gNsbtAmount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
194216
195217
196218 func getParamsOrFail () = $Tuple3(fromBase58String(getStringValue(neutrinoContract, keyBondAsset())), getIntOrFail(keyMinLockAmount()), getIntOrFail(keyHalfLife()))
199221 func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
200222
201223
224+func isBonusPeriod (h) = if ((h >= RENEW_START_HEIGHT))
225+ then (RENEW_END_HEIGHT >= h)
226+ else false
227+
228+
202229 func getUserParamsOrUnit (userAddress) = if (isActiveUser(userAddress))
203- then $Tuple3(false, getIntOrFail(keyLockParamUserAmount(userAddress)), getIntOrFail(keyLockParamStartBlock(userAddress)))
230+ then {
231+ let amount = getIntOrFail(keyLockParamUserAmount(userAddress))
232+ $Tuple4(false, amount, getIntOrFail(keyLockParamStartBlock(userAddress)), getIntOrElse(keyLockParamUserGnsbt(userAddress), amount))
233+ }
204234 else unit
205235
206236
288318 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
289319 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
290320 func forEachAssetCacheUserReward (accum,asset) = {
291- let $t01030110436 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
292- let rewardTotal = $t01030110436._1
293- let cached = $t01030110436._2
294- let dynamic = $t01030110436._3
295- let rewardCachedPartKEY = $t01030110436._4
321+ let $t01148311618 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
322+ let rewardTotal = $t01148311618._1
323+ let cached = $t01148311618._2
324+ let dynamic = $t01148311618._3
325+ let rewardCachedPartKEY = $t01148311618._4
296326 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
297327 }
298328
339369 if ((size(i.payments) > 0))
340370 then throw("payments are not accepted")
341371 else {
342- let $t01337713482 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
343- let isNewUser = $t01337713482._1
344- let stakedAmount = $t01337713482._2
345- let stakingStart = $t01337713482._3
346- let stakedAmountX = toBigInt(stakedAmount)
372+ let $t01455914680 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
373+ let isNewUser = $t01455914680._1
374+ let stakedAmount = $t01455914680._2
375+ let stakingStart = $t01455914680._3
376+ let gNsbtAmount = $t01455914680._4
377+ let stakedAmountX = toBigInt(gNsbtAmount)
347378 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
348379 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
349380 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
350381 func forEachAssetCalcUnclaimedReward (accum,asset) = {
351- let $t01385313991 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
352- let rewardTotal = $t01385313991._1
353- let cached = $t01385313991._2
354- let dynamic = $t01385313991._3
355- let rewardCachedPartKEY = $t01385313991._4
382+ let $t01505015188 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
383+ let rewardTotal = $t01505015188._1
384+ let cached = $t01505015188._2
385+ let dynamic = $t01505015188._3
386+ let rewardCachedPartKEY = $t01505015188._4
356387 let claimedKEY = keyClaimed(userAddressStr, asset)
357- let $t01405114088 = accum
358- let data = $t01405114088._1
359- let claimedAmtByAsset = $t01405114088._2
388+ let $t01524815285 = accum
389+ let data = $t01524815285._1
390+ let claimedAmtByAsset = $t01524815285._2
360391 let newPart = makeString([asset, toString(rewardTotal)], ":")
361392 let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
362393 if ((0 >= rewardTotal))
364395 else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
365396 }
366397
367- let $t01454814661 = {
398+ let $t01574515858 = {
368399 let $l = supportedAssetsList
369400 let $s = size($l)
370401 let $acc0 = $Tuple2(nil, "")
378409
379410 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9)
380411 }
381- let transfers = $t01454814661._1
382- let claimedAmtByAssetResult = $t01454814661._2
412+ let transfers = $t01574515858._1
413+ let claimedAmtByAssetResult = $t01574515858._2
383414 if ((0 >= size(transfers)))
384415 then $Tuple2(nil, 0)
385416 else $Tuple2(((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1))), size(transfers))
386417 }
387418 }
419+
420+
421+func readUserConsentToX2Gnsbt (userAddress) = {
422+ let key = keyUserConsentedToX2Gnsbt(userAddress)
423+ let val = valueOrElse(getBoolean(this, key), false)
424+ $Tuple2(key, val)
425+ }
426+
427+
428+func commonX2Gnsbt (userAddress,i) = if (!(isBonusPeriod(height)))
429+ then throw("No 'Double gNSBT action' available now")
430+ else {
431+ let $t01642016481 = commonClaim(userAddress, i)
432+ let claimActions = $t01642016481._1
433+ let claimResult = $t01642016481._2
434+ let $t01648416609 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, -1, 0))
435+ let isNewUser = $t01648416609._1
436+ let lockAmount = $t01648416609._2
437+ let lockStartHeight = $t01648416609._3
438+ let currUserGnsbt = $t01648416609._4
439+ if (isNewUser)
440+ then throw("You have nothing to restake")
441+ else {
442+ let deltaUserGnsbt = currUserGnsbt
443+ let newUserGnsbt = (currUserGnsbt + deltaUserGnsbt)
444+ let userConsentTuple = readUserConsentToX2Gnsbt(userAddress)
445+ let userConsentedToX2GnsbtKEY = userConsentTuple._1
446+ let userConsentedToX2Gnsbt = userConsentTuple._2
447+ if (userConsentedToX2Gnsbt)
448+ then throw("User has already doubled its gNSBT value")
449+ else {
450+ let $t01702617112 = StatsResult(0, 0, 0, deltaUserGnsbt)
451+ let statsEntries = $t01702617112._1
452+ let totalStaked = $t01702617112._2
453+ let totalStakedNew = $t01702617112._3
454+ $Tuple2((((claimActions ++ LockParamsEntry(userAddress, lockAmount, height, newUserGnsbt)) ++ statsEntries) :+ BooleanEntry(userConsentedToX2GnsbtKEY, true)), claimResult)
455+ }
456+ }
457+ }
388458
389459
390460 @Callable(i)
395465
396466
397467 @Callable(i)
468+func constructorV2 (x2GnsbtOfferHeightStart,x2GnsbtOfferHeightEnd) = if ((i.caller != this))
469+ then throw("Permission denied")
470+ else [IntegerEntry(keyCfgX2GnsbtOfferHeightStart(), x2GnsbtOfferHeightStart), IntegerEntry(keyCfgX2GnsbtOfferHeightEnd(), x2GnsbtOfferHeightEnd)]
471+
472+
473+
474+@Callable(i)
398475 func stake () = {
399- let $t01551215574 = getParamsOrFail()
400- let bondAssetId = $t01551215574._1
401- let minLockAmount = $t01551215574._2
402- let halfLife = $t01551215574._3
476+ let $t01821818280 = getParamsOrFail()
477+ let bondAssetId = $t01821818280._1
478+ let minLockAmount = $t01821818280._2
479+ let halfLife = $t01821818280._3
403480 if ((size(i.payments) != 1))
404481 then throw("Invalid payments size")
405482 else {
412489 else {
413490 let userAddress = i.caller
414491 let userAddressStr = toString(i.caller)
415- let $t01611616223 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
416- let isNewUser = $t01611616223._1
417- let lockAmount = $t01611616223._2
418- let lockStartHeight = $t01611616223._3
492+ let $t01882218947 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, -1, 0))
493+ let isNewUser = $t01882218947._1
494+ let lockAmount = $t01882218947._2
495+ let lockStartHeight = $t01882218947._3
496+ let currUserGnsbt = $t01882218947._4
419497 let mergedAmount = if (isNewUser)
420498 then amount
421499 else (amount + lockAmount)
425503 if ((minLockAmount > mergedAmount))
426504 then throw(("Min lock amount is " + toString(minLockAmount)))
427505 else {
428- let $t01658416686 = StatsResult(amount, 1, if (isNewUser)
506+ let userConsentTuple = readUserConsentToX2Gnsbt(userAddress)
507+ let userConsentedToX2GnsbtKEY = userConsentTuple._1
508+ let userConsentedToX2Gnsbt = userConsentTuple._2
509+ let deltaUserGnsbt = if (if (isBonusPeriod(height))
510+ then if (isNewUser)
511+ then true
512+ else userConsentedToX2Gnsbt
513+ else false)
514+ then (2 * amount)
515+ else amount
516+ let x2GnsbtConsentEntry = if (isNewUser)
517+ then [BooleanEntry(userConsentedToX2GnsbtKEY, true)]
518+ else nil
519+ let $t01995120069 = StatsResult(amount, 1, if (isNewUser)
429520 then 1
430- else 0)
431- let statsEntries = $t01658416686._1
432- let totalStaked = $t01658416686._2
433- let totalStakedNew = $t01658416686._3
434- ((([HistoryRecordEntry("stake", userAddress, i.transactionId, lockAmount, lockStartHeight, mergedAmount, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, mergedAmount, mergedStartHeight)) ++ statsEntries)
521+ else 0, deltaUserGnsbt)
522+ let statsEntries = $t01995120069._1
523+ let totalStaked = $t01995120069._2
524+ let totalStakedNew = $t01995120069._3
525+ (((([HistoryRecordEntry("stake", userAddress, i.transactionId, lockAmount, lockStartHeight, mergedAmount, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, currUserGnsbt)) ++ LockParamsEntry(userAddress, mergedAmount, mergedStartHeight, (currUserGnsbt + deltaUserGnsbt))) ++ statsEntries) ++ x2GnsbtConsentEntry)
435526 }
436527 }
437528 }
445536 else {
446537 let userAddress = i.caller
447538 let userAddressStr = toString(userAddress)
448- let $t01717217234 = getParamsOrFail()
449- let bondAssetId = $t01717217234._1
450- let minLockAmount = $t01717217234._2
451- let halfLife = $t01717217234._3
452- let $t01723717311 = getUserParamsOrFail(userAddress)
453- let isNewUser = $t01723717311._1
454- let lockAmount = $t01723717311._2
455- let lockStart = $t01723717311._3
539+ let $t02061520677 = getParamsOrFail()
540+ let bondAssetId = $t02061520677._1
541+ let minLockAmount = $t02061520677._2
542+ let halfLife = $t02061520677._3
543+ let $t02068020769 = getUserParamsOrFail(userAddress)
544+ let isNewUser = $t02068020769._1
545+ let lockAmount = $t02068020769._2
546+ let lockStart = $t02068020769._3
547+ let currUserGnsbt = $t02068020769._4
456548 if ((0 >= lockAmount))
457549 then throw("Nothing to unstake")
458550 else if ((amount > lockAmount))
464556 then throw(("Your gNsbt are taking part in voting, cannot unstake until " + toString(releaseTime)))
465557 else {
466558 let comissionAmount = asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [amount, lockStart, halfLife], nil))
467- let $t01795218106 = StatsResult(-(amount), if ((amount == lockAmount))
559+ let bonusGnsbtPart = (currUserGnsbt - lockAmount)
560+ let bonusNsbtAmount = min([amount, bonusGnsbtPart])
561+ let deltaGnsbt = (bonusNsbtAmount + amount)
562+ let $t02160721778 = StatsResult(-(amount), if ((amount == lockAmount))
468563 then -1
469564 else 0, if ((amount == lockAmount))
470565 then -1
471- else 0)
472- let statsEntries = $t01795218106._1
473- let totalStaked = $t01795218106._2
474- let totalStakedNew = $t01795218106._3
475- ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(auctionContract, comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
566+ else 0, -(deltaGnsbt))
567+ let statsEntries = $t02160721778._1
568+ let totalStaked = $t02160721778._2
569+ let totalStakedNew = $t02160721778._3
570+ ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(neutrinoDaoContract, comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, currUserGnsbt)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart, (currUserGnsbt - deltaGnsbt))) ++ statsEntries)
476571 }
477572 }
478573 }
481576
482577 @Callable(i)
483578 func deposit () = {
484- let totalStaked = getIntOrElse(keyLockParamTotalAmount(), 0)
579+ let totalStaked = getIntOrElse(keyLockParamTotalGnsbt(), getIntOrElse(keyLockParamTotalAmount(), 0))
485580 if ((0 > totalStaked))
486581 then throw("TODO: case is not supported")
487582 else {
564659
565660
566661 @Callable(i)
662+func x2Gnsbt () = commonX2Gnsbt(i.caller, i)
663+
664+
665+
666+@Callable(i)
667+func x2GnsbtByOriginCaller () = commonX2Gnsbt(i.originCaller, i)
668+
669+
670+
671+@Callable(i)
567672 func unclaimedRewardsREADONLY (userAddressStr) = {
568673 func forEachAssetZeroReward (accum,asset) = ((accum + makeString([asset, "0", "0"], ":")) + "_")
569674
584689 }
585690 else {
586691 let userAddress = addressFromStringValue(userAddressStr)
587- let $t02195522060 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
588- let isNewUser = $t02195522060._1
589- let stakedAmount = $t02195522060._2
590- let stakingStart = $t02195522060._3
591- let stakedAmountX = toBigInt(stakedAmount)
692+ let $t02584925968 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
693+ let isNewUser = $t02584925968._1
694+ let stakedAmount = $t02584925968._2
695+ let stakingStart = $t02584925968._3
696+ let userGnsbt = $t02584925968._4
697+ let stakedAmountX = toBigInt(userGnsbt)
592698 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
593699 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
594700 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
595701 func forEachAssetCalcUnclaimedReward (accum,asset) = {
596- let $t02240622544 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
597- let rewardTotal = $t02240622544._1
598- let cached = $t02240622544._2
599- let dynamic = $t02240622544._3
600- let rewardCachedPartKEY = $t02240622544._4
702+ let $t02631126449 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
703+ let rewardTotal = $t02631126449._1
704+ let cached = $t02631126449._2
705+ let dynamic = $t02631126449._3
706+ let rewardCachedPartKEY = $t02631126449._4
601707 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
602708 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
603709 }
630736 let nsbtAssetId = cfgDATA._1
631737 let minLockAmount = cfgDATA._2
632738 let halfLife = cfgDATA._3
633- let userDATA = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
739+ let userDATA = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
634740 let isNewUser = userDATA._1
635741 let stakedAmount = userDATA._2
636742 let lockStart = userDATA._3
652758 @Callable(i)
653759 func nsbtStakingSYSREADONLY (userAddressStr,nsbtDiff) = {
654760 let totalNsbtAmt = getIntOrElse(keyLockParamTotalAmount(), 0)
761+ let totalGnsbt = getIntOrElse(keyLockParamTotalGnsbt(), totalNsbtAmt)
655762 if ((userAddressStr == ""))
656- then $Tuple2(nil, [0, totalNsbtAmt, 0])
763+ then $Tuple2(nil, [0, totalNsbtAmt, 0, 0, totalGnsbt])
657764 else {
658765 let userAddress = toAddressOrFail(userAddressStr)
659- let $t02422224326 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
660- let isNewUser = $t02422224326._1
661- let userNsbtAmt = $t02422224326._2
662- let stakingStart = $t02422224326._3
663- $Tuple2(nil, [userNsbtAmt, totalNsbtAmt, stakingStart])
766+ let $t02823928364 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
767+ let isNewUser = $t02823928364._1
768+ let userNsbtAmt = $t02823928364._2
769+ let stakingStart = $t02823928364._3
770+ let currentUserGnsbt = $t02823928364._4
771+ let userConsentTuple = readUserConsentToX2Gnsbt(addressFromStringValue(userAddressStr))
772+ let userConsentedToX2GnsbtKEY = userConsentTuple._1
773+ let userConsentedToX2Gnsbt = userConsentTuple._2
774+ let deltaUserGnsbt = if (if (isBonusPeriod(height))
775+ then if (isNewUser)
776+ then true
777+ else userConsentedToX2Gnsbt
778+ else false)
779+ then (2 * nsbtDiff)
780+ else nsbtDiff
781+ $Tuple2(nil, [userNsbtAmt, totalNsbtAmt, stakingStart, currentUserGnsbt, totalGnsbt, deltaUserGnsbt])
664782 }
665783 }
666784
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let revisionNum = "c27a8255bd9ce31a9d41b545f3fc0ad26dd2c105"
4+let revisionNum = ""
55
66 let separator = "__"
77
88 let SEP = "__"
99
1010 let MULT6 = 1000000
1111
1212 let MULT8 = 100000000
1313
1414 let MULTX6 = toBigInt(MULT6)
1515
1616 let MULTX8 = toBigInt(MULT8)
1717
1818 let MULTX18 = toBigInt(1000000000000000000)
1919
2020 let WAVESIDSTR = "WAVES"
2121
2222 let WAVESID = fromBase58String(WAVESIDSTR)
2323
2424 let DAYMILLIS = 86400000
2525
2626 let MAXBASKET = 9
2727
2828 let IdxControlCfgNeutrinoDapp = 1
2929
3030 let IdxControlCfgAuctionDapp = 2
3131
3232 let IdxControlCfgRpdDapp = 3
3333
3434 let IdxControlCfgMathDapp = 4
3535
3636 let IdxControlCfgLiquidationDapp = 5
3737
3838 let IdxControlCfgRestDapp = 6
3939
4040 let IdxControlCfgNodeRegistryDapp = 7
4141
4242 let IdxControlCfgNsbtStakingDapp = 8
4343
4444 let IdxControlCfgMediatorDapp = 9
4545
4646 let IdxControlCfgGovernanceDapp = 13
4747
4848 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
4949
5050
51+func keyCfgX2GnsbtOfferHeightStart () = "%s%s__config__x2GnsbtOfferHeightStart"
52+
53+
54+func keyCfgX2GnsbtOfferHeightEnd () = "%s%s__config__x2GnsbtOfferHeightEnd"
55+
56+
5157 func keyControlAddress () = "%s%s__config__controlAddress"
5258
5359
5460 func keyControlCfg () = "%s__controlConfig"
5561
5662
5763 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
5864
5965
6066 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
6167
6268
6369 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
6470
6571 let controlCfg = readControlCfgOrFail(controlContract)
6672
6773 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
6874
6975 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
7076
7177 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
7278
7379 let govContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
80+
81+let neutrinoDaoContract = addressFromStringValue("3PEiiJRkV66T1NW7MoY3DGgCaxoDRCez8fL")
82+
83+let RENEW_START_HEIGHT = valueOrElse(getInteger(this, keyCfgX2GnsbtOfferHeightStart()), 0)
84+
85+let RENEW_END_HEIGHT = valueOrElse(getInteger(this, keyCfgX2GnsbtOfferHeightEnd()), 0)
7486
7587 func keyBondAsset () = "bond_asset_id"
7688
7789
7890 func keyUserGnsbtReleaseTime (userAddr) = ("%s%s_userGnsbtReleaseTime__" + userAddr)
7991
8092
8193 func keyNeutrinoContractAddress () = "%s__neutrinoContractAddress"
8294
8395
8496 func keyMathContractAddress () = "%s__mathContract"
8597
8698
8799 func keyMinLockAmount () = "%s__minLockAmount"
88100
89101
90102 func keyHalfLife () = "%s__halfLife"
91103
92104
93105 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "amount"], separator)
94106
95107
96108 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
97109
98110
111+func keyLockParamUserGnsbt (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "gNsbt"], separator)
112+
113+
114+func keyUserConsentedToX2Gnsbt (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "consentedToX2Gnsbt"], separator)
115+
116+
99117 func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
100118
101119
102120 func keyLockParamTotalAmount () = makeString(["%s%s", "stats", "activeTotalLocked"], separator)
121+
122+
123+func keyLockParamTotalGnsbt () = makeString(["%s%s", "stats", "activeTotalGnsbt"], separator)
103124
104125
105126 func keyStatsLocksCount () = makeString(["%s%s", "stats", "locksCount"], separator)
106127
107128
108129 func keyStatsUsersCount () = makeString(["%s%s", "stats", "activeUsersCount"], separator)
109130
110131
111132 func keyStatsDepositAmtByDay (timestamp) = makeString(["%s%s%d", "stats", "depositAmtByDay", toString(timestamp)], separator)
112133
113134
114135 func keyStatsDepositAmtTotals () = makeString(["%s%s%d", "stats", "depositAmtTotals"], separator)
115136
116137
117138 func keyNextPeriod () = "%s__nextPeriod"
118139
119140
120141 func keySupportedRewardAssets () = "supportedRewardAssets"
121142
122143
123144 func keyDepositNumLast () = makeString(["%s%s%s", "dep", "lastNum"], separator)
124145
125146
126147 func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s%s", "userRwdFromDepNum", userAddress], separator)
127148
128149
129150 func keyRewardPerNsbtSumAt (depositNum,tkn) = makeString(["%s%d", "rwdPerNsbtSumByDepNum", toString(depositNum), tkn], separator)
130151
131152
132153 func keyReward (userAddress,tkn) = makeString(["%s%s%s", "rwd", userAddress, tkn], separator)
133154
134155
135156 func keyClaimed (userAddress,tkn) = makeString(["%s%s%s", "clm", userAddress, tkn], separator)
136157
137158
138159 func keyNotDistributedReward (tkn) = makeString(["%s%s", "notDistributed", tkn], separator)
139160
140161
141162 func toX18 (origVal,origMult) = fraction(toBigInt(origVal), MULTX18, origMult)
142163
143164
144165 func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
145166
146167
147168 func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
148169
149170
150171 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
151172
152173
153174 func getStrOrElse (key,defaultVal) = valueOrElse(getString(this, key), defaultVal)
154175
155176
156177 func toAddressOrFail (addressStr) = valueOrErrorMessage(addressFromString(addressStr), ("couldn't parse passed addressStr=" + addressStr))
157178
158179
159180 func toAssetVect (assetStr) = if ((assetStr == WAVESIDSTR))
160181 then unit
161182 else fromBase58String(assetStr)
162183
163184
164185 func asInt (val) = match val {
165186 case valInt: Int =>
166187 valInt
167188 case _ =>
168189 throw("fail to cast into Int")
169190 }
170191
171192
172193 func formatHistoryRecord (oldAmount,oldStart,newAmount,newStart) = makeString(["%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(oldAmount), toString(oldStart), toString(newAmount), toString(newStart)], separator)
173194
174195
175196 func formatClaimHistoryRecord (user,claimedRewards) = makeString(["%s%d%d%s", user, toString(lastBlock.height), toString(lastBlock.timestamp), claimedRewards], separator)
176197
177198
178199 func HistoryRecordEntry (type,userAddress,txId,oldAmount,oldStart,newAmount,newStart) = StringEntry(keyHistoryRecord(type, userAddress, txId), formatHistoryRecord(oldAmount, oldStart, newAmount, newStart))
179200
180201
181202 func ClaimHistoryEntry (userAddress,txId,claimedRewards) = StringEntry(keyHistoryRecord("claim", userAddress, txId), formatClaimHistoryRecord(toString(userAddress), claimedRewards))
182203
183204
184-func StatsResult (totalLockedInc,lockCountInc,usersCountInc) = {
205+func StatsResult (totalLockedInc,lockCountInc,usersCountInc,totalGnsbtInc) = {
185206 let locksCount = getIntOrZero(keyStatsLocksCount())
186207 let usersCount = getIntOrZero(keyStatsUsersCount())
187208 let totalAmount = getIntOrZero(keyLockParamTotalAmount())
188209 let totalAmountNew = (totalAmount + totalLockedInc)
189- $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew)], totalAmount, totalAmountNew)
210+ let totalGnsbt = getIntOrElse(keyLockParamTotalGnsbt(), totalAmount)
211+ $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew), IntegerEntry(keyLockParamTotalGnsbt(), (totalGnsbt + totalGnsbtInc))], totalAmount, totalAmountNew)
190212 }
191213
192214
193-func LockParamsEntry (userAddress,amount,start) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
215+func LockParamsEntry (userAddress,nsbtAmount,start,gNsbtAmount) = [IntegerEntry(keyLockParamUserAmount(userAddress), nsbtAmount), IntegerEntry(keyLockParamUserGnsbt(userAddress), gNsbtAmount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
194216
195217
196218 func getParamsOrFail () = $Tuple3(fromBase58String(getStringValue(neutrinoContract, keyBondAsset())), getIntOrFail(keyMinLockAmount()), getIntOrFail(keyHalfLife()))
197219
198220
199221 func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
200222
201223
224+func isBonusPeriod (h) = if ((h >= RENEW_START_HEIGHT))
225+ then (RENEW_END_HEIGHT >= h)
226+ else false
227+
228+
202229 func getUserParamsOrUnit (userAddress) = if (isActiveUser(userAddress))
203- then $Tuple3(false, getIntOrFail(keyLockParamUserAmount(userAddress)), getIntOrFail(keyLockParamStartBlock(userAddress)))
230+ then {
231+ let amount = getIntOrFail(keyLockParamUserAmount(userAddress))
232+ $Tuple4(false, amount, getIntOrFail(keyLockParamStartBlock(userAddress)), getIntOrElse(keyLockParamUserGnsbt(userAddress), amount))
233+ }
204234 else unit
205235
206236
207237 func getUserParamsOrFail (userAddress) = valueOrErrorMessage(getUserParamsOrUnit(userAddress), (("User " + toString(userAddress)) + " is not defined"))
208238
209239
210240 let supportedAssetsStr = getStrOrElse(keySupportedRewardAssets(), "")
211241
212242 let supportedAssetsList = split(supportedAssetsStr, "_")
213243
214244 func calcReward (userAddress,assetId,stakedAmountX,depositNumUser,depositNumLast) = {
215245 let rewardPerNsbtSumLastKEY = keyRewardPerNsbtSumAt(depositNumLast, assetId)
216246 let sumLastX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, assetId), "0"))
217247 let sumUserX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumUser, assetId), "0"))
218248 let rewardDynamicPart = toInt(fraction((sumLastX18 - sumUserX18), stakedAmountX, MULTX18))
219249 let rewardCachedPartKEY = keyReward(userAddress, assetId)
220250 let rewardCachedPart = getIntOrElse(rewardCachedPartKEY, 0)
221251 $Tuple4((rewardCachedPart + rewardDynamicPart), rewardCachedPart, rewardDynamicPart, rewardCachedPartKEY)
222252 }
223253
224254
225255 func toStartOfDay (timestamp) = ((timestamp / DAYMILLIS) * DAYMILLIS)
226256
227257
228258 func findElementPosition (src,element,sep) = {
229259 let elementStart = valueOrErrorMessage(indexOf(src, element), ((("there is no substring " + element) + " in ") + src))
230260 if ((elementStart == 0))
231261 then 0
232262 else {
233263 let left = take(src, elementStart)
234264 (size(split(left, sep)) - 1)
235265 }
236266 }
237267
238268
239269 let DepositTotalsPREFIX = "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
240270
241271 let defaultTotalsDATA = (DepositTotalsPREFIX + "__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0")
242272
243273 func padList (in) = {
244274 let currSize = (size(in) - 1)
245275 func listPadder (acc,idx) = if ((currSize > idx))
246276 then acc
247277 else (acc :+ "0")
248278
249279 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
250280 let $s = size($l)
251281 let $acc0 = in
252282 func $f0_1 ($a,$i) = if (($i >= $s))
253283 then $a
254284 else listPadder($a, $l[$i])
255285
256286 func $f0_2 ($a,$i) = if (($i >= $s))
257287 then $a
258288 else throw("List size exceeds 18")
259289
260290 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18)
261291 }
262292
263293
264294 func padString (in) = {
265295 let currSize = (size(split_4C(in, SEP)) - 1)
266296 func strPadder (acc,idx) = if ((currSize > idx))
267297 then acc
268298 else (acc + "__0")
269299
270300 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
271301 let $s = size($l)
272302 let $acc0 = in
273303 func $f0_1 ($a,$i) = if (($i >= $s))
274304 then $a
275305 else strPadder($a, $l[$i])
276306
277307 func $f0_2 ($a,$i) = if (($i >= $s))
278308 then $a
279309 else throw("List size exceeds 18")
280310
281311 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18)
282312 }
283313
284314
285315 func RewardEntries (isNewUser,userAddress,stakedAmount) = {
286316 let stakedAmountX = toBigInt(stakedAmount)
287317 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddress)
288318 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
289319 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
290320 func forEachAssetCacheUserReward (accum,asset) = {
291- let $t01030110436 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
292- let rewardTotal = $t01030110436._1
293- let cached = $t01030110436._2
294- let dynamic = $t01030110436._3
295- let rewardCachedPartKEY = $t01030110436._4
321+ let $t01148311618 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
322+ let rewardTotal = $t01148311618._1
323+ let cached = $t01148311618._2
324+ let dynamic = $t01148311618._3
325+ let rewardCachedPartKEY = $t01148311618._4
296326 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
297327 }
298328
299329 if (if ((depositNumLast == -1))
300330 then (depositNumUser == -1)
301331 else false)
302332 then nil
303333 else if (if ((depositNumLast == -1))
304334 then (depositNumUser > -1)
305335 else false)
306336 then throw("invalid depositNumLast and depositNumUser state")
307337 else if (if ((depositNumLast > -1))
308338 then (depositNumUser >= -1)
309339 else false)
310340 then if (isNewUser)
311341 then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
312342 else ({
313343 let $l = supportedAssetsList
314344 let $s = size($l)
315345 let $acc0 = nil
316346 func $f0_1 ($a,$i) = if (($i >= $s))
317347 then $a
318348 else forEachAssetCacheUserReward($a, $l[$i])
319349
320350 func $f0_2 ($a,$i) = if (($i >= $s))
321351 then $a
322352 else throw("List size exceeds 9")
323353
324354 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9)
325355 } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
326356 else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
327357 }
328358
329359
330360 func IncrementNotDistributedRewardEntry (tkn,amountInc) = {
331361 let notDistributedRewardKEY = keyNotDistributedReward(tkn)
332362 let notDistributedReward = getIntOrElse(notDistributedRewardKEY, 0)
333363 IntegerEntry(notDistributedRewardKEY, (notDistributedReward + amountInc))
334364 }
335365
336366
337367 func commonClaim (userAddress,i) = {
338368 let userAddressStr = toString(userAddress)
339369 if ((size(i.payments) > 0))
340370 then throw("payments are not accepted")
341371 else {
342- let $t01337713482 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
343- let isNewUser = $t01337713482._1
344- let stakedAmount = $t01337713482._2
345- let stakingStart = $t01337713482._3
346- let stakedAmountX = toBigInt(stakedAmount)
372+ let $t01455914680 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
373+ let isNewUser = $t01455914680._1
374+ let stakedAmount = $t01455914680._2
375+ let stakingStart = $t01455914680._3
376+ let gNsbtAmount = $t01455914680._4
377+ let stakedAmountX = toBigInt(gNsbtAmount)
347378 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
348379 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
349380 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
350381 func forEachAssetCalcUnclaimedReward (accum,asset) = {
351- let $t01385313991 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
352- let rewardTotal = $t01385313991._1
353- let cached = $t01385313991._2
354- let dynamic = $t01385313991._3
355- let rewardCachedPartKEY = $t01385313991._4
382+ let $t01505015188 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
383+ let rewardTotal = $t01505015188._1
384+ let cached = $t01505015188._2
385+ let dynamic = $t01505015188._3
386+ let rewardCachedPartKEY = $t01505015188._4
356387 let claimedKEY = keyClaimed(userAddressStr, asset)
357- let $t01405114088 = accum
358- let data = $t01405114088._1
359- let claimedAmtByAsset = $t01405114088._2
388+ let $t01524815285 = accum
389+ let data = $t01524815285._1
390+ let claimedAmtByAsset = $t01524815285._2
360391 let newPart = makeString([asset, toString(rewardTotal)], ":")
361392 let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
362393 if ((0 >= rewardTotal))
363394 then $Tuple2(data, claimedAmtByAssetNew)
364395 else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
365396 }
366397
367- let $t01454814661 = {
398+ let $t01574515858 = {
368399 let $l = supportedAssetsList
369400 let $s = size($l)
370401 let $acc0 = $Tuple2(nil, "")
371402 func $f0_1 ($a,$i) = if (($i >= $s))
372403 then $a
373404 else forEachAssetCalcUnclaimedReward($a, $l[$i])
374405
375406 func $f0_2 ($a,$i) = if (($i >= $s))
376407 then $a
377408 else throw("List size exceeds 9")
378409
379410 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9)
380411 }
381- let transfers = $t01454814661._1
382- let claimedAmtByAssetResult = $t01454814661._2
412+ let transfers = $t01574515858._1
413+ let claimedAmtByAssetResult = $t01574515858._2
383414 if ((0 >= size(transfers)))
384415 then $Tuple2(nil, 0)
385416 else $Tuple2(((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1))), size(transfers))
386417 }
387418 }
419+
420+
421+func readUserConsentToX2Gnsbt (userAddress) = {
422+ let key = keyUserConsentedToX2Gnsbt(userAddress)
423+ let val = valueOrElse(getBoolean(this, key), false)
424+ $Tuple2(key, val)
425+ }
426+
427+
428+func commonX2Gnsbt (userAddress,i) = if (!(isBonusPeriod(height)))
429+ then throw("No 'Double gNSBT action' available now")
430+ else {
431+ let $t01642016481 = commonClaim(userAddress, i)
432+ let claimActions = $t01642016481._1
433+ let claimResult = $t01642016481._2
434+ let $t01648416609 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, -1, 0))
435+ let isNewUser = $t01648416609._1
436+ let lockAmount = $t01648416609._2
437+ let lockStartHeight = $t01648416609._3
438+ let currUserGnsbt = $t01648416609._4
439+ if (isNewUser)
440+ then throw("You have nothing to restake")
441+ else {
442+ let deltaUserGnsbt = currUserGnsbt
443+ let newUserGnsbt = (currUserGnsbt + deltaUserGnsbt)
444+ let userConsentTuple = readUserConsentToX2Gnsbt(userAddress)
445+ let userConsentedToX2GnsbtKEY = userConsentTuple._1
446+ let userConsentedToX2Gnsbt = userConsentTuple._2
447+ if (userConsentedToX2Gnsbt)
448+ then throw("User has already doubled its gNSBT value")
449+ else {
450+ let $t01702617112 = StatsResult(0, 0, 0, deltaUserGnsbt)
451+ let statsEntries = $t01702617112._1
452+ let totalStaked = $t01702617112._2
453+ let totalStakedNew = $t01702617112._3
454+ $Tuple2((((claimActions ++ LockParamsEntry(userAddress, lockAmount, height, newUserGnsbt)) ++ statsEntries) :+ BooleanEntry(userConsentedToX2GnsbtKEY, true)), claimResult)
455+ }
456+ }
457+ }
388458
389459
390460 @Callable(i)
391461 func constructorV1 (neutrinoContractAddress,mathContractAddress,minLockAmount,halfLife,supportedRewardAssets) = if ((i.caller != this))
392462 then throw("Permission denied")
393463 else [StringEntry(keyNeutrinoContractAddress(), neutrinoContractAddress), StringEntry(keyMathContractAddress(), mathContractAddress), IntegerEntry(keyMinLockAmount(), minLockAmount), IntegerEntry(keyHalfLife(), halfLife), StringEntry(keySupportedRewardAssets(), supportedRewardAssets)]
394464
395465
396466
397467 @Callable(i)
468+func constructorV2 (x2GnsbtOfferHeightStart,x2GnsbtOfferHeightEnd) = if ((i.caller != this))
469+ then throw("Permission denied")
470+ else [IntegerEntry(keyCfgX2GnsbtOfferHeightStart(), x2GnsbtOfferHeightStart), IntegerEntry(keyCfgX2GnsbtOfferHeightEnd(), x2GnsbtOfferHeightEnd)]
471+
472+
473+
474+@Callable(i)
398475 func stake () = {
399- let $t01551215574 = getParamsOrFail()
400- let bondAssetId = $t01551215574._1
401- let minLockAmount = $t01551215574._2
402- let halfLife = $t01551215574._3
476+ let $t01821818280 = getParamsOrFail()
477+ let bondAssetId = $t01821818280._1
478+ let minLockAmount = $t01821818280._2
479+ let halfLife = $t01821818280._3
403480 if ((size(i.payments) != 1))
404481 then throw("Invalid payments size")
405482 else {
406483 let payment = i.payments[0]
407484 let amount = payment.amount
408485 let invalidAssetMessage = (("Invalid asset. " + toBase58String(bondAssetId)) + " is expected")
409486 let assetId = valueOrErrorMessage(payment.assetId, invalidAssetMessage)
410487 if ((assetId != bondAssetId))
411488 then throw(invalidAssetMessage)
412489 else {
413490 let userAddress = i.caller
414491 let userAddressStr = toString(i.caller)
415- let $t01611616223 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
416- let isNewUser = $t01611616223._1
417- let lockAmount = $t01611616223._2
418- let lockStartHeight = $t01611616223._3
492+ let $t01882218947 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, -1, 0))
493+ let isNewUser = $t01882218947._1
494+ let lockAmount = $t01882218947._2
495+ let lockStartHeight = $t01882218947._3
496+ let currUserGnsbt = $t01882218947._4
419497 let mergedAmount = if (isNewUser)
420498 then amount
421499 else (amount + lockAmount)
422500 let mergedStartHeight = if (isNewUser)
423501 then height
424502 else asInt(invoke(mathContract, "mergeStakesREADONLY", [amount, height, lockAmount, lockStartHeight, halfLife], nil))
425503 if ((minLockAmount > mergedAmount))
426504 then throw(("Min lock amount is " + toString(minLockAmount)))
427505 else {
428- let $t01658416686 = StatsResult(amount, 1, if (isNewUser)
506+ let userConsentTuple = readUserConsentToX2Gnsbt(userAddress)
507+ let userConsentedToX2GnsbtKEY = userConsentTuple._1
508+ let userConsentedToX2Gnsbt = userConsentTuple._2
509+ let deltaUserGnsbt = if (if (isBonusPeriod(height))
510+ then if (isNewUser)
511+ then true
512+ else userConsentedToX2Gnsbt
513+ else false)
514+ then (2 * amount)
515+ else amount
516+ let x2GnsbtConsentEntry = if (isNewUser)
517+ then [BooleanEntry(userConsentedToX2GnsbtKEY, true)]
518+ else nil
519+ let $t01995120069 = StatsResult(amount, 1, if (isNewUser)
429520 then 1
430- else 0)
431- let statsEntries = $t01658416686._1
432- let totalStaked = $t01658416686._2
433- let totalStakedNew = $t01658416686._3
434- ((([HistoryRecordEntry("stake", userAddress, i.transactionId, lockAmount, lockStartHeight, mergedAmount, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, mergedAmount, mergedStartHeight)) ++ statsEntries)
521+ else 0, deltaUserGnsbt)
522+ let statsEntries = $t01995120069._1
523+ let totalStaked = $t01995120069._2
524+ let totalStakedNew = $t01995120069._3
525+ (((([HistoryRecordEntry("stake", userAddress, i.transactionId, lockAmount, lockStartHeight, mergedAmount, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, currUserGnsbt)) ++ LockParamsEntry(userAddress, mergedAmount, mergedStartHeight, (currUserGnsbt + deltaUserGnsbt))) ++ statsEntries) ++ x2GnsbtConsentEntry)
435526 }
436527 }
437528 }
438529 }
439530
440531
441532
442533 @Callable(i)
443534 func unstake (amount) = if ((size(i.payments) != 0))
444535 then throw("unstake doesn't require any payment")
445536 else {
446537 let userAddress = i.caller
447538 let userAddressStr = toString(userAddress)
448- let $t01717217234 = getParamsOrFail()
449- let bondAssetId = $t01717217234._1
450- let minLockAmount = $t01717217234._2
451- let halfLife = $t01717217234._3
452- let $t01723717311 = getUserParamsOrFail(userAddress)
453- let isNewUser = $t01723717311._1
454- let lockAmount = $t01723717311._2
455- let lockStart = $t01723717311._3
539+ let $t02061520677 = getParamsOrFail()
540+ let bondAssetId = $t02061520677._1
541+ let minLockAmount = $t02061520677._2
542+ let halfLife = $t02061520677._3
543+ let $t02068020769 = getUserParamsOrFail(userAddress)
544+ let isNewUser = $t02068020769._1
545+ let lockAmount = $t02068020769._2
546+ let lockStart = $t02068020769._3
547+ let currUserGnsbt = $t02068020769._4
456548 if ((0 >= lockAmount))
457549 then throw("Nothing to unstake")
458550 else if ((amount > lockAmount))
459551 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(lockAmount)))
460552 else {
461553 let t = value(blockInfoByHeight(height)).timestamp
462554 let releaseTime = valueOrElse(getInteger(govContract, keyUserGnsbtReleaseTime(userAddressStr)), 0)
463555 if ((releaseTime >= t))
464556 then throw(("Your gNsbt are taking part in voting, cannot unstake until " + toString(releaseTime)))
465557 else {
466558 let comissionAmount = asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [amount, lockStart, halfLife], nil))
467- let $t01795218106 = StatsResult(-(amount), if ((amount == lockAmount))
559+ let bonusGnsbtPart = (currUserGnsbt - lockAmount)
560+ let bonusNsbtAmount = min([amount, bonusGnsbtPart])
561+ let deltaGnsbt = (bonusNsbtAmount + amount)
562+ let $t02160721778 = StatsResult(-(amount), if ((amount == lockAmount))
468563 then -1
469564 else 0, if ((amount == lockAmount))
470565 then -1
471- else 0)
472- let statsEntries = $t01795218106._1
473- let totalStaked = $t01795218106._2
474- let totalStakedNew = $t01795218106._3
475- ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(auctionContract, comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
566+ else 0, -(deltaGnsbt))
567+ let statsEntries = $t02160721778._1
568+ let totalStaked = $t02160721778._2
569+ let totalStakedNew = $t02160721778._3
570+ ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(neutrinoDaoContract, comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, currUserGnsbt)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart, (currUserGnsbt - deltaGnsbt))) ++ statsEntries)
476571 }
477572 }
478573 }
479574
480575
481576
482577 @Callable(i)
483578 func deposit () = {
484- let totalStaked = getIntOrElse(keyLockParamTotalAmount(), 0)
579+ let totalStaked = getIntOrElse(keyLockParamTotalGnsbt(), getIntOrElse(keyLockParamTotalAmount(), 0))
485580 if ((0 > totalStaked))
486581 then throw("TODO: case is not supported")
487582 else {
488583 let depositNumLastKEY = keyDepositNumLast()
489584 let depositNumLast = getIntOrElse(depositNumLastKEY, -1)
490585 let depositNumNew = (depositNumLast + 1)
491586 let totalsKEY = keyStatsDepositAmtTotals()
492587 let byDayKEY = keyStatsDepositAmtByDay(toStartOfDay(lastBlock.timestamp))
493588 let currTotals = padList(split(valueOrElse(getString(totalsKEY), defaultTotalsDATA), SEP))
494589 func dep (acc,pmt) = {
495590 let amount = pmt.amount
496591 let pmtAssetIdStr = toBase58String(valueOrElse(pmt.assetId, WAVESID))
497592 if (!(contains(supportedAssetsStr, pmtAssetIdStr)))
498593 then throw(((supportedAssetsStr + " doesn't contain ") + pmtAssetIdStr))
499594 else if ((totalStaked == 0))
500595 then $Tuple4((acc._1 :+ IncrementNotDistributedRewardEntry(pmtAssetIdStr, amount)), (acc._2 :+ pmtAssetIdStr), (acc._3 :+ toBigInt(0)), (acc._4 :+ amount))
501596 else {
502597 let rewardPerNsbtX18 = fraction(toBigInt(amount), MULTX18, toBigInt(totalStaked))
503598 $Tuple4(acc._1, (acc._2 :+ pmtAssetIdStr), (acc._3 :+ rewardPerNsbtX18), (acc._4 :+ amount))
504599 }
505600 }
506601
507602 let pmtsResult = {
508603 let $l = i.payments
509604 let $s = size($l)
510605 let $acc0 = $Tuple4(nil, nil, nil, nil)
511606 func $f0_1 ($a,$i) = if (($i >= $s))
512607 then $a
513608 else dep($a, $l[$i])
514609
515610 func $f0_2 ($a,$i) = if (($i >= $s))
516611 then $a
517612 else throw("List size exceeds 10")
518613
519614 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
520615 }
521616 func refreshRewardUpdateTotals (accum,nextAsset) = {
522617 let k = accum._3
523618 let sumLastStr = getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, nextAsset), "0")
524619 let idx = indexOf(pmtsResult._2, nextAsset)
525620 let sum = if (isDefined(idx))
526621 then {
527622 let j = value(idx)
528623 let statsDelta = pmtsResult._4[j]
529624 $Tuple2(toString((parseBigIntValue(sumLastStr) + pmtsResult._3[j])), toString((parseIntValue(currTotals[(k + 1)]) + statsDelta)))
530625 }
531626 else $Tuple2(sumLastStr, currTotals[(k + 1)])
532627 $Tuple3((accum._1 :+ StringEntry(keyRewardPerNsbtSumAt(depositNumNew, nextAsset), sum._1)), ((accum._2 + SEP) + sum._2), (k + 1))
533628 }
534629
535630 let assetsResult = {
536631 let $l = supportedAssetsList
537632 let $s = size($l)
538633 let $acc0 = $Tuple3(nil, DepositTotalsPREFIX, 0)
539634 func $f1_1 ($a,$i) = if (($i >= $s))
540635 then $a
541636 else refreshRewardUpdateTotals($a, $l[$i])
542637
543638 func $f1_2 ($a,$i) = if (($i >= $s))
544639 then $a
545640 else throw("List size exceeds 9")
546641
547642 $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9)
548643 }
549644 let totals = padString(assetsResult._2)
550645 $Tuple2(((((pmtsResult._1 ++ assetsResult._1) :+ IntegerEntry(depositNumLastKEY, depositNumNew)) :+ StringEntry(totalsKEY, totals)) :+ StringEntry(byDayKEY, totals)), depositNumNew)
551646 }
552647 }
553648
554649
555650
556651 @Callable(i)
557652 func claimRewards () = commonClaim(i.caller, i)
558653
559654
560655
561656 @Callable(i)
562657 func claimRewardsByOriginCaller () = commonClaim(i.originCaller, i)
563658
564659
565660
566661 @Callable(i)
662+func x2Gnsbt () = commonX2Gnsbt(i.caller, i)
663+
664+
665+
666+@Callable(i)
667+func x2GnsbtByOriginCaller () = commonX2Gnsbt(i.originCaller, i)
668+
669+
670+
671+@Callable(i)
567672 func unclaimedRewardsREADONLY (userAddressStr) = {
568673 func forEachAssetZeroReward (accum,asset) = ((accum + makeString([asset, "0", "0"], ":")) + "_")
569674
570675 let unclaimedRewardStr = if ((userAddressStr == ""))
571676 then {
572677 let $l = supportedAssetsList
573678 let $s = size($l)
574679 let $acc0 = ""
575680 func $f0_1 ($a,$i) = if (($i >= $s))
576681 then $a
577682 else forEachAssetZeroReward($a, $l[$i])
578683
579684 func $f0_2 ($a,$i) = if (($i >= $s))
580685 then $a
581686 else throw("List size exceeds 9")
582687
583688 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9)
584689 }
585690 else {
586691 let userAddress = addressFromStringValue(userAddressStr)
587- let $t02195522060 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
588- let isNewUser = $t02195522060._1
589- let stakedAmount = $t02195522060._2
590- let stakingStart = $t02195522060._3
591- let stakedAmountX = toBigInt(stakedAmount)
692+ let $t02584925968 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
693+ let isNewUser = $t02584925968._1
694+ let stakedAmount = $t02584925968._2
695+ let stakingStart = $t02584925968._3
696+ let userGnsbt = $t02584925968._4
697+ let stakedAmountX = toBigInt(userGnsbt)
592698 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
593699 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
594700 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
595701 func forEachAssetCalcUnclaimedReward (accum,asset) = {
596- let $t02240622544 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
597- let rewardTotal = $t02240622544._1
598- let cached = $t02240622544._2
599- let dynamic = $t02240622544._3
600- let rewardCachedPartKEY = $t02240622544._4
702+ let $t02631126449 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
703+ let rewardTotal = $t02631126449._1
704+ let cached = $t02631126449._2
705+ let dynamic = $t02631126449._3
706+ let rewardCachedPartKEY = $t02631126449._4
601707 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
602708 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
603709 }
604710
605711 let $l = supportedAssetsList
606712 let $s = size($l)
607713 let $acc0 = ""
608714 func $f0_1 ($a,$i) = if (($i >= $s))
609715 then $a
610716 else forEachAssetCalcUnclaimedReward($a, $l[$i])
611717
612718 func $f0_2 ($a,$i) = if (($i >= $s))
613719 then $a
614720 else throw("List size exceeds 9")
615721
616722 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9)
617723 }
618724 $Tuple2(nil, dropRight(unclaimedRewardStr, 1))
619725 }
620726
621727
622728
623729 @Callable(i)
624730 func nsbtUnstakingSYSREADONLY (userAddressStrOrEmpty,unstakeAmtP) = {
625731 let resultArray = if ((userAddressStrOrEmpty == ""))
626732 then [0, 0, 0, 0]
627733 else {
628734 let userAddress = addressFromStringValue(userAddressStrOrEmpty)
629735 let cfgDATA = getParamsOrFail()
630736 let nsbtAssetId = cfgDATA._1
631737 let minLockAmount = cfgDATA._2
632738 let halfLife = cfgDATA._3
633- let userDATA = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
739+ let userDATA = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
634740 let isNewUser = userDATA._1
635741 let stakedAmount = userDATA._2
636742 let lockStart = userDATA._3
637743 let unstakeAmt = if ((unstakeAmtP > stakedAmount))
638744 then stakedAmount
639745 else unstakeAmtP
640746 let stakedAmountNEW = (stakedAmount - unstakeAmt)
641747 let comissionAmount = if ((unstakeAmt == 0))
642748 then 0
643749 else asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [unstakeAmt, lockStart, halfLife], nil))
644750 let receiveAmount = (unstakeAmt - comissionAmount)
645751 [stakedAmount, stakedAmountNEW, receiveAmount, comissionAmount]
646752 }
647753 $Tuple2(nil, resultArray)
648754 }
649755
650756
651757
652758 @Callable(i)
653759 func nsbtStakingSYSREADONLY (userAddressStr,nsbtDiff) = {
654760 let totalNsbtAmt = getIntOrElse(keyLockParamTotalAmount(), 0)
761+ let totalGnsbt = getIntOrElse(keyLockParamTotalGnsbt(), totalNsbtAmt)
655762 if ((userAddressStr == ""))
656- then $Tuple2(nil, [0, totalNsbtAmt, 0])
763+ then $Tuple2(nil, [0, totalNsbtAmt, 0, 0, totalGnsbt])
657764 else {
658765 let userAddress = toAddressOrFail(userAddressStr)
659- let $t02422224326 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
660- let isNewUser = $t02422224326._1
661- let userNsbtAmt = $t02422224326._2
662- let stakingStart = $t02422224326._3
663- $Tuple2(nil, [userNsbtAmt, totalNsbtAmt, stakingStart])
766+ let $t02823928364 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple4(true, 0, 0, 0))
767+ let isNewUser = $t02823928364._1
768+ let userNsbtAmt = $t02823928364._2
769+ let stakingStart = $t02823928364._3
770+ let currentUserGnsbt = $t02823928364._4
771+ let userConsentTuple = readUserConsentToX2Gnsbt(addressFromStringValue(userAddressStr))
772+ let userConsentedToX2GnsbtKEY = userConsentTuple._1
773+ let userConsentedToX2Gnsbt = userConsentTuple._2
774+ let deltaUserGnsbt = if (if (isBonusPeriod(height))
775+ then if (isNewUser)
776+ then true
777+ else userConsentedToX2Gnsbt
778+ else false)
779+ then (2 * nsbtDiff)
780+ else nsbtDiff
781+ $Tuple2(nil, [userNsbtAmt, totalNsbtAmt, stakingStart, currentUserGnsbt, totalGnsbt, deltaUserGnsbt])
664782 }
665783 }
666784
667785
668786 @Verifier(tx)
669787 func verify () = {
670788 let pubKeyAdminsListStr = makeString(["GJdLSaLiv5K7xuejac8mcRcHoyo3dPrESrvktG3a6MAR", "EYwZmURd5KKaQRBjsVa6g8DPisFoS6SovRJtFiL5gMHU", "DtmAfuDdCrHK8spdAeAYzq6MsZegeD9gnsrpuTRkCbVA", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"], SEP)
671789 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
672790 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
673791 then 1
674792 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
675793 then 1
676794 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
677795 then 1
678796 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
679797 then 2
680798 else 0))
681799 (count >= 3)
682800 }
683801

github/deemru/w8io/786bc32 
109.48 ms