tx · Ct8W11t2G1ttQsodNs5mHhYVhHNptaAmvS9NpgtE5rCK

3N5yarEiTQccnnuerogYT3BxM5Zc5bRgDZy:  -0.03100000 Waves

2022.11.21 13:53 [2326779] smart account 3N5yarEiTQccnnuerogYT3BxM5Zc5bRgDZy > SELF 0.00000000 Waves

{ "type": 13, "id": "Ct8W11t2G1ttQsodNs5mHhYVhHNptaAmvS9NpgtE5rCK", "fee": 3100000, "feeAssetId": null, "timestamp": 1669027994735, "version": 2, "chainId": 84, "sender": "3N5yarEiTQccnnuerogYT3BxM5Zc5bRgDZy", "senderPublicKey": "FK9j3YFWVChXKESTn33fMZz1JseCNMMqHhfB7smxJo4e", "proofs": [ "4n49kb9DK2TnNncpgdrtGiYwqU6EGmMEmYvKJVnzF8wocq4CKt8XL9miJyBvF642tnDT834XJ6BfC9zhFnCnbLt7" ], "script": "base64:BgIvCAISBQoDAQgIEgASABIDCgEBEgASABIAEgMKAQgSAwoBCBIECgIIARIDCgEBEgBpAAlzZXBhcmF0b3ICAl9fAANTRVACAl9fAAVNVUxUNgDAhD0ABU1VTFQ4AIDC1y8ABk1VTFRYNgkAtgIBBQVNVUxUNgAGTVVMVFg4CQC2AgEFBU1VTFQ4AAdNVUxUWDE4CQC2AgEAgICQu7rWrfANAApXQVZFU0lEU1RSAgVXQVZFUwAHV0FWRVNJRAkA2QQBBQpXQVZFU0lEU1RSAAlEQVlNSUxMSVMAgLiZKQANREVGQVVMVFBFUklPRAkAaAIAoAsADgAZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAABABhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAAgAUSWR4Q29udHJvbENmZ1JwZERhcHAAAwAVSWR4Q29udHJvbENmZ01hdGhEYXBwAAQAHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAABQAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAYAHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAcAHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAACAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAJABxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwAAoAIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAAsAF0lkeENvbnRyb2xDZmdSZXN0VjJEYXBwAAwAG0lkeENvbnRyb2xDZmdHb3Zlcm5hbmNlRGFwcAANAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQCsAgIJAKwCAgkArAICCQCsAgICCm1hbmRhdG9yeSAJAKUIAQUHYWRkcmVzcwIBLgUDa2V5Ag8gaXMgbm90IGRlZmluZWQBEWtleUNvbnRyb2xBZGRyZXNzAAIcJXMlc19fY29uZmlnX19jb250cm9sQWRkcmVzcwENa2V5Q29udHJvbENmZwACESVzX19jb250cm9sQ29uZmlnARVrZXlHbnNidEZyb21TdXJmQ29lZmYAAh0lcyVzX19jZmdfX2duc2J0RnJvbVN1cmZDb2VmZgEUcmVhZENvbnRyb2xDZmdPckZhaWwBB2NvbnRyb2wJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFB2NvbnRyb2wJAQ1rZXlDb250cm9sQ2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCCmNvbnRyb2xDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpjb250cm9sQ2ZnBQNpZHgJAKwCAgItQ29udHJvbCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAPY29udHJvbENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJARFrZXlDb250cm9sQWRkcmVzcwACIzNONE5TN2Q0Sm85YTZGMTRMaUZVS0tZVmRVa2tmMmVQNFp4AApjb250cm9sQ2ZnCQEUcmVhZENvbnRyb2xDZmdPckZhaWwBBQ9jb250cm9sQ29udHJhY3QADG1hdGhDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAQbmV1dHJpbm9Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAD2F1Y3Rpb25Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAALZ292Q29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRtJZHhDb250cm9sQ2ZnR292ZXJuYW5jZURhcHAAEmduc2J0RnJvbVN1cmZDb2VmZgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEVa2V5R25zYnRGcm9tU3VyZkNvZWZmAACsAgEMa2V5Qm9uZEFzc2V0AAINYm9uZF9hc3NldF9pZAEZa2V5QXVjdGlvbkNvbnRyYWN0QWRkcmVzcwACEGF1Y3Rpb25fY29udHJhY3QBEGtleU1pbkxvY2tBbW91bnQAAhElc19fbWluTG9ja0Ftb3VudAEQa2V5U3Rha2VkQXNzZXRJZAACESVzX19zdGFrZWRBc3NldElkARZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtwYXJhbUJ5VXNlcgkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICBmFtb3VudAUDbmlsBQlzZXBhcmF0b3IBFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIJAKUIAQULdXNlckFkZHJlc3MJAMwIAgIFc3RhcnQFA25pbAUJc2VwYXJhdG9yASZrZXlMb2NrUGFyYW1Wb3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCAhF2cEVmZmVjdGl2ZUhlaWdodAUDbmlsBQlzZXBhcmF0b3IBEGtleUhpc3RvcnlSZWNvcmQDBHR5cGULdXNlckFkZHJlc3MEdHhJZAkAuQkCCQDMCAICCCVzJXMlcyVzCQDMCAICB2hpc3RvcnkJAMwIAgUEdHlwZQkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAIJANgEAQUEdHhJZAUDbmlsBQlzZXBhcmF0b3IBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAkAuQkCCQDMCAICBCVzJXMJAMwIAgIFc3RhdHMJAMwIAgIRYWN0aXZlVG90YWxMb2NrZWQFA25pbAUJc2VwYXJhdG9yARJrZXlTdGF0c0xvY2tzQ291bnQACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVzdGF0cwkAzAgCAgpsb2Nrc0NvdW50BQNuaWwFCXNlcGFyYXRvcgESa2V5U3RhdHNVc2Vyc0NvdW50AAkAuQkCCQDMCAICBCVzJXMJAMwIAgIFc3RhdHMJAMwIAgIQYWN0aXZlVXNlcnNDb3VudAUDbmlsBQlzZXBhcmF0b3IBF2tleVN0YXRzRGVwb3NpdEFtdEJ5RGF5AQl0aW1lc3RhbXAJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIFc3RhdHMJAMwIAgIPZGVwb3NpdEFtdEJ5RGF5CQDMCAIJAKQDAQUJdGltZXN0YW1wBQNuaWwFCXNlcGFyYXRvcgEYa2V5U3RhdHNEZXBvc2l0QW10VG90YWxzAAkAuQkCCQDMCAICBCVzJXMJAMwIAgIFc3RhdHMJAMwIAgIQZGVwb3NpdEFtdFRvdGFscwUDbmlsBQlzZXBhcmF0b3IBGGtleVN1cHBvcnRlZFJld2FyZEFzc2V0cwACFXN1cHBvcnRlZFJld2FyZEFzc2V0cwERa2V5RGVwb3NpdE51bUxhc3QACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgNkZXAJAMwIAgIHbGFzdE51bQUDbmlsBQlzZXBhcmF0b3IBG2tleVVzZXJSZXdhcmRGcm9tRGVwb3NpdE51bQELdXNlckFkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAICEXVzZXJSd2RGcm9tRGVwTnVtCQDMCAIFC3VzZXJBZGRyZXNzBQNuaWwFCXNlcGFyYXRvcgEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgpkZXBvc2l0TnVtA3RrbgkAuQkCCQDMCAICBCVzJWQJAMwIAgIVcndkUGVyTnNidFN1bUJ5RGVwTnVtCQDMCAIJAKQDAQUKZGVwb3NpdE51bQkAzAgCBQN0a24FA25pbAUJc2VwYXJhdG9yAQlrZXlSZXdhcmQCC3VzZXJBZGRyZXNzA3RrbgkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgNyd2QJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUDdGtuBQNuaWwFCXNlcGFyYXRvcgEKa2V5Q2xhaW1lZAILdXNlckFkZHJlc3MDdGtuCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICA2NsbQkAzAgCBQt1c2VyQWRkcmVzcwkAzAgCBQN0a24FA25pbAUJc2VwYXJhdG9yARdrZXlOb3REaXN0cmlidXRlZFJld2FyZAEDdGtuCQC5CQIJAMwIAgIEJXMlcwkAzAgCAg5ub3REaXN0cmlidXRlZAkAzAgCBQN0a24FA25pbAUJc2VwYXJhdG9yARNrZXlWcFBlcmlvZER1cmF0aW9uAAkAuQkCCQDMCAICBCVzJXMJAMwIAgICdnAJAMwIAgIOcGVyaW9kRHVyYXRpb24FA25pbAUJc2VwYXJhdG9yARxrZXlMYXN0VG90YWxzUGVyaW9kUHJvY2Vzc2VkAAkAuQkCCQDMCAICBCVzJXMJAMwIAgICdnAJAMwIAgIZbGFzdFRvdGFsc1BlcmlvZFByb2Nlc3NlZAUDbmlsBQlzZXBhcmF0b3IBGmtleUxhc3RVc2VyUGVyaW9kUHJvY2Vzc2VkAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgJ2cAkAzAgCAhdsYXN0VXNlclBlcmlvZFByb2Nlc3NlZAkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQlzZXBhcmF0b3IBDmtleVRvdGFsTWF0dXJlAAkAuQkCCQDMCAICBCVzJXMJAMwIAgICdnAJAMwIAgILdG90YWxNYXR1cmUFA25pbAUJc2VwYXJhdG9yAQxrZXlUb3RhbFRlZW4ACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgJ2cAkAzAgCAgl0b3RhbFRlZW4FA25pbAUJc2VwYXJhdG9yAQtrZXlUb3RhbEtpZAAJALkJAgkAzAgCAgQlcyVzCQDMCAICAnZwCQDMCAICCHRvdGFsS2lkBQNuaWwFCXNlcGFyYXRvcgENa2V5VXNlck1hdHVyZQELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgICdnAJAMwIAgIKdXNlck1hdHVyZQkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQlzZXBhcmF0b3IBC2tleVVzZXJUZWVuAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgJ2cAkAzAgCAgh1c2VyVGVlbgkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQlzZXBhcmF0b3IBCmtleVVzZXJLaWQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICAnZwCQDMCAICB3VzZXJLaWQJAMwIAgULdXNlckFkZHJlc3MFA25pbAUJc2VwYXJhdG9yAQV0b1gxOAIHb3JpZ1ZhbAhvcmlnTXVsdAkAvAIDCQC2AgEFB29yaWdWYWwFB01VTFRYMTgFCG9yaWdNdWx0AQxnZXRJbnRPclplcm8BA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkAAAEMZ2V0SW50T3JFbHNlAgNrZXkKZGVmYXVsdFZhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkFCmRlZmF1bHRWYWwBDGdldEludE9yRmFpbAEDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUEdGhpcwUDa2V5CQCsAgIJAKwCAgIPTWFuZGF0b3J5IHRoaXMuBQNrZXkCDyBpcyBub3QgZGVmaW5lZAEMZ2V0U3RyT3JFbHNlAgNrZXkKZGVmYXVsdFZhbAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQNrZXkFCmRlZmF1bHRWYWwBD3RvQWRkcmVzc09yRmFpbAEKYWRkcmVzc1N0cgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFCmFkZHJlc3NTdHIJAKwCAgIhY291bGRuJ3QgcGFyc2UgcGFzc2VkIGFkZHJlc3NTdHI9BQphZGRyZXNzU3RyAQt0b0Fzc2V0VmVjdAEIYXNzZXRTdHIDCQAAAgUIYXNzZXRTdHIFCldBVkVTSURTVFIFBHVuaXQJANkEAQUIYXNzZXRTdHIBBWFzSW50AQN2YWwEByRtYXRjaDAFA3ZhbAMJAAECBQckbWF0Y2gwAgNJbnQEBnZhbEludAUHJG1hdGNoMAUGdmFsSW50CQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50ARJhc1N3YXBQYXJhbXNTVFJVQ1QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIjKEludCwgSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCkEBnN0cnVjdAUHJG1hdGNoMAUGc3RydWN0CQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50ARNmb3JtYXRIaXN0b3J5UmVjb3JkBAlvbGRBbW91bnQIb2xkU3RhcnQJbmV3QW1vdW50CG5ld1N0YXJ0CQC5CQIJAMwIAgIMJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQCkAwEFCW9sZEFtb3VudAkAzAgCCQCkAwEFCG9sZFN0YXJ0CQDMCAIJAKQDAQUJbmV3QW1vdW50CQDMCAIJAKQDAQUIbmV3U3RhcnQFA25pbAUJc2VwYXJhdG9yARhmb3JtYXRDbGFpbUhpc3RvcnlSZWNvcmQCBHVzZXIOY2xhaW1lZFJld2FyZHMJALkJAgkAzAgCAgglcyVkJWQlcwkAzAgCBQR1c2VyCQDMCAIJAKQDAQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCBQ5jbGFpbWVkUmV3YXJkcwUDbmlsBQlzZXBhcmF0b3IBEkhpc3RvcnlSZWNvcmRFbnRyeQcEdHlwZQt1c2VyQWRkcmVzcwR0eElkCW9sZEFtb3VudAhvbGRTdGFydAluZXdBbW91bnQIbmV3U3RhcnQJAQtTdHJpbmdFbnRyeQIJARBrZXlIaXN0b3J5UmVjb3JkAwUEdHlwZQULdXNlckFkZHJlc3MFBHR4SWQJARNmb3JtYXRIaXN0b3J5UmVjb3JkBAUJb2xkQW1vdW50BQhvbGRTdGFydAUJbmV3QW1vdW50BQhuZXdTdGFydAERQ2xhaW1IaXN0b3J5RW50cnkDC3VzZXJBZGRyZXNzBHR4SWQOY2xhaW1lZFJld2FyZHMJAQtTdHJpbmdFbnRyeQIJARBrZXlIaXN0b3J5UmVjb3JkAwIFY2xhaW0FC3VzZXJBZGRyZXNzBQR0eElkCQEYZm9ybWF0Q2xhaW1IaXN0b3J5UmVjb3JkAgkApQgBBQt1c2VyQWRkcmVzcwUOY2xhaW1lZFJld2FyZHMBC1N0YXRzUmVzdWx0Aw50b3RhbExvY2tlZEluYwxsb2NrQ291bnRJbmMNdXNlcnNDb3VudEluYwQKbG9ja3NDb3VudAkBDGdldEludE9yWmVybwEJARJrZXlTdGF0c0xvY2tzQ291bnQABAp1c2Vyc0NvdW50CQEMZ2V0SW50T3JaZXJvAQkBEmtleVN0YXRzVXNlcnNDb3VudAAEC3RvdGFsQW1vdW50CQEMZ2V0SW50T3JaZXJvAQkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAQOdG90YWxBbW91bnROZXcJAGQCBQt0b3RhbEFtb3VudAUOdG90YWxMb2NrZWRJbmMJAJUKAwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleVN0YXRzTG9ja3NDb3VudAAJAGQCBQpsb2Nrc0NvdW50BQxsb2NrQ291bnRJbmMJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlTdGF0c1VzZXJzQ291bnQACQBkAgUKdXNlcnNDb3VudAUNdXNlcnNDb3VudEluYwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAUOdG90YWxBbW91bnROZXcFA25pbAULdG90YWxBbW91bnQFDnRvdGFsQW1vdW50TmV3AQ9Mb2NrUGFyYW1zRW50cnkDC3VzZXJBZGRyZXNzBmFtb3VudBp2b3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBBQt1c2VyQWRkcmVzcwUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawEFC3VzZXJBZGRyZXNzBRp2b3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAUDbmlsAQ9nZXRQYXJhbXNPckZhaWwACQCUCgIJANkEAQkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARBrZXlTdGFrZWRBc3NldElkAAkBDGdldEludE9yRmFpbAEJARBrZXlNaW5Mb2NrQW1vdW50AAEMaXNBY3RpdmVVc2VyAQt1c2VyQWRkcmVzcwkAZgIJAQxnZXRJbnRPckVsc2UCCQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEFC3VzZXJBZGRyZXNzAAAAAAETZ2V0VXNlclBhcmFtc09yVW5pdAELdXNlckFkZHJlc3MDCQEMaXNBY3RpdmVVc2VyAQULdXNlckFkZHJlc3MJAJUKAwcJAQxnZXRJbnRPckZhaWwBCQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEFC3VzZXJBZGRyZXNzCQEMZ2V0SW50T3JGYWlsAQkBFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sBBQt1c2VyQWRkcmVzcwUEdW5pdAETZ2V0VXNlclBhcmFtc09yRmFpbAELdXNlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkArAICCQCsAgICBVVzZXIgCQClCAEFC3VzZXJBZGRyZXNzAg8gaXMgbm90IGRlZmluZWQAEnN1cHBvcnRlZEFzc2V0c1N0cgkBDGdldFN0ck9yRWxzZQIJARhrZXlTdXBwb3J0ZWRSZXdhcmRBc3NldHMAAgAAE3N1cHBvcnRlZEFzc2V0c0xpc3QJALUJAgUSc3VwcG9ydGVkQXNzZXRzU3RyAgFfAQpjYWxjUmV3YXJkBQt1c2VyQWRkcmVzcwdhc3NldElkDXN0YWtlZEFtb3VudFgOZGVwb3NpdE51bVVzZXIOZGVwb3NpdE51bUxhc3QEF3Jld2FyZFBlck5zYnRTdW1MYXN0S0VZCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bUxhc3QFB2Fzc2V0SWQECnN1bUxhc3RYMTgJAKcDAQkBDGdldFN0ck9yRWxzZQIJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ5kZXBvc2l0TnVtTGFzdAUHYXNzZXRJZAIBMAQKc3VtVXNlclgxOAkApwMBCQEMZ2V0U3RyT3JFbHNlAgkBFWtleVJld2FyZFBlck5zYnRTdW1BdAIFDmRlcG9zaXROdW1Vc2VyBQdhc3NldElkAgEwBBFyZXdhcmREeW5hbWljUGFydAkAoAMBCQC8AgMJALgCAgUKc3VtTGFzdFgxOAUKc3VtVXNlclgxOAUNc3Rha2VkQW1vdW50WAUHTVVMVFgxOAQTcmV3YXJkQ2FjaGVkUGFydEtFWQkBCWtleVJld2FyZAIFC3VzZXJBZGRyZXNzBQdhc3NldElkBBByZXdhcmRDYWNoZWRQYXJ0CQEMZ2V0SW50T3JFbHNlAgUTcmV3YXJkQ2FjaGVkUGFydEtFWQAACQCWCgQJAGQCBRByZXdhcmRDYWNoZWRQYXJ0BRFyZXdhcmREeW5hbWljUGFydAUQcmV3YXJkQ2FjaGVkUGFydAURcmV3YXJkRHluYW1pY1BhcnQFE3Jld2FyZENhY2hlZFBhcnRLRVkBDHRvU3RhcnRPZkRheQEJdGltZXN0YW1wCQBoAgkAaQIFCXRpbWVzdGFtcAUJREFZTUlMTElTBQlEQVlNSUxMSVMBE2ZpbmRFbGVtZW50UG9zaXRpb24DA3NyYwdlbGVtZW50A3NlcAQMZWxlbWVudFN0YXJ0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJALMJAgUDc3JjBQdlbGVtZW50CQCsAgIJAKwCAgkArAICAhZ0aGVyZSBpcyBubyBzdWJzdHJpbmcgBQdlbGVtZW50AgQgaW4gBQNzcmMDCQAAAgUMZWxlbWVudFN0YXJ0AAAAAAQEbGVmdAkArwICBQNzcmMFDGVsZW1lbnRTdGFydAkAZQIJAJADAQkAtQkCBQRsZWZ0BQNzZXAAAQATRGVwb3NpdFRvdGFsc1BSRUZJWAIkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkARN1cGRhdGVEZXBvc2l0VG90YWxzAwdjdXJyVmFsC2lkeFRvVXBkYXRlCGRlbHRhQW10BAdjdXJyQXJyCQC1CQIFB2N1cnJWYWwFA1NFUAoBDnVwZERlcFRvdEJ5SWR4AQNpZHgDCQECIT0CBQNpZHgFC2lkeFRvVXBkYXRlCQCRAwIFB2N1cnJBcnIFA2lkeAkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFB2N1cnJBcnIFA2lkeAUIZGVsdGFBbXQJALkJAgkAzAgCBRNEZXBvc2l0VG90YWxzUFJFRklYCQDMCAIJAQ51cGREZXBUb3RCeUlkeAEAAQkAzAgCCQEOdXBkRGVwVG90QnlJZHgBAAIJAMwIAgkBDnVwZERlcFRvdEJ5SWR4AQADCQDMCAIJAQ51cGREZXBUb3RCeUlkeAEABAkAzAgCCQEOdXBkRGVwVG90QnlJZHgBAAUJAMwIAgkBDnVwZERlcFRvdEJ5SWR4AQAGCQDMCAIJAQ51cGREZXBUb3RCeUlkeAEABwkAzAgCCQEOdXBkRGVwVG90QnlJZHgBAAgJAMwIAgkBDnVwZERlcFRvdEJ5SWR4AQAJCQDMCAIJAQ51cGREZXBUb3RCeUlkeAEACgkAzAgCCQEOdXBkRGVwVG90QnlJZHgBAAsJAMwIAgkBDnVwZERlcFRvdEJ5SWR4AQAMCQDMCAIJAQ51cGREZXBUb3RCeUlkeAEADQkAzAgCCQEOdXBkRGVwVG90QnlJZHgBAA4JAMwIAgkBDnVwZERlcFRvdEJ5SWR4AQAPCQDMCAIJAQ51cGREZXBUb3RCeUlkeAEAEAkAzAgCCQEOdXBkRGVwVG90QnlJZHgBABEJAMwIAgkBDnVwZERlcFRvdEJ5SWR4AQASBQNuaWwFA1NFUAEVRGVwb3NpdHNUb3RhbHNFbnRyaWVzAg1kZXBvc2l0QW1vdW50CmFzc2V0SWRTdHIECnN0YXJ0T2ZEYXkJAQx0b1N0YXJ0T2ZEYXkBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQIYnlEYXlLRVkJARdrZXlTdGF0c0RlcG9zaXRBbXRCeURheQEFCnN0YXJ0T2ZEYXkECXRvdGFsc0tFWQkBGGtleVN0YXRzRGVwb3NpdEFtdFRvdGFscwAECHBvc2l0aW9uCQETZmluZEVsZW1lbnRQb3NpdGlvbgMFEnN1cHBvcnRlZEFzc2V0c1N0cgUKYXNzZXRJZFN0cgIBXwQLZGVmYXVsdERBVEEJAKwCAgUTRGVwb3NpdFRvdGFsc1BSRUZJWAI2X18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wX18wBA5jdXJyVG90YWxzREFUQQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQl0b3RhbHNLRVkFC2RlZmF1bHREQVRBBA1uZXdUb3RhbHNEQVRBCQETdXBkYXRlRGVwb3NpdFRvdGFscwMFDmN1cnJUb3RhbHNEQVRBCQBkAgUIcG9zaXRpb24AAQUNZGVwb3NpdEFtb3VudAkAzAgCCQELU3RyaW5nRW50cnkCBQl0b3RhbHNLRVkFDW5ld1RvdGFsc0RBVEEJAMwIAgkBC1N0cmluZ0VudHJ5AgUIYnlEYXlLRVkFDW5ld1RvdGFsc0RBVEEFA25pbAENUmV3YXJkRW50cmllcwMJaXNOZXdVc2VyC3VzZXJBZGRyZXNzDHN0YWtlZEFtb3VudAQNc3Rha2VkQW1vdW50WAkAtgIBBQxzdGFrZWRBbW91bnQEG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQkBG2tleVVzZXJSZXdhcmRGcm9tRGVwb3NpdE51bQEFC3VzZXJBZGRyZXNzBA5kZXBvc2l0TnVtVXNlcgkBDGdldEludE9yRWxzZQIFG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQD///////////8BBA5kZXBvc2l0TnVtTGFzdAkBDGdldEludE9yRWxzZQIJARFrZXlEZXBvc2l0TnVtTGFzdAAA////////////AQoBG2ZvckVhY2hBc3NldENhY2hlVXNlclJld2FyZAIFYWNjdW0FYXNzZXQEDSR0MDEyMTA0MTIyMzkJAQpjYWxjUmV3YXJkBQULdXNlckFkZHJlc3MFBWFzc2V0BQ1zdGFrZWRBbW91bnRYBQ5kZXBvc2l0TnVtVXNlcgUOZGVwb3NpdE51bUxhc3QEC3Jld2FyZFRvdGFsCAUNJHQwMTIxMDQxMjIzOQJfMQQGY2FjaGVkCAUNJHQwMTIxMDQxMjIzOQJfMgQHZHluYW1pYwgFDSR0MDEyMTA0MTIyMzkCXzMEE3Jld2FyZENhY2hlZFBhcnRLRVkIBQ0kdDAxMjEwNDEyMjM5Al80CQDNCAIFBWFjY3VtCQEMSW50ZWdlckVudHJ5AgUTcmV3YXJkQ2FjaGVkUGFydEtFWQULcmV3YXJkVG90YWwDAwkAAAIFDmRlcG9zaXROdW1MYXN0AP///////////wEJAAACBQ5kZXBvc2l0TnVtVXNlcgD///////////8BBwUDbmlsAwMJAAACBQ5kZXBvc2l0TnVtTGFzdAD///////////8BCQBmAgUOZGVwb3NpdE51bVVzZXIA////////////AQcJAAIBAi9pbnZhbGlkIGRlcG9zaXROdW1MYXN0IGFuZCBkZXBvc2l0TnVtVXNlciBzdGF0ZQMDCQBmAgUOZGVwb3NpdE51bUxhc3QA////////////AQkAZwIFDmRlcG9zaXROdW1Vc2VyAP///////////wEHAwUJaXNOZXdVc2VyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0BQNuaWwJAM0IAgoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARtmb3JFYWNoQXNzZXRDYWNoZVVzZXJSZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDkJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0CQACAQkArAICCQCsAgIJAKwCAgIkdW5jb3ZlcmVkIGNvbmRpdGlvbjogZGVwb3NpdE51bUxhc3Q9CQCkAwEFDmRlcG9zaXROdW1MYXN0AhAgZGVwb3NpdE51bVVzZXI9CQCkAwEFDmRlcG9zaXROdW1Vc2VyASJJbmNyZW1lbnROb3REaXN0cmlidXRlZFJld2FyZEVudHJ5AgN0a24JYW1vdW50SW5jBBdub3REaXN0cmlidXRlZFJld2FyZEtFWQkBF2tleU5vdERpc3RyaWJ1dGVkUmV3YXJkAQUDdGtuBBRub3REaXN0cmlidXRlZFJld2FyZAkBDGdldEludE9yRWxzZQIFF25vdERpc3RyaWJ1dGVkUmV3YXJkS0VZAAAJAMwIAgkBDEludGVnZXJFbnRyeQIFF25vdERpc3RyaWJ1dGVkUmV3YXJkS0VZCQBkAgUUbm90RGlzdHJpYnV0ZWRSZXdhcmQFCWFtb3VudEluYwUDbmlsAQtzdXJmVG9HbnNidAEHc3VyZkFtdAkAaQIFB3N1cmZBbXQFEmduc2J0RnJvbVN1cmZDb2VmZgEKbWVyZ2VTdGFrZQQLdXNlckFkZHJlc3MLYW1vdW50VG9BZGQIdXNlclRlZW4HdXNlcktpZAQNJHQwMTUxNjIxNTI3MgkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDE1MTYyMTUyNzICXzEEDHN0YWtlZEFtb3VudAgFDSR0MDE1MTYyMTUyNzICXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUNJHQwMTUxNjIxNTI3MgJfMwQPc3Rha2VkQW1vdW50TkVXAwUJaXNOZXdVc2VyBQthbW91bnRUb0FkZAkAZAIFC2Ftb3VudFRvQWRkBQxzdGFrZWRBbW91bnQEAlcyCQEMZ2V0SW50T3JFbHNlAgkBE2tleVZwUGVyaW9kRHVyYXRpb24ABQ1ERUZBVUxUUEVSSU9EBAZwZXJpb2QJAGkCBQZoZWlnaHQFAlcyBBR2cEVmZmVjdGl2ZVBlcmlvZE5FVwMJAGYCBQd1c2VyS2lkAAAJAGQCBQZwZXJpb2QAAgMJAGYCBQh1c2VyVGVlbgAACQBkAgUGcGVyaW9kAAEFBnBlcmlvZAkAlwoFBQlpc05ld1VzZXIFDHN0YWtlZEFtb3VudAURdnBFZmZlY3RpdmVIZWlnaHQFD3N0YWtlZEFtb3VudE5FVwkAaAIFFHZwRWZmZWN0aXZlUGVyaW9kTkVXBQJXMgEMdXBkYXRlVG90YWxzAAQGcGVyaW9kCQBpAgUGaGVpZ2h0CQEMZ2V0SW50T3JFbHNlAgkBE2tleVZwUGVyaW9kRHVyYXRpb24ABQ1ERUZBVUxUUEVSSU9EAwkAZgIFBnBlcmlvZAkBDGdldEludE9yWmVybwEJARxrZXlMYXN0VG90YWxzUGVyaW9kUHJvY2Vzc2VkAAQLdG90YWxNYXR1cmUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBDmtleVRvdGFsTWF0dXJlAAkBDGdldEludE9yWmVybwEJARdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5rZXlUb3RhbE1hdHVyZQAJAGQCBQt0b3RhbE1hdHVyZQkBDGdldEludE9yWmVybwEJAQxrZXlUb3RhbFRlZW4ACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEMa2V5VG90YWxUZWVuAAkBDGdldEludE9yWmVybwEJAQtrZXlUb3RhbEtpZAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQtrZXlUb3RhbEtpZAAAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHGtleUxhc3RUb3RhbHNQZXJpb2RQcm9jZXNzZWQABQZwZXJpb2QFA25pbAUDbmlsAQdvblN0YWtlAg51c2VyQWRkcmVzc1N0cgthbW91bnRUb0FkZAMJAGYCAAAFC2Ftb3VudFRvQWRkCQACAQIaYW1vdW50VG9BZGQgc2hvdWxkIGJlID49IDAEAlcyCQEMZ2V0SW50T3JFbHNlAgkBE2tleVZwUGVyaW9kRHVyYXRpb24ABQ1ERUZBVUxUUEVSSU9EBAZwZXJpb2QJAGkCBQZoZWlnaHQFAlcyBAt0b3RhbE1hdHVyZQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEOa2V5VG90YWxNYXR1cmUACQEMZ2V0SW50T3JaZXJvAQkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAQJdG90YWxUZWVuCQEMZ2V0SW50T3JaZXJvAQkBDGtleVRvdGFsVGVlbgAECHRvdGFsS2lkCQEMZ2V0SW50T3JaZXJvAQkBC2tleVRvdGFsS2lkAAQKdXNlck1hdHVyZQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQENa2V5VXNlck1hdHVyZQEFDnVzZXJBZGRyZXNzU3RyCQEMZ2V0SW50T3JaZXJvAQkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQ51c2VyQWRkcmVzc1N0cgQIdXNlclRlZW4JAQxnZXRJbnRPclplcm8BCQELa2V5VXNlclRlZW4BBQ51c2VyQWRkcmVzc1N0cgQHdXNlcktpZAkBDGdldEludE9yWmVybwEJAQprZXlVc2VyS2lkAQUOdXNlckFkZHJlc3NTdHIEA3RtcAMJAGYCBQZwZXJpb2QJAQxnZXRJbnRPclplcm8BCQEaa2V5TGFzdFVzZXJQZXJpb2RQcm9jZXNzZWQBBQ51c2VyQWRkcmVzc1N0cgkAmQoHCQBkAgULdG90YWxNYXR1cmUFCHVzZXJUZWVuCQBkAgUJdG90YWxUZWVuCQBlAgUHdXNlcktpZAUIdXNlclRlZW4JAGUCBQh0b3RhbEtpZAUHdXNlcktpZAkAZAIFCnVzZXJNYXR1cmUFCHVzZXJUZWVuBQd1c2VyS2lkAAAJAMwIAgkBDEludGVnZXJFbnRyeQIJARprZXlMYXN0VXNlclBlcmlvZFByb2Nlc3NlZAEFDnVzZXJBZGRyZXNzU3RyBQZwZXJpb2QFA25pbAkAmQoHBQt0b3RhbE1hdHVyZQUJdG90YWxUZWVuBQh0b3RhbEtpZAUKdXNlck1hdHVyZQUIdXNlclRlZW4FB3VzZXJLaWQFA25pbAQGdG90YWxzAwkAZgIFBnBlcmlvZAkBDGdldEludE9yWmVybwEJARxrZXlMYXN0VG90YWxzUGVyaW9kUHJvY2Vzc2VkAAkAlgoECQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOa2V5VG90YWxNYXR1cmUACQBkAggFA3RtcAJfMQgFA3RtcAJfMgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDGtleVRvdGFsVGVlbgAIBQN0bXACXzMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQtrZXlUb3RhbEtpZAAAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHGtleUxhc3RUb3RhbHNQZXJpb2RQcm9jZXNzZWQABQZwZXJpb2QFA25pbAkAZAIIBQN0bXACXzEIBQN0bXACXzIIBQN0bXACXzMAAAkAlgoEBQNuaWwFC3RvdGFsTWF0dXJlBQl0b3RhbFRlZW4FCHRvdGFsS2lkBAZuZXdLaWQJAGsDBQthbW91bnRUb0FkZAkAagIFBmhlaWdodAUCVzIFAlcyBAduZXdUZWVuCQBlAgULYW1vdW50VG9BZGQFBm5ld0tpZAkAmQoHCQDOCAIJAM0IAgkAzQgCCQDNCAIIBQZ0b3RhbHMCXzEJAQxJbnRlZ2VyRW50cnkCCQENa2V5VXNlck1hdHVyZQEFDnVzZXJBZGRyZXNzU3RyCAUDdG1wAl80CQEMSW50ZWdlckVudHJ5AgkBC2tleVVzZXJUZWVuAQUOdXNlckFkZHJlc3NTdHIJAGQCCAUDdG1wAl81BQduZXdUZWVuCQEMSW50ZWdlckVudHJ5AgkBCmtleVVzZXJLaWQBBQ51c2VyQWRkcmVzc1N0cgkAZAIIBQN0bXACXzYFBm5ld0tpZAgFA3RtcAJfNwgFBnRvdGFscwJfMggFBnRvdGFscwJfMwgFBnRvdGFscwJfNAgFA3RtcAJfNAkAZAIIBQN0bXACXzUFB25ld1RlZW4JAGQCCAUDdG1wAl82BQZuZXdLaWQACklkeE5ld0RpZmYAAAALSWR4TmV3R25zYnQAAQEMdXNlckRlY3JlYXNlAgVnbnNidARkaWZmAwkAZwIFBGRpZmYFBWduc2J0CQDMCAIJAGUCBQRkaWZmBQVnbnNidAkAzAgCAAAFA25pbAkAzAgCAAAJAMwIAgkAZQIFBWduc2J0BQRkaWZmBQNuaWwBCW9uVW5zdGFrZQIOdXNlckFkZHJlc3NTdHIOYW1vdW50VG9SZW1vdmUDCQBnAgUOYW1vdW50VG9SZW1vdmUAAAkAAgECHGFtb3VudFRvUmVtb3ZlIHNob3VsZCBiZSA8IDAEAlcyCQEMZ2V0SW50T3JFbHNlAgkBE2tleVZwUGVyaW9kRHVyYXRpb24ABQ1ERUZBVUxUUEVSSU9EBAZwZXJpb2QJAGkCBQZoZWlnaHQFAlcyBAt0b3RhbE1hdHVyZQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEOa2V5VG90YWxNYXR1cmUACQEMZ2V0SW50T3JaZXJvAQkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAQJdG90YWxUZWVuCQEMZ2V0SW50T3JaZXJvAQkBDGtleVRvdGFsVGVlbgAECHRvdGFsS2lkCQEMZ2V0SW50T3JaZXJvAQkBC2tleVRvdGFsS2lkAAQKdXNlck1hdHVyZQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQENa2V5VXNlck1hdHVyZQEFDnVzZXJBZGRyZXNzU3RyCQEMZ2V0SW50T3JaZXJvAQkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBCQERQGV4dHJOYXRpdmUoMTA2MikBBQ51c2VyQWRkcmVzc1N0cgQIdXNlclRlZW4JAQxnZXRJbnRPclplcm8BCQELa2V5VXNlclRlZW4BBQ51c2VyQWRkcmVzc1N0cgQHdXNlcktpZAkBDGdldEludE9yWmVybwEJAQprZXlVc2VyS2lkAQUOdXNlckFkZHJlc3NTdHIEAnVtCQEMdXNlckRlY3JlYXNlAgUKdXNlck1hdHVyZQUOYW1vdW50VG9SZW1vdmUEAnV0CQEMdXNlckRlY3JlYXNlAgUIdXNlclRlZW4JAJEDAgUCdW0FCklkeE5ld0RpZmYEAnVrCQEMdXNlckRlY3JlYXNlAgUHdXNlcktpZAkAkQMCBQJ1dAUKSWR4TmV3RGlmZgMJAQIhPQIJAJEDAgUCdWsFCklkeE5ld0RpZmYAAAkAAgECEVNob3VsZCBub3QgaGFwcGVuBAN0bXADCQBmAgUGcGVyaW9kCQEMZ2V0SW50T3JaZXJvAQkBGmtleUxhc3RVc2VyUGVyaW9kUHJvY2Vzc2VkAQUOdXNlckFkZHJlc3NTdHIJAJkKBwkAZAIFC3RvdGFsTWF0dXJlCQCRAwIFAnV0BQtJZHhOZXdHbnNidAkAZAIFCXRvdGFsVGVlbgkAZQIJAJEDAgUCdWsFC0lkeE5ld0duc2J0CQCRAwIFAnV0BQtJZHhOZXdHbnNidAkAZQIFCHRvdGFsS2lkCQCRAwIFAnVrBQtJZHhOZXdHbnNidAkAZAIJAJEDAgUCdW0FC0lkeE5ld0duc2J0CQCRAwIFAnV0BQtJZHhOZXdHbnNidAkAkQMCBQJ1awULSWR4TmV3R25zYnQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBGmtleUxhc3RVc2VyUGVyaW9kUHJvY2Vzc2VkAQUOdXNlckFkZHJlc3NTdHIFBnBlcmlvZAUDbmlsCQCZCgcFC3RvdGFsTWF0dXJlBQl0b3RhbFRlZW4FCHRvdGFsS2lkCQCRAwIFAnVtBQtJZHhOZXdHbnNidAkAkQMCBQJ1dAULSWR4TmV3R25zYnQJAJEDAgUCdWsFC0lkeE5ld0duc2J0BQNuaWwEBnRvdGFscwMJAGYCBQZwZXJpb2QJAQxnZXRJbnRPclplcm8BCQEca2V5TGFzdFRvdGFsc1BlcmlvZFByb2Nlc3NlZAAJAJYKBAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDmtleVRvdGFsTWF0dXJlAAkAZAIIBQN0bXACXzEIBQN0bXACXzIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQxrZXlUb3RhbFRlZW4ACAUDdG1wAl8zCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQELa2V5VG90YWxLaWQAAAAJAMwIAgkBDEludGVnZXJFbnRyeQIJARxrZXlMYXN0VG90YWxzUGVyaW9kUHJvY2Vzc2VkAAUGcGVyaW9kBQNuaWwJAGQCCAUDdG1wAl8xCAUDdG1wAl8yCAUDdG1wAl8zAAAJAJYKBAUDbmlsBQt0b3RhbE1hdHVyZQUJdG90YWxUZWVuBQh0b3RhbEtpZAkAmQoHCQDOCAIJAM0IAgkAzQgCCQDNCAIIBQZ0b3RhbHMCXzEJAQxJbnRlZ2VyRW50cnkCCQENa2V5VXNlck1hdHVyZQEFDnVzZXJBZGRyZXNzU3RyCAUDdG1wAl80CQEMSW50ZWdlckVudHJ5AgkBC2tleVVzZXJUZWVuAQUOdXNlckFkZHJlc3NTdHIIBQN0bXACXzUJAQxJbnRlZ2VyRW50cnkCCQEKa2V5VXNlcktpZAEFDnVzZXJBZGRyZXNzU3RyCAUDdG1wAl82CAUDdG1wAl83CAUGdG90YWxzAl8yCAUGdG90YWxzAl8zCAUGdG90YWxzAl80CAUDdG1wAl80CAUDdG1wAl81CAUDdG1wAl82AQtjb21tb25TdGFrZQILdXNlckFkZHJlc3MBaQQNJHQwMjEwODMyMTEzNwkBD2dldFBhcmFtc09yRmFpbAAEDXN0YWtlZEFzc2V0SWQIBQ0kdDAyMTA4MzIxMTM3Al8xBA1taW5Mb2NrQW1vdW50CAUNJHQwMjEwODMyMTEzNwJfMgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECFUludmFsaWQgcGF5bWVudHMgc2l6ZQQHcGF5bWVudAkAkQMCCAUBaQhwYXltZW50cwAABAZhbW91bnQIBQdwYXltZW50BmFtb3VudAQTaW52YWxpZEFzc2V0TWVzc2FnZQkArAICCQCsAgICD0ludmFsaWQgYXNzZXQuIAkA2AQBBQ1zdGFrZWRBc3NldElkAgwgaXMgZXhwZWN0ZWQEB2Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggFB3BheW1lbnQHYXNzZXRJZAUTaW52YWxpZEFzc2V0TWVzc2FnZQMJAQIhPQIFB2Fzc2V0SWQFDXN0YWtlZEFzc2V0SWQJAAIBBRNpbnZhbGlkQXNzZXRNZXNzYWdlBA51c2VyQWRkcmVzc1N0cgkApQgBBQt1c2VyQWRkcmVzcwQBcgkBB29uU3Rha2UCBQ51c2VyQWRkcmVzc1N0cgUGYW1vdW50BAptZXJnZWREYXRhCQEKbWVyZ2VTdGFrZQQFC3VzZXJBZGRyZXNzBQZhbW91bnQIBQFyAl82CAUBcgJfNwQJaXNOZXdVc2VyCAUKbWVyZ2VkRGF0YQJfMQQMc3Rha2VkQW1vdW50CAUKbWVyZ2VkRGF0YQJfMgQRdnBFZmZlY3RpdmVIZWlnaHQIBQptZXJnZWREYXRhAl8zBA9zdGFrZWRBbW91bnRORVcIBQptZXJnZWREYXRhAl80BBR2cEVmZmVjdGl2ZUhlaWdodE5FVwgFCm1lcmdlZERhdGECXzUDCQBmAgUNbWluTG9ja0Ftb3VudAUPc3Rha2VkQW1vdW50TkVXCQACAQkArAICAhNNaW4gbG9jayBhbW91bnQgaXMgCQCkAwEFDW1pbkxvY2tBbW91bnQEDSR0MDIxOTkxMjIwOTMJAQtTdGF0c1Jlc3VsdAMFBmFtb3VudAABAwUJaXNOZXdVc2VyAAEAAAQMc3RhdHNFbnRyaWVzCAUNJHQwMjE5OTEyMjA5MwJfMQQLdG90YWxTdGFrZWQIBQ0kdDAyMTk5MTIyMDkzAl8yBA50b3RhbFN0YWtlZE5ldwgFDSR0MDIxOTkxMjIwOTMCXzMJAM4IAgkAzggCCQDOCAIJAM4IAgkAzAgCCQESSGlzdG9yeVJlY29yZEVudHJ5BwIFc3Rha2UFC3VzZXJBZGRyZXNzCAUBaQ10cmFuc2FjdGlvbklkBQxzdGFrZWRBbW91bnQFEXZwRWZmZWN0aXZlSGVpZ2h0BQ9zdGFrZWRBbW91bnRORVcFFHZwRWZmZWN0aXZlSGVpZ2h0TkVXBQNuaWwJAQ1SZXdhcmRFbnRyaWVzAwUJaXNOZXdVc2VyBQ51c2VyQWRkcmVzc1N0cgUMc3Rha2VkQW1vdW50CQEPTG9ja1BhcmFtc0VudHJ5AwULdXNlckFkZHJlc3MFD3N0YWtlZEFtb3VudE5FVwUUdnBFZmZlY3RpdmVIZWlnaHRORVcFDHN0YXRzRW50cmllcwgFAXICXzEBC2NvbW1vbkNsYWltAgt1c2VyQWRkcmVzcwFpBA51c2VyQWRkcmVzc1N0cgkApQgBBQt1c2VyQWRkcmVzcwMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhlwYXltZW50cyBhcmUgbm90IGFjY2VwdGVkBA0kdDAyMjYwMDIyNzA1CQELdmFsdWVPckVsc2UCCQETZ2V0VXNlclBhcmFtc09yVW5pdAEFC3VzZXJBZGRyZXNzCQCVCgMGAAAAAAQJaXNOZXdVc2VyCAUNJHQwMjI2MDAyMjcwNQJfMQQMc3Rha2VkQW1vdW50CAUNJHQwMjI2MDAyMjcwNQJfMgQMc3Rha2luZ1N0YXJ0CAUNJHQwMjI2MDAyMjcwNQJfMwQNc3Rha2VkQW1vdW50WAkAtgIBBQxzdGFrZWRBbW91bnQEG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQkBG2tleVVzZXJSZXdhcmRGcm9tRGVwb3NpdE51bQEFDnVzZXJBZGRyZXNzU3RyBA5kZXBvc2l0TnVtVXNlcgkBDGdldEludE9yRWxzZQIFG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQD///////////8BBA5kZXBvc2l0TnVtTGFzdAkBDGdldEludE9yRWxzZQIJARFrZXlEZXBvc2l0TnVtTGFzdAAA////////////AQoBH2ZvckVhY2hBc3NldENhbGNVbmNsYWltZWRSZXdhcmQCBWFjY3VtBWFzc2V0BA0kdDAyMzA3NjIzMjE0CQEKY2FsY1Jld2FyZAUFDnVzZXJBZGRyZXNzU3RyBQVhc3NldAUNc3Rha2VkQW1vdW50WAUOZGVwb3NpdE51bVVzZXIFDmRlcG9zaXROdW1MYXN0BAtyZXdhcmRUb3RhbAgFDSR0MDIzMDc2MjMyMTQCXzEEBmNhY2hlZAgFDSR0MDIzMDc2MjMyMTQCXzIEB2R5bmFtaWMIBQ0kdDAyMzA3NjIzMjE0Al8zBBNyZXdhcmRDYWNoZWRQYXJ0S0VZCAUNJHQwMjMwNzYyMzIxNAJfNAQKY2xhaW1lZEtFWQkBCmtleUNsYWltZWQCBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQEDSR0MDIzMjc0MjMzMTEFBWFjY3VtBARkYXRhCAUNJHQwMjMyNzQyMzMxMQJfMQQRY2xhaW1lZEFtdEJ5QXNzZXQIBQ0kdDAyMzI3NDIzMzExAl8yBAduZXdQYXJ0CQC5CQIJAMwIAgUFYXNzZXQJAMwIAgkApAMBBQtyZXdhcmRUb3RhbAUDbmlsAgE6BBRjbGFpbWVkQW10QnlBc3NldE5ldwkAuQkCCQDMCAIFEWNsYWltZWRBbXRCeUFzc2V0CQDMCAIFB25ld1BhcnQFA25pbAIBXwMJAGcCAAAFC3Jld2FyZFRvdGFsCQCUCgIFBGRhdGEFFGNsYWltZWRBbXRCeUFzc2V0TmV3CQCUCgIJAM0IAgkAzQgCCQDNCAIFBGRhdGEJAQ5TY3JpcHRUcmFuc2ZlcgMFC3VzZXJBZGRyZXNzBQtyZXdhcmRUb3RhbAkBC3RvQXNzZXRWZWN0AQUFYXNzZXQJAQxJbnRlZ2VyRW50cnkCBQpjbGFpbWVkS0VZCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQpjbGFpbWVkS0VZAAAFC3Jld2FyZFRvdGFsCQEMSW50ZWdlckVudHJ5AgUTcmV3YXJkQ2FjaGVkUGFydEtFWQAABRRjbGFpbWVkQW10QnlBc3NldE5ldwQNJHQwMjM3NzEyMzg4NAoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwCAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEfZm9yRWFjaEFzc2V0Q2FsY1VuY2xhaW1lZFJld2FyZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgOQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQQJdHJhbnNmZXJzCAUNJHQwMjM3NzEyMzg4NAJfMQQXY2xhaW1lZEFtdEJ5QXNzZXRSZXN1bHQIBQ0kdDAyMzc3MTIzODg0Al8yAwkAZwIAAAkAkAMBBQl0cmFuc2ZlcnMJAJQKAgUDbmlsAAAJAJQKAgkAzQgCCQDNCAIFCXRyYW5zZmVycwkBDEludGVnZXJFbnRyeQIFG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQUOZGVwb3NpdE51bUxhc3QJARFDbGFpbUhpc3RvcnlFbnRyeQMFC3VzZXJBZGRyZXNzCAUBaQ10cmFuc2FjdGlvbklkCQCwAgIFF2NsYWltZWRBbXRCeUFzc2V0UmVzdWx0AAEJAJADAQUJdHJhbnNmZXJzDAFpAQtjb25zdHJ1Y3RvcgMNbWluTG9ja0Ftb3VudBVzdXBwb3J0ZWRSZXdhcmRBc3NldHMNc3Rha2VkQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEVBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEQa2V5TWluTG9ja0Ftb3VudAAFDW1pbkxvY2tBbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGGtleVN1cHBvcnRlZFJld2FyZEFzc2V0cwAFFXN1cHBvcnRlZFJld2FyZEFzc2V0cwkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5U3Rha2VkQXNzZXRJZAAFDXN0YWtlZEFzc2V0SWQFA25pbAFpAQVzdGFrZQAJAQtjb21tb25TdGFrZQIIBQFpBmNhbGxlcgUBaQFpARNzdGFrZUJ5T3JpZ2luQ2FsbGVyAAkBC2NvbW1vblN0YWtlAggFAWkMb3JpZ2luQ2FsbGVyBQFpAWkBB3Vuc3Rha2UBBmFtb3VudAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECI3Vuc3Rha2UgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50BAt1c2VyQWRkcmVzcwgFAWkGY2FsbGVyBA51c2VyQWRkcmVzc1N0cgkApQgBBQt1c2VyQWRkcmVzcwQNJHQwMjQ4MTgyNDg3MgkBD2dldFBhcmFtc09yRmFpbAAEDXN0YWtlZEFzc2V0SWQIBQ0kdDAyNDgxODI0ODcyAl8xBA1taW5Mb2NrQW1vdW50CAUNJHQwMjQ4MTgyNDg3MgJfMgQNJHQwMjQ4NzUyNDk1OQkBE2dldFVzZXJQYXJhbXNPckZhaWwBBQt1c2VyQWRkcmVzcwQJaXNOZXdVc2VyCAUNJHQwMjQ4NzUyNDk1OQJfMQQMc3Rha2VkQW1vdW50CAUNJHQwMjQ4NzUyNDk1OQJfMgQRdnBFZmZlY3RpdmVIZWlnaHQIBQ0kdDAyNDg3NTI0OTU5Al8zBBBzd2FwUGFyYW1zU1RSVUNUCQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/QcEBRBuZXV0cmlub0NvbnRyYWN0Ahtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgAABQNuaWwFA25pbAQUc3dhcExpbWl0U3BlbnRJblVzZG4IBRBzd2FwUGFyYW1zU1RSVUNUAl8yBA5ibGNrczJMbXRSZXNldAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzMDCQBmAgUUc3dhcExpbWl0U3BlbnRJblVzZG4AAAkAAgEJAKwCAgkArAICAi1Zb3UgaGF2ZSBhbHJlYWR5IG1hZGUgYSBzd2FwIG9wZXJhdGlvbi4gV2FpdCAJAKQDAQkAZAIFBmhlaWdodAUOYmxja3MyTG10UmVzZXQCEiBoZWlnaHQgdG8gdW5zdGFrZQMJAGcCAAAFDHN0YWtlZEFtb3VudAkAAgECEk5vdGhpbmcgdG8gdW5zdGFrZQMJAGYCBQZhbW91bnQFDHN0YWtlZEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICClJlcXVlc3RlZCAJAKQDAQUGYW1vdW50AhIsIGJ1dCBzdGFrZWQgb25seSAJAKQDAQUMc3Rha2VkQW1vdW50BA9zdGFrZWRBbW91bnRORVcJAGUCBQxzdGFrZWRBbW91bnQFBmFtb3VudAQNJHQwMjU1OTcyNTc1NQkBC1N0YXRzUmVzdWx0AwkBAS0BBQZhbW91bnQDCQAAAgUGYW1vdW50BQxzdGFrZWRBbW91bnQA////////////AQAAAwkAAAIFBmFtb3VudAUMc3Rha2VkQW1vdW50AP///////////wEAAAQMc3RhdHNFbnRyaWVzCAUNJHQwMjU1OTcyNTc1NQJfMQQLdG90YWxTdGFrZWQIBQ0kdDAyNTU5NzI1NzU1Al8yBA50b3RhbFN0YWtlZE5ldwgFDSR0MDI1NTk3MjU3NTUCXzMJAM4IAgkAzggCCQDOCAIJAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwUGYW1vdW50BQ1zdGFrZWRBc3NldElkCQDMCAIJARJIaXN0b3J5UmVjb3JkRW50cnkHAgd1bnN0YWtlBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAUMc3Rha2VkQW1vdW50BRF2cEVmZmVjdGl2ZUhlaWdodAUPc3Rha2VkQW1vdW50TkVXBRF2cEVmZmVjdGl2ZUhlaWdodAUDbmlsCQENUmV3YXJkRW50cmllcwMHBQ51c2VyQWRkcmVzc1N0cgUMc3Rha2VkQW1vdW50CQEPTG9ja1BhcmFtc0VudHJ5AwULdXNlckFkZHJlc3MFD3N0YWtlZEFtb3VudE5FVwURdnBFZmZlY3RpdmVIZWlnaHQFDHN0YXRzRW50cmllcwgJAQlvblVuc3Rha2UCBQ51c2VyQWRkcmVzc1N0cgUGYW1vdW50Al8xAWkBB2RlcG9zaXQAAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIfZXhhY3QgMSBwYXltZW50IGlzIGFsbG93ZWQgb25seQQDcG10CQCRAwIIBQFpCHBheW1lbnRzAAAEBmFtb3VudAgFA3BtdAZhbW91bnQECnBtdEFzc2V0SWQJAQt2YWx1ZU9yRWxzZQIIBQNwbXQHYXNzZXRJZAUHV0FWRVNJRAQNcG10QXNzZXRJZFN0cgkA2AQBBQpwbXRBc3NldElkBAhwbXRNdWx0WAMJAAACBQpwbXRBc3NldElkBQdXQVZFU0lEBQZNVUxUWDgFBk1VTFRYNgQHYW1vdW50WAkAtgIBBQZhbW91bnQEC3RvdGFsU3Rha2VkCQEMZ2V0SW50T3JFbHNlAgkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAAABAx0b3RhbFN0YWtlZFgJALYCAQULdG90YWxTdGFrZWQDCQBmAgAABQt0b3RhbFN0YWtlZAkAAgECG1RPRE86IGNhc2UgaXMgbm90IHN1cHBvcnRlZAMJAAACBQt0b3RhbFN0YWtlZAAACQEiSW5jcmVtZW50Tm90RGlzdHJpYnV0ZWRSZXdhcmRFbnRyeQIFDXBtdEFzc2V0SWRTdHIFBmFtb3VudAQQcmV3YXJkUGVyTnNidFgxOAkAvAIDBQdhbW91bnRYBQdNVUxUWDE4BQx0b3RhbFN0YWtlZFgEEWRlcG9zaXROdW1MYXN0S0VZCQERa2V5RGVwb3NpdE51bUxhc3QABA5kZXBvc2l0TnVtTGFzdAkBDGdldEludE9yRWxzZQIFEWRlcG9zaXROdW1MYXN0S0VZAP///////////wEEDWRlcG9zaXROdW1OZXcJAGQCBQ5kZXBvc2l0TnVtTGFzdAABAwkBASEBCQEIY29udGFpbnMCBRJzdXBwb3J0ZWRBc3NldHNTdHIFDXBtdEFzc2V0SWRTdHIJAAIBCQCsAgIJAKwCAgUSc3VwcG9ydGVkQXNzZXRzU3RyAhEgZG9lc24ndCBjb250YWluIAUNcG10QXNzZXRJZFN0cgoBF3JlZnJlc2hSZXdhcmRQZXJOc2J0U1VNAgVhY2N1bQluZXh0QXNzZXQEFnJld2FyZFBlck5zYnRTdW1OZXdLRVkJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ1kZXBvc2l0TnVtTmV3BQluZXh0QXNzZXQECnN1bUxhc3RTdHIJAQxnZXRTdHJPckVsc2UCCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bUxhc3QFCW5leHRBc3NldAIBMAkAzQgCBQVhY2N1bQMJAAACBQluZXh0QXNzZXQFDXBtdEFzc2V0SWRTdHIJAQtTdHJpbmdFbnRyeQIFFnJld2FyZFBlck5zYnRTdW1OZXdLRVkJAKYDAQkAtwICCQCnAwEFCnN1bUxhc3RTdHIFEHJld2FyZFBlck5zYnRYMTgJAQtTdHJpbmdFbnRyeQIFFnJld2FyZFBlck5zYnRTdW1OZXdLRVkFCnN1bUxhc3RTdHIJAM4IAgkAzggCCQDNCAIKAAIkbAUTc3VwcG9ydGVkQXNzZXRzTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEXcmVmcmVzaFJld2FyZFBlck5zYnRTVU0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDkJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkJAQxJbnRlZ2VyRW50cnkCBRFkZXBvc2l0TnVtTGFzdEtFWQUNZGVwb3NpdE51bU5ldwkBFURlcG9zaXRzVG90YWxzRW50cmllcwIFBmFtb3VudAUNcG10QXNzZXRJZFN0cgkBDHVwZGF0ZVRvdGFscwABaQEMY2xhaW1SZXdhcmRzAAkBC2NvbW1vbkNsYWltAggFAWkGY2FsbGVyBQFpAWkBGmNsYWltUmV3YXJkc0J5T3JpZ2luQ2FsbGVyAAkBC2NvbW1vbkNsYWltAggFAWkMb3JpZ2luQ2FsbGVyBQFpAWkBGHVuY2xhaW1lZFJld2FyZHNSRUFET05MWQEOdXNlckFkZHJlc3NTdHIKARZmb3JFYWNoQXNzZXRaZXJvUmV3YXJkAgVhY2N1bQVhc3NldAkArAICCQCsAgIFBWFjY3VtCQC5CQIJAMwIAgUFYXNzZXQJAMwIAgIBMAkAzAgCAgEwBQNuaWwCAToCAV8EEnVuY2xhaW1lZFJld2FyZFN0cgMJAAACBQ51c2VyQWRkcmVzc1N0cgIACgACJGwFE3N1cHBvcnRlZEFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBFmZvckVhY2hBc3NldFplcm9SZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDkJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkEC3VzZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQ51c2VyQWRkcmVzc1N0cgQNJHQwMjg0NzcyODU4MgkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDI4NDc3Mjg1ODICXzEEDHN0YWtlZEFtb3VudAgFDSR0MDI4NDc3Mjg1ODICXzIEDHN0YWtpbmdTdGFydAgFDSR0MDI4NDc3Mjg1ODICXzMEDXN0YWtlZEFtb3VudFgJALYCAQUMc3Rha2VkQW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQ51c2VyQWRkcmVzc1N0cgQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgVhY2N1bQVhc3NldAQNJHQwMjg5MjgyOTA2NgkBCmNhbGNSZXdhcmQFBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQ0kdDAyODkyODI5MDY2Al8xBAZjYWNoZWQIBQ0kdDAyODkyODI5MDY2Al8yBAdkeW5hbWljCAUNJHQwMjg5MjgyOTA2NgJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFDSR0MDI4OTI4MjkwNjYCXzQEB2NsYWltZWQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBCmtleUNsYWltZWQCBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQAAAkArAICCQCsAgIFBWFjY3VtCQC5CQIJAMwIAgUFYXNzZXQJAMwIAgkApAMBBQtyZXdhcmRUb3RhbAkAzAgCCQCkAwEFB2NsYWltZWQFA25pbAIBOgIBXwoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA5CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJCQCUCgIFA25pbAkAswICBRJ1bmNsYWltZWRSZXdhcmRTdHIAAQFpARF1cGRhdGVWb3RpbmdQb3dlcgEOdXNlckFkZHJlc3NTdHIDCQEBIQEJAQlpc0RlZmluZWQBCQCmCAEFDnVzZXJBZGRyZXNzU3RyCQACAQIUSW52YWxpZCB1c2VyIGFkZHJlc3MEAXIJAQdvblN0YWtlAgUOdXNlckFkZHJlc3NTdHIAAAkAlAoCCAUBcgJfMQkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfMgkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfMwkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNAkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNQkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNgkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNwUDbmlsAWkBFnN1cmZTdGFraW5nU1lTUkVBRE9OTFkCFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQhzdXJmRGlmZgQJc3VyZlRvdGFsCQEMZ2V0SW50T3JFbHNlAgkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAAABBJnbnNidEZyb21TdXJmVG90YWwJAQtzdXJmVG9HbnNidAEFCXN1cmZUb3RhbAQBcgMJAGcCBQhzdXJmRGlmZgAACQEHb25TdGFrZQIFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQUIc3VyZkRpZmYJAQlvblVuc3Rha2UCBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkFCHN1cmZEaWZmAwkAAAIFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQIACQCUCgIFA25pbAkAzAgCAAAJAMwIAgUJc3VyZlRvdGFsCQDMCAIAAAkAzAgCBRJnbnNidEZyb21TdXJmVG90YWwJAMwIAgUGaGVpZ2h0CQDMCAIFBmhlaWdodAkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfMgkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfMwkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNAkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNQkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNgkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNwUDbmlsBAt1c2VyQWRkcmVzcwkBD3RvQWRkcmVzc09yRmFpbAEFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQQKbWVyZ2VkRGF0YQkBCm1lcmdlU3Rha2UEBQt1c2VyQWRkcmVzcwUIc3VyZkRpZmYIBQFyAl82CAUBcgJfNwQMc3Rha2VkQW1vdW50CAUKbWVyZ2VkRGF0YQJfMgQRdnBFZmZlY3RpdmVIZWlnaHQIBQptZXJnZWREYXRhAl8zBA9zdGFrZWRBbW91bnRORVcIBQptZXJnZWREYXRhAl80BBR2cEVmZmVjdGl2ZUhlaWdodE5FVwgFCm1lcmdlZERhdGECXzUECHN1cmZVc2VyBQxzdGFrZWRBbW91bnQEEWduc2J0RnJvbVN1cmZVc2VyCQELc3VyZlRvR25zYnQBBQhzdXJmVXNlcgkAlAoCBQNuaWwJAMwIAgUIc3VyZlVzZXIJAMwIAgUJc3VyZlRvdGFsCQDMCAIFEWduc2J0RnJvbVN1cmZVc2VyCQDMCAIFEmduc2J0RnJvbVN1cmZUb3RhbAkAzAgCBRF2cEVmZmVjdGl2ZUhlaWdodAkAzAgCBRR2cEVmZmVjdGl2ZUhlaWdodE5FVwkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfMgkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfMwkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNAkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNQkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNgkAzAgCCQELc3VyZlRvR25zYnQBCAUBcgJfNwUDbmlsAWkBGGduc2J0RnJvbVN1cmZTWVNSRUFET05MWQEHc3VyZkFtdAkAlAoCBQNuaWwJAQtzdXJmVG9HbnNidAEFB3N1cmZBbXQBaQERY29uZmlnU1lTUkVBRE9OTFkABAptaW5Mb2NrQW10CQERQGV4dHJOYXRpdmUoMTA1NSkBCQEQa2V5TWluTG9ja0Ftb3VudAAEIHN1cmZWb3RpbmdQb3dlclJlc3RyaWN0aXZlUGVyaW9kBQ1ERUZBVUxUUEVSSU9EBBticlRvU3RhcnRTdXJmVHJhbnNmb3JtYXRpb24AsJhGCQCUCgIFA25pbAkAzAgCBQptaW5Mb2NrQW10CQDMCAIJAGgCBRJnbnNidEZyb21TdXJmQ29lZmYFBU1VTFQ2CQDMCAIFIHN1cmZWb3RpbmdQb3dlclJlc3RyaWN0aXZlUGVyaW9kCQDMCAIFG2JyVG9TdGFydFN1cmZUcmFuc2Zvcm1hdGlvbgUDbmlsAJG7t6A=", "height": 2326779, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 8jMpDxhfGn11M1m7QqTccXb6n7P8EDQju6YCe2kjdH2J Next: BPc8E4DJmBDdKqE58NFoQaajKT35tKuEqz8aBYMFufUR Diff:
OldNewDifferences
2121
2222 let DAYMILLIS = 86400000
2323
24+let DEFAULTPERIOD = (1440 * 14)
25+
2426 let IdxControlCfgNeutrinoDapp = 1
2527
2628 let IdxControlCfgAuctionDapp = 2
4244 let IdxControlCfgSurfStakingDapp = 10
4345
4446 let IdxControlCfgGnsbtControllerDapp = 11
47+
48+let IdxControlCfgRestV2Dapp = 12
49+
50+let IdxControlCfgGovernanceDapp = 13
4551
4652 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
4753
7076 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
7177
7278 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
79+
80+let govContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
7381
7482 let gnsbtFromSurfCoeff = valueOrElse(getInteger(this, keyGnsbtFromSurfCoeff()), 300)
7583
109117 func keyStatsDepositAmtByDay (timestamp) = makeString(["%s%s%d", "stats", "depositAmtByDay", toString(timestamp)], separator)
110118
111119
112-func keyStatsDepositAmtTotals () = makeString(["%s%s%d", "stats", "depositAmtTotals"], separator)
113-
114-
115-func keyNextPeriod () = "%s__nextPeriod"
120+func keyStatsDepositAmtTotals () = makeString(["%s%s", "stats", "depositAmtTotals"], separator)
116121
117122
118123 func keySupportedRewardAssets () = "supportedRewardAssets"
119124
120125
121-func keyDepositNumLast () = makeString(["%s%s%s", "dep", "lastNum"], separator)
126+func keyDepositNumLast () = makeString(["%s%s", "dep", "lastNum"], separator)
122127
123128
124-func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s%s", "userRwdFromDepNum", userAddress], separator)
129+func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s", "userRwdFromDepNum", userAddress], separator)
125130
126131
127132 func keyRewardPerNsbtSumAt (depositNum,tkn) = makeString(["%s%d", "rwdPerNsbtSumByDepNum", toString(depositNum), tkn], separator)
134139
135140
136141 func keyNotDistributedReward (tkn) = makeString(["%s%s", "notDistributed", tkn], separator)
142+
143+
144+func keyVpPeriodDuration () = makeString(["%s%s", "vp", "periodDuration"], separator)
145+
146+
147+func keyLastTotalsPeriodProcessed () = makeString(["%s%s", "vp", "lastTotalsPeriodProcessed"], separator)
148+
149+
150+func keyLastUserPeriodProcessed (userAddress) = makeString(["%s%s%s", "vp", "lastUserPeriodProcessed", userAddress], separator)
151+
152+
153+func keyTotalMature () = makeString(["%s%s", "vp", "totalMature"], separator)
154+
155+
156+func keyTotalTeen () = makeString(["%s%s", "vp", "totalTeen"], separator)
157+
158+
159+func keyTotalKid () = makeString(["%s%s", "vp", "totalKid"], separator)
160+
161+
162+func keyUserMature (userAddress) = makeString(["%s%s%s", "vp", "userMature", userAddress], separator)
163+
164+
165+func keyUserTeen (userAddress) = makeString(["%s%s%s", "vp", "userTeen", userAddress], separator)
166+
167+
168+func keyUserKid (userAddress) = makeString(["%s%s%s", "vp", "userKid", userAddress], separator)
137169
138170
139171 func toX18 (origVal,origMult) = fraction(toBigInt(origVal), MULTX18, origMult)
272304 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
273305 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
274306 func forEachAssetCacheUserReward (accum,asset) = {
275- let $t01108411219 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
276- let rewardTotal = $t01108411219._1
277- let cached = $t01108411219._2
278- let dynamic = $t01108411219._3
279- let rewardCachedPartKEY = $t01108411219._4
307+ let $t01210412239 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
308+ let rewardTotal = $t01210412239._1
309+ let cached = $t01210412239._2
310+ let dynamic = $t01210412239._3
311+ let rewardCachedPartKEY = $t01210412239._4
280312 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
281313 }
282314
321353 func surfToGnsbt (surfAmt) = (surfAmt / gnsbtFromSurfCoeff)
322354
323355
324-func mergeVotingPowerEffectiveHeight (quarantinePeriod,vpEffectiveHeight,stakedAmt,stakedAmtNEW) = {
325- let remainingToWait = (vpEffectiveHeight - height)
326- if ((0 >= remainingToWait))
327- then (height + quarantinePeriod)
328- else {
329- let alreadyWaited = (quarantinePeriod - remainingToWait)
330- let kX8 = if ((stakedAmtNEW != 0))
331- then fraction(stakedAmt, MULT8, stakedAmtNEW)
332- else vpEffectiveHeight
333- ((quarantinePeriod + height) - fraction(alreadyWaited, kX8, MULT8))
334- }
356+func mergeStake (userAddress,amountToAdd,userTeen,userKid) = {
357+ let $t01516215272 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
358+ let isNewUser = $t01516215272._1
359+ let stakedAmount = $t01516215272._2
360+ let vpEffectiveHeight = $t01516215272._3
361+ let stakedAmountNEW = if (isNewUser)
362+ then amountToAdd
363+ else (amountToAdd + stakedAmount)
364+ let W2 = getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD)
365+ let period = (height / W2)
366+ let vpEffectivePeriodNEW = if ((userKid > 0))
367+ then (period + 2)
368+ else if ((userTeen > 0))
369+ then (period + 1)
370+ else period
371+ $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, (vpEffectivePeriodNEW * W2))
335372 }
336373
337374
338-func mergeStake (userAddress,amountToAdd) = {
339- let $t01487114981 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
340- let isNewUser = $t01487114981._1
341- let stakedAmount = $t01487114981._2
342- let vpEffectiveHeight = $t01487114981._3
343- let stakedAmountNEW = if (isNewUser)
344- then amountToAdd
345- else (amountToAdd + stakedAmount)
346- let quarantinePeriod = (1440 * 14)
347- let vpEffectiveHeightNEW = if (isNewUser)
348- then (quarantinePeriod + height)
349- else mergeVotingPowerEffectiveHeight(quarantinePeriod, vpEffectiveHeight, stakedAmount, stakedAmountNEW)
350- $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)
375+func updateTotals () = {
376+ let period = (height / getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD))
377+ if ((period > getIntOrZero(keyLastTotalsPeriodProcessed())))
378+ then {
379+ let totalMature = valueOrElse(getInteger(keyTotalMature()), getIntOrZero(keyLockParamTotalAmount()))
380+[IntegerEntry(keyTotalMature(), (totalMature + getIntOrZero(keyTotalTeen()))), IntegerEntry(keyTotalTeen(), getIntOrZero(keyTotalKid())), IntegerEntry(keyTotalKid(), 0), IntegerEntry(keyLastTotalsPeriodProcessed(), period)]
381+ }
382+ else nil
351383 }
352384
353385
386+func onStake (userAddressStr,amountToAdd) = if ((0 > amountToAdd))
387+ then throw("amountToAdd should be >= 0")
388+ else {
389+ let W2 = getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD)
390+ let period = (height / W2)
391+ let totalMature = valueOrElse(getInteger(keyTotalMature()), getIntOrZero(keyLockParamTotalAmount()))
392+ let totalTeen = getIntOrZero(keyTotalTeen())
393+ let totalKid = getIntOrZero(keyTotalKid())
394+ let userMature = valueOrElse(getInteger(keyUserMature(userAddressStr)), getIntOrZero(keyLockParamUserAmount(addressFromStringValue(userAddressStr))))
395+ let userTeen = getIntOrZero(keyUserTeen(userAddressStr))
396+ let userKid = getIntOrZero(keyUserKid(userAddressStr))
397+ let tmp = if ((period > getIntOrZero(keyLastUserPeriodProcessed(userAddressStr))))
398+ then $Tuple7((totalMature + userTeen), (totalTeen + (userKid - userTeen)), (totalKid - userKid), (userMature + userTeen), userKid, 0, [IntegerEntry(keyLastUserPeriodProcessed(userAddressStr), period)])
399+ else $Tuple7(totalMature, totalTeen, totalKid, userMature, userTeen, userKid, nil)
400+ let totals = if ((period > getIntOrZero(keyLastTotalsPeriodProcessed())))
401+ then $Tuple4([IntegerEntry(keyTotalMature(), (tmp._1 + tmp._2)), IntegerEntry(keyTotalTeen(), tmp._3), IntegerEntry(keyTotalKid(), 0), IntegerEntry(keyLastTotalsPeriodProcessed(), period)], (tmp._1 + tmp._2), tmp._3, 0)
402+ else $Tuple4(nil, totalMature, totalTeen, totalKid)
403+ let newKid = fraction(amountToAdd, (height % W2), W2)
404+ let newTeen = (amountToAdd - newKid)
405+ $Tuple7(((((totals._1 :+ IntegerEntry(keyUserMature(userAddressStr), tmp._4)) :+ IntegerEntry(keyUserTeen(userAddressStr), (tmp._5 + newTeen))) :+ IntegerEntry(keyUserKid(userAddressStr), (tmp._6 + newKid))) ++ tmp._7), totals._2, totals._3, totals._4, tmp._4, (tmp._5 + newTeen), (tmp._6 + newKid))
406+ }
407+
408+
409+let IdxNewDiff = 0
410+
411+let IdxNewGnsbt = 1
412+
413+func userDecrease (gnsbt,diff) = if ((diff >= gnsbt))
414+ then [(diff - gnsbt), 0]
415+ else [0, (gnsbt - diff)]
416+
417+
418+func onUnstake (userAddressStr,amountToRemove) = if ((amountToRemove >= 0))
419+ then throw("amountToRemove should be < 0")
420+ else {
421+ let W2 = getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD)
422+ let period = (height / W2)
423+ let totalMature = valueOrElse(getInteger(keyTotalMature()), getIntOrZero(keyLockParamTotalAmount()))
424+ let totalTeen = getIntOrZero(keyTotalTeen())
425+ let totalKid = getIntOrZero(keyTotalKid())
426+ let userMature = valueOrElse(getInteger(keyUserMature(userAddressStr)), getIntOrZero(keyLockParamUserAmount(addressFromStringValue(userAddressStr))))
427+ let userTeen = getIntOrZero(keyUserTeen(userAddressStr))
428+ let userKid = getIntOrZero(keyUserKid(userAddressStr))
429+ let um = userDecrease(userMature, amountToRemove)
430+ let ut = userDecrease(userTeen, um[IdxNewDiff])
431+ let uk = userDecrease(userKid, ut[IdxNewDiff])
432+ if ((uk[IdxNewDiff] != 0))
433+ then throw("Should not happen")
434+ else {
435+ let tmp = if ((period > getIntOrZero(keyLastUserPeriodProcessed(userAddressStr))))
436+ then $Tuple7((totalMature + ut[IdxNewGnsbt]), (totalTeen + (uk[IdxNewGnsbt] - ut[IdxNewGnsbt])), (totalKid - uk[IdxNewGnsbt]), (um[IdxNewGnsbt] + ut[IdxNewGnsbt]), uk[IdxNewGnsbt], 0, [IntegerEntry(keyLastUserPeriodProcessed(userAddressStr), period)])
437+ else $Tuple7(totalMature, totalTeen, totalKid, um[IdxNewGnsbt], ut[IdxNewGnsbt], uk[IdxNewGnsbt], nil)
438+ let totals = if ((period > getIntOrZero(keyLastTotalsPeriodProcessed())))
439+ then $Tuple4([IntegerEntry(keyTotalMature(), (tmp._1 + tmp._2)), IntegerEntry(keyTotalTeen(), tmp._3), IntegerEntry(keyTotalKid(), 0), IntegerEntry(keyLastTotalsPeriodProcessed(), period)], (tmp._1 + tmp._2), tmp._3, 0)
440+ else $Tuple4(nil, totalMature, totalTeen, totalKid)
441+ $Tuple7(((((totals._1 :+ IntegerEntry(keyUserMature(userAddressStr), tmp._4)) :+ IntegerEntry(keyUserTeen(userAddressStr), tmp._5)) :+ IntegerEntry(keyUserKid(userAddressStr), tmp._6)) ++ tmp._7), totals._2, totals._3, totals._4, tmp._4, tmp._5, tmp._6)
442+ }
443+ }
444+
445+
354446 func commonStake (userAddress,i) = {
355- let $t01546715521 = getParamsOrFail()
356- let stakedAssetId = $t01546715521._1
357- let minLockAmount = $t01546715521._2
447+ let $t02108321137 = getParamsOrFail()
448+ let stakedAssetId = $t02108321137._1
449+ let minLockAmount = $t02108321137._2
358450 if ((size(i.payments) != 1))
359451 then throw("Invalid payments size")
360452 else {
366458 then throw(invalidAssetMessage)
367459 else {
368460 let userAddressStr = toString(userAddress)
369- let mergedData = mergeStake(userAddress, amount)
461+ let r = onStake(userAddressStr, amount)
462+ let mergedData = mergeStake(userAddress, amount, r._6, r._7)
370463 let isNewUser = mergedData._1
371464 let stakedAmount = mergedData._2
372465 let vpEffectiveHeight = mergedData._3
375468 if ((minLockAmount > stakedAmountNEW))
376469 then throw(("Min lock amount is " + toString(minLockAmount)))
377470 else {
378- let $t01632016422 = StatsResult(amount, 1, if (isNewUser)
471+ let $t02199122093 = StatsResult(amount, 1, if (isNewUser)
379472 then 1
380473 else 0)
381- let statsEntries = $t01632016422._1
382- let totalStaked = $t01632016422._2
383- let totalStakedNew = $t01632016422._3
384- ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries)
474+ let statsEntries = $t02199122093._1
475+ let totalStaked = $t02199122093._2
476+ let totalStakedNew = $t02199122093._3
477+ (((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries) ++ r._1)
385478 }
386479 }
387480 }
393486 if ((size(i.payments) > 0))
394487 then throw("payments are not accepted")
395488 else {
396- let $t01690117006 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
397- let isNewUser = $t01690117006._1
398- let stakedAmount = $t01690117006._2
399- let stakingStart = $t01690117006._3
489+ let $t02260022705 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
490+ let isNewUser = $t02260022705._1
491+ let stakedAmount = $t02260022705._2
492+ let stakingStart = $t02260022705._3
400493 let stakedAmountX = toBigInt(stakedAmount)
401494 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
402495 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
403496 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
404497 func forEachAssetCalcUnclaimedReward (accum,asset) = {
405- let $t01737717515 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
406- let rewardTotal = $t01737717515._1
407- let cached = $t01737717515._2
408- let dynamic = $t01737717515._3
409- let rewardCachedPartKEY = $t01737717515._4
498+ let $t02307623214 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
499+ let rewardTotal = $t02307623214._1
500+ let cached = $t02307623214._2
501+ let dynamic = $t02307623214._3
502+ let rewardCachedPartKEY = $t02307623214._4
410503 let claimedKEY = keyClaimed(userAddressStr, asset)
411- let $t01757517612 = accum
412- let data = $t01757517612._1
413- let claimedAmtByAsset = $t01757517612._2
504+ let $t02327423311 = accum
505+ let data = $t02327423311._1
506+ let claimedAmtByAsset = $t02327423311._2
414507 let newPart = makeString([asset, toString(rewardTotal)], ":")
415508 let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
416509 if ((0 >= rewardTotal))
418511 else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
419512 }
420513
421- let $t01807218185 = {
514+ let $t02377123884 = {
422515 let $l = supportedAssetsList
423516 let $s = size($l)
424517 let $acc0 = $Tuple2(nil, "")
432525
433526 $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)
434527 }
435- let transfers = $t01807218185._1
436- let claimedAmtByAssetResult = $t01807218185._2
528+ let transfers = $t02377123884._1
529+ let claimedAmtByAssetResult = $t02377123884._2
437530 if ((0 >= size(transfers)))
438531 then $Tuple2(nil, 0)
439532 else $Tuple2(((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1))), size(transfers))
464557 else {
465558 let userAddress = i.caller
466559 let userAddressStr = toString(userAddress)
467- let $t01911919173 = getParamsOrFail()
468- let stakedAssetId = $t01911919173._1
469- let minLockAmount = $t01911919173._2
470- let $t01917619260 = getUserParamsOrFail(userAddress)
471- let isNewUser = $t01917619260._1
472- let stakedAmount = $t01917619260._2
473- let vpEffectiveHeight = $t01917619260._3
560+ let $t02481824872 = getParamsOrFail()
561+ let stakedAssetId = $t02481824872._1
562+ let minLockAmount = $t02481824872._2
563+ let $t02487524959 = getUserParamsOrFail(userAddress)
564+ let isNewUser = $t02487524959._1
565+ let stakedAmount = $t02487524959._2
566+ let vpEffectiveHeight = $t02487524959._3
474567 let swapParamsSTRUCT = asSwapParamsSTRUCT(reentrantInvoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStr, 0], nil))
475568 let swapLimitSpentInUsdn = swapParamsSTRUCT._2
476569 let blcks2LmtReset = swapParamsSTRUCT._3
482575 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(stakedAmount)))
483576 else {
484577 let stakedAmountNEW = (stakedAmount - amount)
485- let $t01989820056 = StatsResult(-(amount), if ((amount == stakedAmount))
578+ let $t02559725755 = StatsResult(-(amount), if ((amount == stakedAmount))
486579 then -1
487580 else 0, if ((amount == stakedAmount))
488581 then -1
489582 else 0)
490- let statsEntries = $t01989820056._1
491- let totalStaked = $t01989820056._2
492- let totalStakedNew = $t01989820056._3
493- ((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeight)] ++ RewardEntries(false, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeight)) ++ statsEntries)
583+ let statsEntries = $t02559725755._1
584+ let totalStaked = $t02559725755._2
585+ let totalStakedNew = $t02559725755._3
586+ (((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeight)] ++ RewardEntries(false, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeight)) ++ statsEntries) ++ onUnstake(userAddressStr, amount)._1)
494587 }
495588 }
496589
530623 else StringEntry(rewardPerNsbtSumNewKEY, sumLastStr)))
531624 }
532625
533- (({
626+ ((({
534627 let $l = supportedAssetsList
535628 let $s = size($l)
536629 let $acc0 = nil
543636 else throw("List size exceeds 9")
544637
545638 $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)
546- } :+ IntegerEntry(depositNumLastKEY, depositNumNew)) ++ DepositsTotalsEntries(amount, pmtAssetIdStr))
639+ } :+ IntegerEntry(depositNumLastKEY, depositNumNew)) ++ DepositsTotalsEntries(amount, pmtAssetIdStr)) ++ updateTotals())
547640 }
548641 }
549642 }
581674 }
582675 else {
583676 let userAddress = addressFromStringValue(userAddressStr)
584- let $t02268022785 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
585- let isNewUser = $t02268022785._1
586- let stakedAmount = $t02268022785._2
587- let stakingStart = $t02268022785._3
677+ let $t02847728582 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
678+ let isNewUser = $t02847728582._1
679+ let stakedAmount = $t02847728582._2
680+ let stakingStart = $t02847728582._3
588681 let stakedAmountX = toBigInt(stakedAmount)
589682 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
590683 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
591684 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
592685 func forEachAssetCalcUnclaimedReward (accum,asset) = {
593- let $t02313123269 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
594- let rewardTotal = $t02313123269._1
595- let cached = $t02313123269._2
596- let dynamic = $t02313123269._3
597- let rewardCachedPartKEY = $t02313123269._4
686+ let $t02892829066 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
687+ let rewardTotal = $t02892829066._1
688+ let cached = $t02892829066._2
689+ let dynamic = $t02892829066._3
690+ let rewardCachedPartKEY = $t02892829066._4
598691 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
599692 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
600693 }
618711
619712
620713 @Callable(i)
714+func updateVotingPower (userAddressStr) = if (!(isDefined(addressFromString(userAddressStr))))
715+ then throw("Invalid user address")
716+ else {
717+ let r = onStake(userAddressStr, 0)
718+ $Tuple2(r._1, [surfToGnsbt(r._2), surfToGnsbt(r._3), surfToGnsbt(r._4), surfToGnsbt(r._5), surfToGnsbt(r._6), surfToGnsbt(r._7)])
719+ }
720+
721+
722+
723+@Callable(i)
621724 func surfStakingSYSREADONLY (userAddressStrOrEmpty,surfDiff) = {
622725 let surfTotal = getIntOrElse(keyLockParamTotalAmount(), 0)
623726 let gnsbtFromSurfTotal = surfToGnsbt(surfTotal)
727+ let r = if ((surfDiff >= 0))
728+ then onStake(userAddressStrOrEmpty, surfDiff)
729+ else onUnstake(userAddressStrOrEmpty, surfDiff)
624730 if ((userAddressStrOrEmpty == ""))
625- then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, 0, height, height])
731+ then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, height, height, surfToGnsbt(r._2), surfToGnsbt(r._3), surfToGnsbt(r._4), surfToGnsbt(r._5), surfToGnsbt(r._6), surfToGnsbt(r._7)])
626732 else {
627733 let userAddress = toAddressOrFail(userAddressStrOrEmpty)
628- let mergedData = mergeStake(userAddress, surfDiff)
629- let isNewUser = mergedData._1
734+ let mergedData = mergeStake(userAddress, surfDiff, r._6, r._7)
630735 let stakedAmount = mergedData._2
631736 let vpEffectiveHeight = mergedData._3
632737 let stakedAmountNEW = mergedData._4
633738 let vpEffectiveHeightNEW = mergedData._5
634739 let surfUser = stakedAmount
635740 let gnsbtFromSurfUser = surfToGnsbt(surfUser)
636- $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, vpEffectiveHeight, vpEffectiveHeightNEW])
741+ $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, vpEffectiveHeight, vpEffectiveHeightNEW, surfToGnsbt(r._2), surfToGnsbt(r._3), surfToGnsbt(r._4), surfToGnsbt(r._5), surfToGnsbt(r._6), surfToGnsbt(r._7)])
637742 }
638743 }
639744
647752 @Callable(i)
648753 func configSYSREADONLY () = {
649754 let minLockAmt = getIntegerValue(keyMinLockAmount())
650- let surfVotingPowerRestrictivePeriod = (1440 * 14)
755+ let surfVotingPowerRestrictivePeriod = DEFAULTPERIOD
651756 let brToStartSurfTransformation = 1150000
652757 $Tuple2(nil, [minLockAmt, (gnsbtFromSurfCoeff * MULT6), surfVotingPowerRestrictivePeriod, brToStartSurfTransformation])
653758 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let SEP = "__"
77
88 let MULT6 = 1000000
99
1010 let MULT8 = 100000000
1111
1212 let MULTX6 = toBigInt(MULT6)
1313
1414 let MULTX8 = toBigInt(MULT8)
1515
1616 let MULTX18 = toBigInt(1000000000000000000)
1717
1818 let WAVESIDSTR = "WAVES"
1919
2020 let WAVESID = fromBase58String(WAVESIDSTR)
2121
2222 let DAYMILLIS = 86400000
2323
24+let DEFAULTPERIOD = (1440 * 14)
25+
2426 let IdxControlCfgNeutrinoDapp = 1
2527
2628 let IdxControlCfgAuctionDapp = 2
2729
2830 let IdxControlCfgRpdDapp = 3
2931
3032 let IdxControlCfgMathDapp = 4
3133
3234 let IdxControlCfgLiquidationDapp = 5
3335
3436 let IdxControlCfgRestDapp = 6
3537
3638 let IdxControlCfgNodeRegistryDapp = 7
3739
3840 let IdxControlCfgNsbtStakingDapp = 8
3941
4042 let IdxControlCfgMediatorDapp = 9
4143
4244 let IdxControlCfgSurfStakingDapp = 10
4345
4446 let IdxControlCfgGnsbtControllerDapp = 11
47+
48+let IdxControlCfgRestV2Dapp = 12
49+
50+let IdxControlCfgGovernanceDapp = 13
4551
4652 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
4753
4854
4955 func keyControlAddress () = "%s%s__config__controlAddress"
5056
5157
5258 func keyControlCfg () = "%s__controlConfig"
5359
5460
5561 func keyGnsbtFromSurfCoeff () = "%s%s__cfg__gnsbtFromSurfCoeff"
5662
5763
5864 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
5965
6066
6167 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
6268
6369
6470 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3N4NS7d4Jo9a6F14LiFUKKYVdUkkf2eP4Zx"))
6571
6672 let controlCfg = readControlCfgOrFail(controlContract)
6773
6874 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
6975
7076 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
7177
7278 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
79+
80+let govContract = getContractAddressOrFail(controlCfg, IdxControlCfgGovernanceDapp)
7381
7482 let gnsbtFromSurfCoeff = valueOrElse(getInteger(this, keyGnsbtFromSurfCoeff()), 300)
7583
7684 func keyBondAsset () = "bond_asset_id"
7785
7886
7987 func keyAuctionContractAddress () = "auction_contract"
8088
8189
8290 func keyMinLockAmount () = "%s__minLockAmount"
8391
8492
8593 func keyStakedAssetId () = "%s__stakedAssetId"
8694
8795
8896 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "amount"], separator)
8997
9098
9199 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
92100
93101
94102 func keyLockParamVotingPowerEffectiveHeight (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "vpEffectiveHeight"], separator)
95103
96104
97105 func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
98106
99107
100108 func keyLockParamTotalAmount () = makeString(["%s%s", "stats", "activeTotalLocked"], separator)
101109
102110
103111 func keyStatsLocksCount () = makeString(["%s%s", "stats", "locksCount"], separator)
104112
105113
106114 func keyStatsUsersCount () = makeString(["%s%s", "stats", "activeUsersCount"], separator)
107115
108116
109117 func keyStatsDepositAmtByDay (timestamp) = makeString(["%s%s%d", "stats", "depositAmtByDay", toString(timestamp)], separator)
110118
111119
112-func keyStatsDepositAmtTotals () = makeString(["%s%s%d", "stats", "depositAmtTotals"], separator)
113-
114-
115-func keyNextPeriod () = "%s__nextPeriod"
120+func keyStatsDepositAmtTotals () = makeString(["%s%s", "stats", "depositAmtTotals"], separator)
116121
117122
118123 func keySupportedRewardAssets () = "supportedRewardAssets"
119124
120125
121-func keyDepositNumLast () = makeString(["%s%s%s", "dep", "lastNum"], separator)
126+func keyDepositNumLast () = makeString(["%s%s", "dep", "lastNum"], separator)
122127
123128
124-func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s%s", "userRwdFromDepNum", userAddress], separator)
129+func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s", "userRwdFromDepNum", userAddress], separator)
125130
126131
127132 func keyRewardPerNsbtSumAt (depositNum,tkn) = makeString(["%s%d", "rwdPerNsbtSumByDepNum", toString(depositNum), tkn], separator)
128133
129134
130135 func keyReward (userAddress,tkn) = makeString(["%s%s%s", "rwd", userAddress, tkn], separator)
131136
132137
133138 func keyClaimed (userAddress,tkn) = makeString(["%s%s%s", "clm", userAddress, tkn], separator)
134139
135140
136141 func keyNotDistributedReward (tkn) = makeString(["%s%s", "notDistributed", tkn], separator)
142+
143+
144+func keyVpPeriodDuration () = makeString(["%s%s", "vp", "periodDuration"], separator)
145+
146+
147+func keyLastTotalsPeriodProcessed () = makeString(["%s%s", "vp", "lastTotalsPeriodProcessed"], separator)
148+
149+
150+func keyLastUserPeriodProcessed (userAddress) = makeString(["%s%s%s", "vp", "lastUserPeriodProcessed", userAddress], separator)
151+
152+
153+func keyTotalMature () = makeString(["%s%s", "vp", "totalMature"], separator)
154+
155+
156+func keyTotalTeen () = makeString(["%s%s", "vp", "totalTeen"], separator)
157+
158+
159+func keyTotalKid () = makeString(["%s%s", "vp", "totalKid"], separator)
160+
161+
162+func keyUserMature (userAddress) = makeString(["%s%s%s", "vp", "userMature", userAddress], separator)
163+
164+
165+func keyUserTeen (userAddress) = makeString(["%s%s%s", "vp", "userTeen", userAddress], separator)
166+
167+
168+func keyUserKid (userAddress) = makeString(["%s%s%s", "vp", "userKid", userAddress], separator)
137169
138170
139171 func toX18 (origVal,origMult) = fraction(toBigInt(origVal), MULTX18, origMult)
140172
141173
142174 func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
143175
144176
145177 func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
146178
147179
148180 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
149181
150182
151183 func getStrOrElse (key,defaultVal) = valueOrElse(getString(this, key), defaultVal)
152184
153185
154186 func toAddressOrFail (addressStr) = valueOrErrorMessage(addressFromString(addressStr), ("couldn't parse passed addressStr=" + addressStr))
155187
156188
157189 func toAssetVect (assetStr) = if ((assetStr == WAVESIDSTR))
158190 then unit
159191 else fromBase58String(assetStr)
160192
161193
162194 func asInt (val) = match val {
163195 case valInt: Int =>
164196 valInt
165197 case _ =>
166198 throw("fail to cast into Int")
167199 }
168200
169201
170202 func asSwapParamsSTRUCT (v) = match v {
171203 case struct: (Int, Int, Int, Int, Int, Int, Int) =>
172204 struct
173205 case _ =>
174206 throw("fail to cast into Int")
175207 }
176208
177209
178210 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)
179211
180212
181213 func formatClaimHistoryRecord (user,claimedRewards) = makeString(["%s%d%d%s", user, toString(lastBlock.height), toString(lastBlock.timestamp), claimedRewards], separator)
182214
183215
184216 func HistoryRecordEntry (type,userAddress,txId,oldAmount,oldStart,newAmount,newStart) = StringEntry(keyHistoryRecord(type, userAddress, txId), formatHistoryRecord(oldAmount, oldStart, newAmount, newStart))
185217
186218
187219 func ClaimHistoryEntry (userAddress,txId,claimedRewards) = StringEntry(keyHistoryRecord("claim", userAddress, txId), formatClaimHistoryRecord(toString(userAddress), claimedRewards))
188220
189221
190222 func StatsResult (totalLockedInc,lockCountInc,usersCountInc) = {
191223 let locksCount = getIntOrZero(keyStatsLocksCount())
192224 let usersCount = getIntOrZero(keyStatsUsersCount())
193225 let totalAmount = getIntOrZero(keyLockParamTotalAmount())
194226 let totalAmountNew = (totalAmount + totalLockedInc)
195227 $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew)], totalAmount, totalAmountNew)
196228 }
197229
198230
199231 func LockParamsEntry (userAddress,amount,votingPowerEffectiveHeight) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), votingPowerEffectiveHeight)]
200232
201233
202234 func getParamsOrFail () = $Tuple2(fromBase58String(getStringOrFail(this, keyStakedAssetId())), getIntOrFail(keyMinLockAmount()))
203235
204236
205237 func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
206238
207239
208240 func getUserParamsOrUnit (userAddress) = if (isActiveUser(userAddress))
209241 then $Tuple3(false, getIntOrFail(keyLockParamUserAmount(userAddress)), getIntOrFail(keyLockParamStartBlock(userAddress)))
210242 else unit
211243
212244
213245 func getUserParamsOrFail (userAddress) = valueOrErrorMessage(getUserParamsOrUnit(userAddress), (("User " + toString(userAddress)) + " is not defined"))
214246
215247
216248 let supportedAssetsStr = getStrOrElse(keySupportedRewardAssets(), "")
217249
218250 let supportedAssetsList = split(supportedAssetsStr, "_")
219251
220252 func calcReward (userAddress,assetId,stakedAmountX,depositNumUser,depositNumLast) = {
221253 let rewardPerNsbtSumLastKEY = keyRewardPerNsbtSumAt(depositNumLast, assetId)
222254 let sumLastX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, assetId), "0"))
223255 let sumUserX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumUser, assetId), "0"))
224256 let rewardDynamicPart = toInt(fraction((sumLastX18 - sumUserX18), stakedAmountX, MULTX18))
225257 let rewardCachedPartKEY = keyReward(userAddress, assetId)
226258 let rewardCachedPart = getIntOrElse(rewardCachedPartKEY, 0)
227259 $Tuple4((rewardCachedPart + rewardDynamicPart), rewardCachedPart, rewardDynamicPart, rewardCachedPartKEY)
228260 }
229261
230262
231263 func toStartOfDay (timestamp) = ((timestamp / DAYMILLIS) * DAYMILLIS)
232264
233265
234266 func findElementPosition (src,element,sep) = {
235267 let elementStart = valueOrErrorMessage(indexOf(src, element), ((("there is no substring " + element) + " in ") + src))
236268 if ((elementStart == 0))
237269 then 0
238270 else {
239271 let left = take(src, elementStart)
240272 (size(split(left, sep)) - 1)
241273 }
242274 }
243275
244276
245277 let DepositTotalsPREFIX = "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
246278
247279 func updateDepositTotals (currVal,idxToUpdate,deltaAmt) = {
248280 let currArr = split(currVal, SEP)
249281 func updDepTotByIdx (idx) = if ((idx != idxToUpdate))
250282 then currArr[idx]
251283 else toString((parseIntValue(currArr[idx]) + deltaAmt))
252284
253285 makeString([DepositTotalsPREFIX, updDepTotByIdx(1), updDepTotByIdx(2), updDepTotByIdx(3), updDepTotByIdx(4), updDepTotByIdx(5), updDepTotByIdx(6), updDepTotByIdx(7), updDepTotByIdx(8), updDepTotByIdx(9), updDepTotByIdx(10), updDepTotByIdx(11), updDepTotByIdx(12), updDepTotByIdx(13), updDepTotByIdx(14), updDepTotByIdx(15), updDepTotByIdx(16), updDepTotByIdx(17), updDepTotByIdx(18)], SEP)
254286 }
255287
256288
257289 func DepositsTotalsEntries (depositAmount,assetIdStr) = {
258290 let startOfDay = toStartOfDay(lastBlock.timestamp)
259291 let byDayKEY = keyStatsDepositAmtByDay(startOfDay)
260292 let totalsKEY = keyStatsDepositAmtTotals()
261293 let position = findElementPosition(supportedAssetsStr, assetIdStr, "_")
262294 let defaultDATA = (DepositTotalsPREFIX + "__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0__0")
263295 let currTotalsDATA = valueOrElse(getString(this, totalsKEY), defaultDATA)
264296 let newTotalsDATA = updateDepositTotals(currTotalsDATA, (position + 1), depositAmount)
265297 [StringEntry(totalsKEY, newTotalsDATA), StringEntry(byDayKEY, newTotalsDATA)]
266298 }
267299
268300
269301 func RewardEntries (isNewUser,userAddress,stakedAmount) = {
270302 let stakedAmountX = toBigInt(stakedAmount)
271303 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddress)
272304 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
273305 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
274306 func forEachAssetCacheUserReward (accum,asset) = {
275- let $t01108411219 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
276- let rewardTotal = $t01108411219._1
277- let cached = $t01108411219._2
278- let dynamic = $t01108411219._3
279- let rewardCachedPartKEY = $t01108411219._4
307+ let $t01210412239 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
308+ let rewardTotal = $t01210412239._1
309+ let cached = $t01210412239._2
310+ let dynamic = $t01210412239._3
311+ let rewardCachedPartKEY = $t01210412239._4
280312 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
281313 }
282314
283315 if (if ((depositNumLast == -1))
284316 then (depositNumUser == -1)
285317 else false)
286318 then nil
287319 else if (if ((depositNumLast == -1))
288320 then (depositNumUser > -1)
289321 else false)
290322 then throw("invalid depositNumLast and depositNumUser state")
291323 else if (if ((depositNumLast > -1))
292324 then (depositNumUser >= -1)
293325 else false)
294326 then if (isNewUser)
295327 then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
296328 else ({
297329 let $l = supportedAssetsList
298330 let $s = size($l)
299331 let $acc0 = nil
300332 func $f0_1 ($a,$i) = if (($i >= $s))
301333 then $a
302334 else forEachAssetCacheUserReward($a, $l[$i])
303335
304336 func $f0_2 ($a,$i) = if (($i >= $s))
305337 then $a
306338 else throw("List size exceeds 9")
307339
308340 $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)
309341 } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
310342 else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
311343 }
312344
313345
314346 func IncrementNotDistributedRewardEntry (tkn,amountInc) = {
315347 let notDistributedRewardKEY = keyNotDistributedReward(tkn)
316348 let notDistributedReward = getIntOrElse(notDistributedRewardKEY, 0)
317349 [IntegerEntry(notDistributedRewardKEY, (notDistributedReward + amountInc))]
318350 }
319351
320352
321353 func surfToGnsbt (surfAmt) = (surfAmt / gnsbtFromSurfCoeff)
322354
323355
324-func mergeVotingPowerEffectiveHeight (quarantinePeriod,vpEffectiveHeight,stakedAmt,stakedAmtNEW) = {
325- let remainingToWait = (vpEffectiveHeight - height)
326- if ((0 >= remainingToWait))
327- then (height + quarantinePeriod)
328- else {
329- let alreadyWaited = (quarantinePeriod - remainingToWait)
330- let kX8 = if ((stakedAmtNEW != 0))
331- then fraction(stakedAmt, MULT8, stakedAmtNEW)
332- else vpEffectiveHeight
333- ((quarantinePeriod + height) - fraction(alreadyWaited, kX8, MULT8))
334- }
356+func mergeStake (userAddress,amountToAdd,userTeen,userKid) = {
357+ let $t01516215272 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
358+ let isNewUser = $t01516215272._1
359+ let stakedAmount = $t01516215272._2
360+ let vpEffectiveHeight = $t01516215272._3
361+ let stakedAmountNEW = if (isNewUser)
362+ then amountToAdd
363+ else (amountToAdd + stakedAmount)
364+ let W2 = getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD)
365+ let period = (height / W2)
366+ let vpEffectivePeriodNEW = if ((userKid > 0))
367+ then (period + 2)
368+ else if ((userTeen > 0))
369+ then (period + 1)
370+ else period
371+ $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, (vpEffectivePeriodNEW * W2))
335372 }
336373
337374
338-func mergeStake (userAddress,amountToAdd) = {
339- let $t01487114981 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
340- let isNewUser = $t01487114981._1
341- let stakedAmount = $t01487114981._2
342- let vpEffectiveHeight = $t01487114981._3
343- let stakedAmountNEW = if (isNewUser)
344- then amountToAdd
345- else (amountToAdd + stakedAmount)
346- let quarantinePeriod = (1440 * 14)
347- let vpEffectiveHeightNEW = if (isNewUser)
348- then (quarantinePeriod + height)
349- else mergeVotingPowerEffectiveHeight(quarantinePeriod, vpEffectiveHeight, stakedAmount, stakedAmountNEW)
350- $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)
375+func updateTotals () = {
376+ let period = (height / getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD))
377+ if ((period > getIntOrZero(keyLastTotalsPeriodProcessed())))
378+ then {
379+ let totalMature = valueOrElse(getInteger(keyTotalMature()), getIntOrZero(keyLockParamTotalAmount()))
380+[IntegerEntry(keyTotalMature(), (totalMature + getIntOrZero(keyTotalTeen()))), IntegerEntry(keyTotalTeen(), getIntOrZero(keyTotalKid())), IntegerEntry(keyTotalKid(), 0), IntegerEntry(keyLastTotalsPeriodProcessed(), period)]
381+ }
382+ else nil
351383 }
352384
353385
386+func onStake (userAddressStr,amountToAdd) = if ((0 > amountToAdd))
387+ then throw("amountToAdd should be >= 0")
388+ else {
389+ let W2 = getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD)
390+ let period = (height / W2)
391+ let totalMature = valueOrElse(getInteger(keyTotalMature()), getIntOrZero(keyLockParamTotalAmount()))
392+ let totalTeen = getIntOrZero(keyTotalTeen())
393+ let totalKid = getIntOrZero(keyTotalKid())
394+ let userMature = valueOrElse(getInteger(keyUserMature(userAddressStr)), getIntOrZero(keyLockParamUserAmount(addressFromStringValue(userAddressStr))))
395+ let userTeen = getIntOrZero(keyUserTeen(userAddressStr))
396+ let userKid = getIntOrZero(keyUserKid(userAddressStr))
397+ let tmp = if ((period > getIntOrZero(keyLastUserPeriodProcessed(userAddressStr))))
398+ then $Tuple7((totalMature + userTeen), (totalTeen + (userKid - userTeen)), (totalKid - userKid), (userMature + userTeen), userKid, 0, [IntegerEntry(keyLastUserPeriodProcessed(userAddressStr), period)])
399+ else $Tuple7(totalMature, totalTeen, totalKid, userMature, userTeen, userKid, nil)
400+ let totals = if ((period > getIntOrZero(keyLastTotalsPeriodProcessed())))
401+ then $Tuple4([IntegerEntry(keyTotalMature(), (tmp._1 + tmp._2)), IntegerEntry(keyTotalTeen(), tmp._3), IntegerEntry(keyTotalKid(), 0), IntegerEntry(keyLastTotalsPeriodProcessed(), period)], (tmp._1 + tmp._2), tmp._3, 0)
402+ else $Tuple4(nil, totalMature, totalTeen, totalKid)
403+ let newKid = fraction(amountToAdd, (height % W2), W2)
404+ let newTeen = (amountToAdd - newKid)
405+ $Tuple7(((((totals._1 :+ IntegerEntry(keyUserMature(userAddressStr), tmp._4)) :+ IntegerEntry(keyUserTeen(userAddressStr), (tmp._5 + newTeen))) :+ IntegerEntry(keyUserKid(userAddressStr), (tmp._6 + newKid))) ++ tmp._7), totals._2, totals._3, totals._4, tmp._4, (tmp._5 + newTeen), (tmp._6 + newKid))
406+ }
407+
408+
409+let IdxNewDiff = 0
410+
411+let IdxNewGnsbt = 1
412+
413+func userDecrease (gnsbt,diff) = if ((diff >= gnsbt))
414+ then [(diff - gnsbt), 0]
415+ else [0, (gnsbt - diff)]
416+
417+
418+func onUnstake (userAddressStr,amountToRemove) = if ((amountToRemove >= 0))
419+ then throw("amountToRemove should be < 0")
420+ else {
421+ let W2 = getIntOrElse(keyVpPeriodDuration(), DEFAULTPERIOD)
422+ let period = (height / W2)
423+ let totalMature = valueOrElse(getInteger(keyTotalMature()), getIntOrZero(keyLockParamTotalAmount()))
424+ let totalTeen = getIntOrZero(keyTotalTeen())
425+ let totalKid = getIntOrZero(keyTotalKid())
426+ let userMature = valueOrElse(getInteger(keyUserMature(userAddressStr)), getIntOrZero(keyLockParamUserAmount(addressFromStringValue(userAddressStr))))
427+ let userTeen = getIntOrZero(keyUserTeen(userAddressStr))
428+ let userKid = getIntOrZero(keyUserKid(userAddressStr))
429+ let um = userDecrease(userMature, amountToRemove)
430+ let ut = userDecrease(userTeen, um[IdxNewDiff])
431+ let uk = userDecrease(userKid, ut[IdxNewDiff])
432+ if ((uk[IdxNewDiff] != 0))
433+ then throw("Should not happen")
434+ else {
435+ let tmp = if ((period > getIntOrZero(keyLastUserPeriodProcessed(userAddressStr))))
436+ then $Tuple7((totalMature + ut[IdxNewGnsbt]), (totalTeen + (uk[IdxNewGnsbt] - ut[IdxNewGnsbt])), (totalKid - uk[IdxNewGnsbt]), (um[IdxNewGnsbt] + ut[IdxNewGnsbt]), uk[IdxNewGnsbt], 0, [IntegerEntry(keyLastUserPeriodProcessed(userAddressStr), period)])
437+ else $Tuple7(totalMature, totalTeen, totalKid, um[IdxNewGnsbt], ut[IdxNewGnsbt], uk[IdxNewGnsbt], nil)
438+ let totals = if ((period > getIntOrZero(keyLastTotalsPeriodProcessed())))
439+ then $Tuple4([IntegerEntry(keyTotalMature(), (tmp._1 + tmp._2)), IntegerEntry(keyTotalTeen(), tmp._3), IntegerEntry(keyTotalKid(), 0), IntegerEntry(keyLastTotalsPeriodProcessed(), period)], (tmp._1 + tmp._2), tmp._3, 0)
440+ else $Tuple4(nil, totalMature, totalTeen, totalKid)
441+ $Tuple7(((((totals._1 :+ IntegerEntry(keyUserMature(userAddressStr), tmp._4)) :+ IntegerEntry(keyUserTeen(userAddressStr), tmp._5)) :+ IntegerEntry(keyUserKid(userAddressStr), tmp._6)) ++ tmp._7), totals._2, totals._3, totals._4, tmp._4, tmp._5, tmp._6)
442+ }
443+ }
444+
445+
354446 func commonStake (userAddress,i) = {
355- let $t01546715521 = getParamsOrFail()
356- let stakedAssetId = $t01546715521._1
357- let minLockAmount = $t01546715521._2
447+ let $t02108321137 = getParamsOrFail()
448+ let stakedAssetId = $t02108321137._1
449+ let minLockAmount = $t02108321137._2
358450 if ((size(i.payments) != 1))
359451 then throw("Invalid payments size")
360452 else {
361453 let payment = i.payments[0]
362454 let amount = payment.amount
363455 let invalidAssetMessage = (("Invalid asset. " + toBase58String(stakedAssetId)) + " is expected")
364456 let assetId = valueOrErrorMessage(payment.assetId, invalidAssetMessage)
365457 if ((assetId != stakedAssetId))
366458 then throw(invalidAssetMessage)
367459 else {
368460 let userAddressStr = toString(userAddress)
369- let mergedData = mergeStake(userAddress, amount)
461+ let r = onStake(userAddressStr, amount)
462+ let mergedData = mergeStake(userAddress, amount, r._6, r._7)
370463 let isNewUser = mergedData._1
371464 let stakedAmount = mergedData._2
372465 let vpEffectiveHeight = mergedData._3
373466 let stakedAmountNEW = mergedData._4
374467 let vpEffectiveHeightNEW = mergedData._5
375468 if ((minLockAmount > stakedAmountNEW))
376469 then throw(("Min lock amount is " + toString(minLockAmount)))
377470 else {
378- let $t01632016422 = StatsResult(amount, 1, if (isNewUser)
471+ let $t02199122093 = StatsResult(amount, 1, if (isNewUser)
379472 then 1
380473 else 0)
381- let statsEntries = $t01632016422._1
382- let totalStaked = $t01632016422._2
383- let totalStakedNew = $t01632016422._3
384- ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries)
474+ let statsEntries = $t02199122093._1
475+ let totalStaked = $t02199122093._2
476+ let totalStakedNew = $t02199122093._3
477+ (((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries) ++ r._1)
385478 }
386479 }
387480 }
388481 }
389482
390483
391484 func commonClaim (userAddress,i) = {
392485 let userAddressStr = toString(userAddress)
393486 if ((size(i.payments) > 0))
394487 then throw("payments are not accepted")
395488 else {
396- let $t01690117006 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
397- let isNewUser = $t01690117006._1
398- let stakedAmount = $t01690117006._2
399- let stakingStart = $t01690117006._3
489+ let $t02260022705 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
490+ let isNewUser = $t02260022705._1
491+ let stakedAmount = $t02260022705._2
492+ let stakingStart = $t02260022705._3
400493 let stakedAmountX = toBigInt(stakedAmount)
401494 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
402495 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
403496 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
404497 func forEachAssetCalcUnclaimedReward (accum,asset) = {
405- let $t01737717515 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
406- let rewardTotal = $t01737717515._1
407- let cached = $t01737717515._2
408- let dynamic = $t01737717515._3
409- let rewardCachedPartKEY = $t01737717515._4
498+ let $t02307623214 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
499+ let rewardTotal = $t02307623214._1
500+ let cached = $t02307623214._2
501+ let dynamic = $t02307623214._3
502+ let rewardCachedPartKEY = $t02307623214._4
410503 let claimedKEY = keyClaimed(userAddressStr, asset)
411- let $t01757517612 = accum
412- let data = $t01757517612._1
413- let claimedAmtByAsset = $t01757517612._2
504+ let $t02327423311 = accum
505+ let data = $t02327423311._1
506+ let claimedAmtByAsset = $t02327423311._2
414507 let newPart = makeString([asset, toString(rewardTotal)], ":")
415508 let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
416509 if ((0 >= rewardTotal))
417510 then $Tuple2(data, claimedAmtByAssetNew)
418511 else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
419512 }
420513
421- let $t01807218185 = {
514+ let $t02377123884 = {
422515 let $l = supportedAssetsList
423516 let $s = size($l)
424517 let $acc0 = $Tuple2(nil, "")
425518 func $f0_1 ($a,$i) = if (($i >= $s))
426519 then $a
427520 else forEachAssetCalcUnclaimedReward($a, $l[$i])
428521
429522 func $f0_2 ($a,$i) = if (($i >= $s))
430523 then $a
431524 else throw("List size exceeds 9")
432525
433526 $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)
434527 }
435- let transfers = $t01807218185._1
436- let claimedAmtByAssetResult = $t01807218185._2
528+ let transfers = $t02377123884._1
529+ let claimedAmtByAssetResult = $t02377123884._2
437530 if ((0 >= size(transfers)))
438531 then $Tuple2(nil, 0)
439532 else $Tuple2(((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1))), size(transfers))
440533 }
441534 }
442535
443536
444537 @Callable(i)
445538 func constructor (minLockAmount,supportedRewardAssets,stakedAssetId) = if ((i.caller != this))
446539 then throw("Permission denied")
447540 else [IntegerEntry(keyMinLockAmount(), minLockAmount), StringEntry(keySupportedRewardAssets(), supportedRewardAssets), StringEntry(keyStakedAssetId(), stakedAssetId)]
448541
449542
450543
451544 @Callable(i)
452545 func stake () = commonStake(i.caller, i)
453546
454547
455548
456549 @Callable(i)
457550 func stakeByOriginCaller () = commonStake(i.originCaller, i)
458551
459552
460553
461554 @Callable(i)
462555 func unstake (amount) = if ((size(i.payments) != 0))
463556 then throw("unstake doesn't require any payment")
464557 else {
465558 let userAddress = i.caller
466559 let userAddressStr = toString(userAddress)
467- let $t01911919173 = getParamsOrFail()
468- let stakedAssetId = $t01911919173._1
469- let minLockAmount = $t01911919173._2
470- let $t01917619260 = getUserParamsOrFail(userAddress)
471- let isNewUser = $t01917619260._1
472- let stakedAmount = $t01917619260._2
473- let vpEffectiveHeight = $t01917619260._3
560+ let $t02481824872 = getParamsOrFail()
561+ let stakedAssetId = $t02481824872._1
562+ let minLockAmount = $t02481824872._2
563+ let $t02487524959 = getUserParamsOrFail(userAddress)
564+ let isNewUser = $t02487524959._1
565+ let stakedAmount = $t02487524959._2
566+ let vpEffectiveHeight = $t02487524959._3
474567 let swapParamsSTRUCT = asSwapParamsSTRUCT(reentrantInvoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStr, 0], nil))
475568 let swapLimitSpentInUsdn = swapParamsSTRUCT._2
476569 let blcks2LmtReset = swapParamsSTRUCT._3
477570 if ((swapLimitSpentInUsdn > 0))
478571 then throw((("You have already made a swap operation. Wait " + toString((height + blcks2LmtReset))) + " height to unstake"))
479572 else if ((0 >= stakedAmount))
480573 then throw("Nothing to unstake")
481574 else if ((amount > stakedAmount))
482575 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(stakedAmount)))
483576 else {
484577 let stakedAmountNEW = (stakedAmount - amount)
485- let $t01989820056 = StatsResult(-(amount), if ((amount == stakedAmount))
578+ let $t02559725755 = StatsResult(-(amount), if ((amount == stakedAmount))
486579 then -1
487580 else 0, if ((amount == stakedAmount))
488581 then -1
489582 else 0)
490- let statsEntries = $t01989820056._1
491- let totalStaked = $t01989820056._2
492- let totalStakedNew = $t01989820056._3
493- ((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeight)] ++ RewardEntries(false, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeight)) ++ statsEntries)
583+ let statsEntries = $t02559725755._1
584+ let totalStaked = $t02559725755._2
585+ let totalStakedNew = $t02559725755._3
586+ (((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeight)] ++ RewardEntries(false, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeight)) ++ statsEntries) ++ onUnstake(userAddressStr, amount)._1)
494587 }
495588 }
496589
497590
498591
499592 @Callable(i)
500593 func deposit () = if ((size(i.payments) != 1))
501594 then throw("exact 1 payment is allowed only")
502595 else {
503596 let pmt = i.payments[0]
504597 let amount = pmt.amount
505598 let pmtAssetId = valueOrElse(pmt.assetId, WAVESID)
506599 let pmtAssetIdStr = toBase58String(pmtAssetId)
507600 let pmtMultX = if ((pmtAssetId == WAVESID))
508601 then MULTX8
509602 else MULTX6
510603 let amountX = toBigInt(amount)
511604 let totalStaked = getIntOrElse(keyLockParamTotalAmount(), 0)
512605 let totalStakedX = toBigInt(totalStaked)
513606 if ((0 > totalStaked))
514607 then throw("TODO: case is not supported")
515608 else if ((totalStaked == 0))
516609 then IncrementNotDistributedRewardEntry(pmtAssetIdStr, amount)
517610 else {
518611 let rewardPerNsbtX18 = fraction(amountX, MULTX18, totalStakedX)
519612 let depositNumLastKEY = keyDepositNumLast()
520613 let depositNumLast = getIntOrElse(depositNumLastKEY, -1)
521614 let depositNumNew = (depositNumLast + 1)
522615 if (!(contains(supportedAssetsStr, pmtAssetIdStr)))
523616 then throw(((supportedAssetsStr + " doesn't contain ") + pmtAssetIdStr))
524617 else {
525618 func refreshRewardPerNsbtSUM (accum,nextAsset) = {
526619 let rewardPerNsbtSumNewKEY = keyRewardPerNsbtSumAt(depositNumNew, nextAsset)
527620 let sumLastStr = getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, nextAsset), "0")
528621 (accum :+ (if ((nextAsset == pmtAssetIdStr))
529622 then StringEntry(rewardPerNsbtSumNewKEY, toString((parseBigIntValue(sumLastStr) + rewardPerNsbtX18)))
530623 else StringEntry(rewardPerNsbtSumNewKEY, sumLastStr)))
531624 }
532625
533- (({
626+ ((({
534627 let $l = supportedAssetsList
535628 let $s = size($l)
536629 let $acc0 = nil
537630 func $f0_1 ($a,$i) = if (($i >= $s))
538631 then $a
539632 else refreshRewardPerNsbtSUM($a, $l[$i])
540633
541634 func $f0_2 ($a,$i) = if (($i >= $s))
542635 then $a
543636 else throw("List size exceeds 9")
544637
545638 $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)
546- } :+ IntegerEntry(depositNumLastKEY, depositNumNew)) ++ DepositsTotalsEntries(amount, pmtAssetIdStr))
639+ } :+ IntegerEntry(depositNumLastKEY, depositNumNew)) ++ DepositsTotalsEntries(amount, pmtAssetIdStr)) ++ updateTotals())
547640 }
548641 }
549642 }
550643
551644
552645
553646 @Callable(i)
554647 func claimRewards () = commonClaim(i.caller, i)
555648
556649
557650
558651 @Callable(i)
559652 func claimRewardsByOriginCaller () = commonClaim(i.originCaller, i)
560653
561654
562655
563656 @Callable(i)
564657 func unclaimedRewardsREADONLY (userAddressStr) = {
565658 func forEachAssetZeroReward (accum,asset) = ((accum + makeString([asset, "0", "0"], ":")) + "_")
566659
567660 let unclaimedRewardStr = if ((userAddressStr == ""))
568661 then {
569662 let $l = supportedAssetsList
570663 let $s = size($l)
571664 let $acc0 = ""
572665 func $f0_1 ($a,$i) = if (($i >= $s))
573666 then $a
574667 else forEachAssetZeroReward($a, $l[$i])
575668
576669 func $f0_2 ($a,$i) = if (($i >= $s))
577670 then $a
578671 else throw("List size exceeds 9")
579672
580673 $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)
581674 }
582675 else {
583676 let userAddress = addressFromStringValue(userAddressStr)
584- let $t02268022785 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
585- let isNewUser = $t02268022785._1
586- let stakedAmount = $t02268022785._2
587- let stakingStart = $t02268022785._3
677+ let $t02847728582 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
678+ let isNewUser = $t02847728582._1
679+ let stakedAmount = $t02847728582._2
680+ let stakingStart = $t02847728582._3
588681 let stakedAmountX = toBigInt(stakedAmount)
589682 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
590683 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
591684 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
592685 func forEachAssetCalcUnclaimedReward (accum,asset) = {
593- let $t02313123269 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
594- let rewardTotal = $t02313123269._1
595- let cached = $t02313123269._2
596- let dynamic = $t02313123269._3
597- let rewardCachedPartKEY = $t02313123269._4
686+ let $t02892829066 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
687+ let rewardTotal = $t02892829066._1
688+ let cached = $t02892829066._2
689+ let dynamic = $t02892829066._3
690+ let rewardCachedPartKEY = $t02892829066._4
598691 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
599692 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
600693 }
601694
602695 let $l = supportedAssetsList
603696 let $s = size($l)
604697 let $acc0 = ""
605698 func $f0_1 ($a,$i) = if (($i >= $s))
606699 then $a
607700 else forEachAssetCalcUnclaimedReward($a, $l[$i])
608701
609702 func $f0_2 ($a,$i) = if (($i >= $s))
610703 then $a
611704 else throw("List size exceeds 9")
612705
613706 $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)
614707 }
615708 $Tuple2(nil, dropRight(unclaimedRewardStr, 1))
616709 }
617710
618711
619712
620713 @Callable(i)
714+func updateVotingPower (userAddressStr) = if (!(isDefined(addressFromString(userAddressStr))))
715+ then throw("Invalid user address")
716+ else {
717+ let r = onStake(userAddressStr, 0)
718+ $Tuple2(r._1, [surfToGnsbt(r._2), surfToGnsbt(r._3), surfToGnsbt(r._4), surfToGnsbt(r._5), surfToGnsbt(r._6), surfToGnsbt(r._7)])
719+ }
720+
721+
722+
723+@Callable(i)
621724 func surfStakingSYSREADONLY (userAddressStrOrEmpty,surfDiff) = {
622725 let surfTotal = getIntOrElse(keyLockParamTotalAmount(), 0)
623726 let gnsbtFromSurfTotal = surfToGnsbt(surfTotal)
727+ let r = if ((surfDiff >= 0))
728+ then onStake(userAddressStrOrEmpty, surfDiff)
729+ else onUnstake(userAddressStrOrEmpty, surfDiff)
624730 if ((userAddressStrOrEmpty == ""))
625- then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, 0, height, height])
731+ then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, height, height, surfToGnsbt(r._2), surfToGnsbt(r._3), surfToGnsbt(r._4), surfToGnsbt(r._5), surfToGnsbt(r._6), surfToGnsbt(r._7)])
626732 else {
627733 let userAddress = toAddressOrFail(userAddressStrOrEmpty)
628- let mergedData = mergeStake(userAddress, surfDiff)
629- let isNewUser = mergedData._1
734+ let mergedData = mergeStake(userAddress, surfDiff, r._6, r._7)
630735 let stakedAmount = mergedData._2
631736 let vpEffectiveHeight = mergedData._3
632737 let stakedAmountNEW = mergedData._4
633738 let vpEffectiveHeightNEW = mergedData._5
634739 let surfUser = stakedAmount
635740 let gnsbtFromSurfUser = surfToGnsbt(surfUser)
636- $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, vpEffectiveHeight, vpEffectiveHeightNEW])
741+ $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, vpEffectiveHeight, vpEffectiveHeightNEW, surfToGnsbt(r._2), surfToGnsbt(r._3), surfToGnsbt(r._4), surfToGnsbt(r._5), surfToGnsbt(r._6), surfToGnsbt(r._7)])
637742 }
638743 }
639744
640745
641746
642747 @Callable(i)
643748 func gnsbtFromSurfSYSREADONLY (surfAmt) = $Tuple2(nil, surfToGnsbt(surfAmt))
644749
645750
646751
647752 @Callable(i)
648753 func configSYSREADONLY () = {
649754 let minLockAmt = getIntegerValue(keyMinLockAmount())
650- let surfVotingPowerRestrictivePeriod = (1440 * 14)
755+ let surfVotingPowerRestrictivePeriod = DEFAULTPERIOD
651756 let brToStartSurfTransformation = 1150000
652757 $Tuple2(nil, [minLockAmt, (gnsbtFromSurfCoeff * MULT6), surfVotingPowerRestrictivePeriod, brToStartSurfTransformation])
653758 }
654759
655760

github/deemru/w8io/873ac7e 
116.59 ms