tx · 5izKXppfmhfDmuwJgSTaKuoXBSKL46hU5tXYvF5K4KFn

3MyN19SDzDpXyEtabWvag2P5mkeFrdFVd4h:  -0.01900000 Waves

2022.10.12 01:52 [2268311] smart account 3MyN19SDzDpXyEtabWvag2P5mkeFrdFVd4h > SELF 0.00000000 Waves

{ "type": 13, "id": "5izKXppfmhfDmuwJgSTaKuoXBSKL46hU5tXYvF5K4KFn", "fee": 1900000, "feeAssetId": null, "timestamp": 1665528833718, "version": 2, "chainId": 84, "sender": "3MyN19SDzDpXyEtabWvag2P5mkeFrdFVd4h", "senderPublicKey": "4HqqczFwZHAsxp1oNq8dQkRStfCKBL79X99icQ2B6FYn", "proofs": [ "5f17cbQobhVAPcFtg8NBswaDaGkwVgGmkE7YscL2X4DdBkFHbJo1wqp6fcZF78c298L8Fxf2vyZSQTYdrfz8PzRU" ], "script": "base64:BgIlCAISBQoDAQgIEgASABIDCgEBEgASABIAEgMKAQgSBAoCCAESAE4AC3JldmlzaW9uTnVtAgAACXNlcGFyYXRvcgICX18AA1NFUAICX18ABU1VTFQ2AMCEPQAFTVVMVDgAgMLXLwAGTVVMVFg2CQC2AgEFBU1VTFQ2AAZNVUxUWDgJALYCAQUFTVVMVDgAB01VTFRYMTgJALYCAQCAgJC7utat8A0ACVVTRE5JRFNUUgIEVVNETgAGVVNETklECQDZBAEFCVVTRE5JRFNUUgAZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAABABhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHAAAgAUSWR4Q29udHJvbENmZ1JwZERhcHAAAwAVSWR4Q29udHJvbENmZ01hdGhEYXBwAAQAHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAABQAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAYAHUlkeENvbnRyb2xDZmdOb2RlUmVnaXN0cnlEYXBwAAcAHElkeENvbnRyb2xDZmdOc2J0U3Rha2luZ0RhcHAACAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAJABxJZHhDb250cm9sQ2ZnU3VyZlN0YWtpbmdEYXBwAAoAIElkeENvbnRyb2xDZmdHbnNidENvbnRyb2xsZXJEYXBwAAsBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJAKwCAgkArAICCQCsAgIJAKwCAgIKbWFuZGF0b3J5IAkApQgBBQdhZGRyZXNzAgEuBQNrZXkCDyBpcyBub3QgZGVmaW5lZAERa2V5Q29udHJvbEFkZHJlc3MAAhwlcyVzX19jb25maWdfX2NvbnRyb2xBZGRyZXNzAQ1rZXlDb250cm9sQ2ZnAAIRJXNfX2NvbnRyb2xDb25maWcBFHJlYWRDb250cm9sQ2ZnT3JGYWlsAQdjb250cm9sCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQdjb250cm9sCQENa2V5Q29udHJvbENmZwAFA1NFUAEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgpjb250cm9sQ2ZnA2lkeAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUKY29udHJvbENmZwUDaWR4CQCsAgICLUNvbnRyb2wgY2ZnIGRvZXNuJ3QgY29udGFpbiBhZGRyZXNzIGF0IGluZGV4IAkApAMBBQNpZHgAD2NvbnRyb2xDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQERa2V5Q29udHJvbEFkZHJlc3MAAiMzUDVCZmQ1OFBQZk52Qk0ySHk4UWZiY0RxTWVOdHpnN0tmUAAKY29udHJvbENmZwkBFHJlYWRDb250cm9sQ2ZnT3JGYWlsAQUPY29udHJvbENvbnRyYWN0AAxtYXRoQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRVJZHhDb250cm9sQ2ZnTWF0aERhcHAAEG5ldXRyaW5vQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRlJZHhDb250cm9sQ2ZnTmV1dHJpbm9EYXBwAA9hdWN0aW9uQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRhJZHhDb250cm9sQ2ZnQXVjdGlvbkRhcHABDGtleUJvbmRBc3NldAACDWJvbmRfYXNzZXRfaWQBGWtleUF1Y3Rpb25Db250cmFjdEFkZHJlc3MAAhBhdWN0aW9uX2NvbnRyYWN0ARBrZXlNaW5Mb2NrQW1vdW50AAIRJXNfX21pbkxvY2tBbW91bnQBEGtleVN0YWtlZEFzc2V0SWQAAhElc19fc3Rha2VkQXNzZXRJZAEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCAgZhbW91bnQFA25pbAUJc2VwYXJhdG9yARZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtwYXJhbUJ5VXNlcgkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICBXN0YXJ0BQNuaWwFCXNlcGFyYXRvcgEma2V5TG9ja1BhcmFtVm90aW5nUG93ZXJFZmZlY3RpdmVIZWlnaHQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIJAKUIAQULdXNlckFkZHJlc3MJAMwIAgIRdnBFZmZlY3RpdmVIZWlnaHQFA25pbAUJc2VwYXJhdG9yARBrZXlIaXN0b3J5UmVjb3JkAwR0eXBlC3VzZXJBZGRyZXNzBHR4SWQJALkJAgkAzAgCAgglcyVzJXMlcwkAzAgCAgdoaXN0b3J5CQDMCAIFBHR5cGUJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCCQDYBAEFBHR4SWQFA25pbAUJc2VwYXJhdG9yARdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAJALkJAgkAzAgCAgQlcyVzCQDMCAICBXN0YXRzCQDMCAICEWFjdGl2ZVRvdGFsTG9ja2VkBQNuaWwFCXNlcGFyYXRvcgESa2V5U3RhdHNMb2Nrc0NvdW50AAkAuQkCCQDMCAICBCVzJXMJAMwIAgIFc3RhdHMJAMwIAgIKbG9ja3NDb3VudAUDbmlsBQlzZXBhcmF0b3IBEmtleVN0YXRzVXNlcnNDb3VudAAJALkJAgkAzAgCAgQlcyVzCQDMCAICBXN0YXRzCQDMCAICEGFjdGl2ZVVzZXJzQ291bnQFA25pbAUJc2VwYXJhdG9yAQ1rZXlOZXh0UGVyaW9kAAIOJXNfX25leHRQZXJpb2QBGGtleVN1cHBvcnRlZFJld2FyZEFzc2V0cwACFXN1cHBvcnRlZFJld2FyZEFzc2V0cwERa2V5RGVwb3NpdE51bUxhc3QACQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICA2RlcAkAzAgCAgdsYXN0TnVtBQNuaWwFCXNlcGFyYXRvcgEba2V5VXNlclJld2FyZEZyb21EZXBvc2l0TnVtAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAhF1c2VyUndkRnJvbURlcE51bQkAzAgCBQt1c2VyQWRkcmVzcwUDbmlsBQlzZXBhcmF0b3IBFWtleVJld2FyZFBlck5zYnRTdW1BdAIKZGVwb3NpdE51bQN0a24JALkJAgkAzAgCAgQlcyVkCQDMCAICFXJ3ZFBlck5zYnRTdW1CeURlcE51bQkAzAgCCQCkAwEFCmRlcG9zaXROdW0JAMwIAgUDdGtuBQNuaWwFCXNlcGFyYXRvcgEJa2V5UmV3YXJkAgt1c2VyQWRkcmVzcwN0a24JALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIDcndkCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBCmtleUNsYWltZWQCC3VzZXJBZGRyZXNzA3RrbgkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgNjbG0JAMwIAgULdXNlckFkZHJlc3MJAMwIAgUDdGtuBQNuaWwFCXNlcGFyYXRvcgEXa2V5Tm90RGlzdHJpYnV0ZWRSZXdhcmQBA3RrbgkAuQkCCQDMCAICBCVzJXMJAMwIAgIObm90RGlzdHJpYnV0ZWQJAMwIAgUDdGtuBQNuaWwFCXNlcGFyYXRvcgEFdG9YMTgCB29yaWdWYWwIb3JpZ011bHQJALwCAwkAtgIBBQdvcmlnVmFsBQdNVUxUWDE4BQhvcmlnTXVsdAEMZ2V0SW50T3JaZXJvAQNrZXkJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5AAABDGdldEludE9yRWxzZQIDa2V5CmRlZmF1bHRWYWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5BQpkZWZhdWx0VmFsAQxnZXRJbnRPckZhaWwBA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFA2tleQkArAICCQCsAgICD01hbmRhdG9yeSB0aGlzLgUDa2V5Ag8gaXMgbm90IGRlZmluZWQBDGdldFN0ck9yRWxzZQIDa2V5CmRlZmF1bHRWYWwJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUDa2V5BQpkZWZhdWx0VmFsAQ90b0FkZHJlc3NPckZhaWwBCmFkZHJlc3NTdHIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQphZGRyZXNzU3RyCQCsAgICIWNvdWxkbid0IHBhcnNlIHBhc3NlZCBhZGRyZXNzU3RyPQUKYWRkcmVzc1N0cgELdG9Bc3NldFZlY3QBCGFzc2V0U3RyAwkAAAIFCGFzc2V0U3RyBQlVU0ROSURTVFIFBHVuaXQJANkEAQUIYXNzZXRTdHIBBWFzSW50AQN2YWwEByRtYXRjaDAFA3ZhbAMJAAECBQckbWF0Y2gwAgNJbnQEBnZhbEludAUHJG1hdGNoMAUGdmFsSW50CQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50ARJhc1N3YXBQYXJhbXNTVFJVQ1QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIjKEludCwgSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCkEBnN0cnVjdAUHJG1hdGNoMAUGc3RydWN0CQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50ARNmb3JtYXRIaXN0b3J5UmVjb3JkBAlvbGRBbW91bnQIb2xkU3RhcnQJbmV3QW1vdW50CG5ld1N0YXJ0CQC5CQIJAMwIAgIMJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQCkAwEFCW9sZEFtb3VudAkAzAgCCQCkAwEFCG9sZFN0YXJ0CQDMCAIJAKQDAQUJbmV3QW1vdW50CQDMCAIJAKQDAQUIbmV3U3RhcnQFA25pbAUJc2VwYXJhdG9yARhmb3JtYXRDbGFpbUhpc3RvcnlSZWNvcmQCBHVzZXIOY2xhaW1lZFJld2FyZHMJALkJAgkAzAgCAgglcyVkJWQlcwkAzAgCBQR1c2VyCQDMCAIJAKQDAQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCBQ5jbGFpbWVkUmV3YXJkcwUDbmlsBQlzZXBhcmF0b3IBEkhpc3RvcnlSZWNvcmRFbnRyeQcEdHlwZQt1c2VyQWRkcmVzcwR0eElkCW9sZEFtb3VudAhvbGRTdGFydAluZXdBbW91bnQIbmV3U3RhcnQJAQtTdHJpbmdFbnRyeQIJARBrZXlIaXN0b3J5UmVjb3JkAwUEdHlwZQULdXNlckFkZHJlc3MFBHR4SWQJARNmb3JtYXRIaXN0b3J5UmVjb3JkBAUJb2xkQW1vdW50BQhvbGRTdGFydAUJbmV3QW1vdW50BQhuZXdTdGFydAERQ2xhaW1IaXN0b3J5RW50cnkDC3VzZXJBZGRyZXNzBHR4SWQOY2xhaW1lZFJld2FyZHMJAQtTdHJpbmdFbnRyeQIJARBrZXlIaXN0b3J5UmVjb3JkAwIFY2xhaW0FC3VzZXJBZGRyZXNzBQR0eElkCQEYZm9ybWF0Q2xhaW1IaXN0b3J5UmVjb3JkAgkApQgBBQt1c2VyQWRkcmVzcwUOY2xhaW1lZFJld2FyZHMBC1N0YXRzUmVzdWx0Aw50b3RhbExvY2tlZEluYwxsb2NrQ291bnRJbmMNdXNlcnNDb3VudEluYwQKbG9ja3NDb3VudAkBDGdldEludE9yWmVybwEJARJrZXlTdGF0c0xvY2tzQ291bnQABAp1c2Vyc0NvdW50CQEMZ2V0SW50T3JaZXJvAQkBEmtleVN0YXRzVXNlcnNDb3VudAAEC3RvdGFsQW1vdW50CQEMZ2V0SW50T3JaZXJvAQkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAQOdG90YWxBbW91bnROZXcJAGQCBQt0b3RhbEFtb3VudAUOdG90YWxMb2NrZWRJbmMJAJUKAwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleVN0YXRzTG9ja3NDb3VudAAJAGQCBQpsb2Nrc0NvdW50BQxsb2NrQ291bnRJbmMJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlTdGF0c1VzZXJzQ291bnQACQBkAgUKdXNlcnNDb3VudAUNdXNlcnNDb3VudEluYwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAUOdG90YWxBbW91bnROZXcFA25pbAULdG90YWxBbW91bnQFDnRvdGFsQW1vdW50TmV3AQ9Mb2NrUGFyYW1zRW50cnkDC3VzZXJBZGRyZXNzBmFtb3VudBp2b3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBBQt1c2VyQWRkcmVzcwUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawEFC3VzZXJBZGRyZXNzBRp2b3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAUDbmlsAQ9nZXRQYXJhbXNPckZhaWwACQCUCgIJANkEAQkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARBrZXlTdGFrZWRBc3NldElkAAkBDGdldEludE9yRmFpbAEJARBrZXlNaW5Mb2NrQW1vdW50AAEMaXNBY3RpdmVVc2VyAQt1c2VyQWRkcmVzcwkAZgIJAQxnZXRJbnRPckVsc2UCCQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEFC3VzZXJBZGRyZXNzAAAAAAETZ2V0VXNlclBhcmFtc09yVW5pdAELdXNlckFkZHJlc3MDCQEMaXNBY3RpdmVVc2VyAQULdXNlckFkZHJlc3MJAJUKAwcJAQxnZXRJbnRPckZhaWwBCQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEFC3VzZXJBZGRyZXNzCQEMZ2V0SW50T3JGYWlsAQkBFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sBBQt1c2VyQWRkcmVzcwUEdW5pdAETZ2V0VXNlclBhcmFtc09yRmFpbAELdXNlckFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkArAICCQCsAgICBVVzZXIgCQClCAEFC3VzZXJBZGRyZXNzAg8gaXMgbm90IGRlZmluZWQAEnN1cHBvcnRlZEFzc2V0c1N0cgkBDGdldFN0ck9yRWxzZQIJARhrZXlTdXBwb3J0ZWRSZXdhcmRBc3NldHMAAgAAE3N1cHBvcnRlZEFzc2V0c0xpc3QJALUJAgUSc3VwcG9ydGVkQXNzZXRzU3RyAgFfAQpjYWxjUmV3YXJkBQt1c2VyQWRkcmVzcwdhc3NldElkDXN0YWtlZEFtb3VudFgOZGVwb3NpdE51bVVzZXIOZGVwb3NpdE51bUxhc3QEF3Jld2FyZFBlck5zYnRTdW1MYXN0S0VZCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bUxhc3QFB2Fzc2V0SWQECnN1bUxhc3RYMTgJAKcDAQkBDGdldFN0ck9yRWxzZQIJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ5kZXBvc2l0TnVtTGFzdAUHYXNzZXRJZAIBMAQKc3VtVXNlclgxOAkApwMBCQEMZ2V0U3RyT3JFbHNlAgkBFWtleVJld2FyZFBlck5zYnRTdW1BdAIFDmRlcG9zaXROdW1Vc2VyBQdhc3NldElkAgEwBBFyZXdhcmREeW5hbWljUGFydAkAoAMBCQC8AgMJALgCAgUKc3VtTGFzdFgxOAUKc3VtVXNlclgxOAUNc3Rha2VkQW1vdW50WAUHTVVMVFgxOAQTcmV3YXJkQ2FjaGVkUGFydEtFWQkBCWtleVJld2FyZAIFC3VzZXJBZGRyZXNzBQdhc3NldElkBBByZXdhcmRDYWNoZWRQYXJ0CQEMZ2V0SW50T3JFbHNlAgUTcmV3YXJkQ2FjaGVkUGFydEtFWQAACQCWCgQJAGQCBRByZXdhcmRDYWNoZWRQYXJ0BRFyZXdhcmREeW5hbWljUGFydAUQcmV3YXJkQ2FjaGVkUGFydAURcmV3YXJkRHluYW1pY1BhcnQFE3Jld2FyZENhY2hlZFBhcnRLRVkBDVJld2FyZEVudHJpZXMDCWlzTmV3VXNlcgt1c2VyQWRkcmVzcwxzdGFrZWRBbW91bnQEDXN0YWtlZEFtb3VudFgJALYCAQUMc3Rha2VkQW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQt1c2VyQWRkcmVzcwQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKARtmb3JFYWNoQXNzZXRDYWNoZVVzZXJSZXdhcmQCBWFjY3VtBWFzc2V0BAskdDA4Nzk3ODkzMgkBCmNhbGNSZXdhcmQFBQt1c2VyQWRkcmVzcwUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQskdDA4Nzk3ODkzMgJfMQQGY2FjaGVkCAULJHQwODc5Nzg5MzICXzIEB2R5bmFtaWMIBQskdDA4Nzk3ODkzMgJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFCyR0MDg3OTc4OTMyAl80CQDNCAIFBWFjY3VtCQEMSW50ZWdlckVudHJ5AgUTcmV3YXJkQ2FjaGVkUGFydEtFWQULcmV3YXJkVG90YWwDAwkAAAIFDmRlcG9zaXROdW1MYXN0AP///////////wEJAAACBQ5kZXBvc2l0TnVtVXNlcgD///////////8BBwUDbmlsAwMJAAACBQ5kZXBvc2l0TnVtTGFzdAD///////////8BCQBmAgUOZGVwb3NpdE51bVVzZXIA////////////AQcJAAIBAi9pbnZhbGlkIGRlcG9zaXROdW1MYXN0IGFuZCBkZXBvc2l0TnVtVXNlciBzdGF0ZQMDCQBmAgUOZGVwb3NpdE51bUxhc3QA////////////AQkAZwIFDmRlcG9zaXROdW1Vc2VyAP///////////wEHAwUJaXNOZXdVc2VyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0BQNuaWwJAM0IAgoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARtmb3JFYWNoQXNzZXRDYWNoZVVzZXJSZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0CQACAQkArAICCQCsAgIJAKwCAgIkdW5jb3ZlcmVkIGNvbmRpdGlvbjogZGVwb3NpdE51bUxhc3Q9CQCkAwEFDmRlcG9zaXROdW1MYXN0AhAgZGVwb3NpdE51bVVzZXI9CQCkAwEFDmRlcG9zaXROdW1Vc2VyASJJbmNyZW1lbnROb3REaXN0cmlidXRlZFJld2FyZEVudHJ5AgN0a24JYW1vdW50SW5jBBdub3REaXN0cmlidXRlZFJld2FyZEtFWQkBF2tleU5vdERpc3RyaWJ1dGVkUmV3YXJkAQUDdGtuBBRub3REaXN0cmlidXRlZFJld2FyZAkBDGdldEludE9yRWxzZQIFF25vdERpc3RyaWJ1dGVkUmV3YXJkS0VZAAAJAMwIAgkBDEludGVnZXJFbnRyeQIFF25vdERpc3RyaWJ1dGVkUmV3YXJkS0VZCQBkAgUUbm90RGlzdHJpYnV0ZWRSZXdhcmQFCWFtb3VudEluYwUDbmlsAR9tZXJnZVZvdGluZ1Bvd2VyRWZmZWN0aXZlSGVpZ2h0BBBxdWFyYW50aW5lUGVyaW9kEXZwRWZmZWN0aXZlSGVpZ2h0CXN0YWtlZEFtdAxzdGFrZWRBbXRORVcED3JlbWFpbmluZ1RvV2FpdAkAZQIFEXZwRWZmZWN0aXZlSGVpZ2h0BQZoZWlnaHQDCQBnAgAABQ9yZW1haW5pbmdUb1dhaXQJAGQCBQZoZWlnaHQFEHF1YXJhbnRpbmVQZXJpb2QEDWFscmVhZHlXYWl0ZWQJAGUCBRBxdWFyYW50aW5lUGVyaW9kBQ9yZW1haW5pbmdUb1dhaXQEA2tYOAMJAQIhPQIFDHN0YWtlZEFtdE5FVwAACQBrAwUJc3Rha2VkQW10BQVNVUxUOAUMc3Rha2VkQW10TkVXBRF2cEVmZmVjdGl2ZUhlaWdodAkAZQIJAGQCBRBxdWFyYW50aW5lUGVyaW9kBQZoZWlnaHQJAGsDBQ1hbHJlYWR5V2FpdGVkBQNrWDgFBU1VTFQ4AQptZXJnZVN0YWtlAgt1c2VyQWRkcmVzcwthbW91bnRUb0FkZAQNJHQwMTI1MTcxMjYyNwkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDEyNTE3MTI2MjcCXzEEDHN0YWtlZEFtb3VudAgFDSR0MDEyNTE3MTI2MjcCXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUNJHQwMTI1MTcxMjYyNwJfMwQPc3Rha2VkQW1vdW50TkVXAwUJaXNOZXdVc2VyBQthbW91bnRUb0FkZAkAZAIFC2Ftb3VudFRvQWRkBQxzdGFrZWRBbW91bnQEEHF1YXJhbnRpbmVQZXJpb2QJAGgCAKALAA4EFHZwRWZmZWN0aXZlSGVpZ2h0TkVXAwUJaXNOZXdVc2VyCQBkAgUQcXVhcmFudGluZVBlcmlvZAUGaGVpZ2h0CQEfbWVyZ2VWb3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAQFEHF1YXJhbnRpbmVQZXJpb2QFEXZwRWZmZWN0aXZlSGVpZ2h0BQxzdGFrZWRBbW91bnQFD3N0YWtlZEFtb3VudE5FVwkAlwoFBQlpc05ld1VzZXIFDHN0YWtlZEFtb3VudAURdnBFZmZlY3RpdmVIZWlnaHQFD3N0YWtlZEFtb3VudE5FVwUUdnBFZmZlY3RpdmVIZWlnaHRORVcBC2NvbW1vblN0YWtlAgt1c2VyQWRkcmVzcwFpBA0kdDAxMzExMzEzMTY3CQEPZ2V0UGFyYW1zT3JGYWlsAAQNc3Rha2VkQXNzZXRJZAgFDSR0MDEzMTEzMTMxNjcCXzEEDW1pbkxvY2tBbW91bnQIBQ0kdDAxMzExMzEzMTY3Al8yAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIVSW52YWxpZCBwYXltZW50cyBzaXplBAdwYXltZW50CQCRAwIIBQFpCHBheW1lbnRzAAAEBmFtb3VudAgFB3BheW1lbnQGYW1vdW50BBNpbnZhbGlkQXNzZXRNZXNzYWdlCQCsAgIJAKwCAgIPSW52YWxpZCBhc3NldC4gCQDYBAEFDXN0YWtlZEFzc2V0SWQCDCBpcyBleHBlY3RlZAQHYXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAUHcGF5bWVudAdhc3NldElkBRNpbnZhbGlkQXNzZXRNZXNzYWdlAwkBAiE9AgUHYXNzZXRJZAUNc3Rha2VkQXNzZXRJZAkAAgEFE2ludmFsaWRBc3NldE1lc3NhZ2UEDnVzZXJBZGRyZXNzU3RyCQClCAEFC3VzZXJBZGRyZXNzBAptZXJnZWREYXRhCQEKbWVyZ2VTdGFrZQIFC3VzZXJBZGRyZXNzBQZhbW91bnQECWlzTmV3VXNlcggFCm1lcmdlZERhdGECXzEEDHN0YWtlZEFtb3VudAgFCm1lcmdlZERhdGECXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUKbWVyZ2VkRGF0YQJfMwQPc3Rha2VkQW1vdW50TkVXCAUKbWVyZ2VkRGF0YQJfNAQUdnBFZmZlY3RpdmVIZWlnaHRORVcIBQptZXJnZWREYXRhAl81AwkAZgIFDW1pbkxvY2tBbW91bnQFD3N0YWtlZEFtb3VudE5FVwkAAgEJAKwCAgITTWluIGxvY2sgYW1vdW50IGlzIAkApAMBBQ1taW5Mb2NrQW1vdW50BA0kdDAxMzk2NjE0MDY4CQELU3RhdHNSZXN1bHQDBQZhbW91bnQAAQMFCWlzTmV3VXNlcgABAAAEDHN0YXRzRW50cmllcwgFDSR0MDEzOTY2MTQwNjgCXzEEC3RvdGFsU3Rha2VkCAUNJHQwMTM5NjYxNDA2OAJfMgQOdG90YWxTdGFrZWROZXcIBQ0kdDAxMzk2NjE0MDY4Al8zCQDOCAIJAM4IAgkAzggCCQDMCAIJARJIaXN0b3J5UmVjb3JkRW50cnkHAgVzdGFrZQULdXNlckFkZHJlc3MIBQFpDXRyYW5zYWN0aW9uSWQFDHN0YWtlZEFtb3VudAURdnBFZmZlY3RpdmVIZWlnaHQFD3N0YWtlZEFtb3VudE5FVwUUdnBFZmZlY3RpdmVIZWlnaHRORVcFA25pbAkBDVJld2FyZEVudHJpZXMDBQlpc05ld1VzZXIFDnVzZXJBZGRyZXNzU3RyBQxzdGFrZWRBbW91bnQJAQ9Mb2NrUGFyYW1zRW50cnkDBQt1c2VyQWRkcmVzcwUPc3Rha2VkQW1vdW50TkVXBRR2cEVmZmVjdGl2ZUhlaWdodE5FVwUMc3RhdHNFbnRyaWVzAQtjb21tb25DbGFpbQILdXNlckFkZHJlc3MBaQQOdXNlckFkZHJlc3NTdHIJAKUIAQULdXNlckFkZHJlc3MDCQBmAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIZcGF5bWVudHMgYXJlIG5vdCBhY2NlcHRlZAQNJHQwMTQ1NDcxNDY1MgkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDE0NTQ3MTQ2NTICXzEEDHN0YWtlZEFtb3VudAgFDSR0MDE0NTQ3MTQ2NTICXzIEDHN0YWtpbmdTdGFydAgFDSR0MDE0NTQ3MTQ2NTICXzMEDXN0YWtlZEFtb3VudFgJALYCAQUMc3Rha2VkQW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQ51c2VyQWRkcmVzc1N0cgQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgVhY2N1bQVhc3NldAQNJHQwMTUwMjMxNTE2MQkBCmNhbGNSZXdhcmQFBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQ0kdDAxNTAyMzE1MTYxAl8xBAZjYWNoZWQIBQ0kdDAxNTAyMzE1MTYxAl8yBAdkeW5hbWljCAUNJHQwMTUwMjMxNTE2MQJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFDSR0MDE1MDIzMTUxNjECXzQECmNsYWltZWRLRVkJAQprZXlDbGFpbWVkAgUOdXNlckFkZHJlc3NTdHIFBWFzc2V0BA0kdDAxNTIyMTE1MjU4BQVhY2N1bQQEZGF0YQgFDSR0MDE1MjIxMTUyNTgCXzEEEWNsYWltZWRBbXRCeUFzc2V0CAUNJHQwMTUyMjExNTI1OAJfMgQHbmV3UGFydAkAuQkCCQDMCAIFBWFzc2V0CQDMCAIJAKQDAQULcmV3YXJkVG90YWwFA25pbAIBOgQUY2xhaW1lZEFtdEJ5QXNzZXROZXcJALkJAgkAzAgCBRFjbGFpbWVkQW10QnlBc3NldAkAzAgCBQduZXdQYXJ0BQNuaWwCAV8DCQBnAgAABQtyZXdhcmRUb3RhbAkAlAoCBQRkYXRhBRRjbGFpbWVkQW10QnlBc3NldE5ldwkAlAoCCQDNCAIJAM0IAgkAzQgCBQRkYXRhCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwULcmV3YXJkVG90YWwJAQt0b0Fzc2V0VmVjdAEFBWFzc2V0CQEMSW50ZWdlckVudHJ5AgUKY2xhaW1lZEtFWQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUKY2xhaW1lZEtFWQAABQtyZXdhcmRUb3RhbAkBDEludGVnZXJFbnRyeQIFE3Jld2FyZENhY2hlZFBhcnRLRVkAAAUUY2xhaW1lZEFtdEJ5QXNzZXROZXcEDSR0MDE1NzE4MTU4MzIKAAIkbAUTc3VwcG9ydGVkQXNzZXRzTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBH2ZvckVhY2hBc3NldENhbGNVbmNsYWltZWRSZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoECXRyYW5zZmVycwgFDSR0MDE1NzE4MTU4MzICXzEEF2NsYWltZWRBbXRCeUFzc2V0UmVzdWx0CAUNJHQwMTU3MTgxNTgzMgJfMgMJAGcCAAAJAJADAQUJdHJhbnNmZXJzBQNuaWwJAM0IAgkAzQgCBQl0cmFuc2ZlcnMJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0CQERQ2xhaW1IaXN0b3J5RW50cnkDBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAkAsAICBRdjbGFpbWVkQW10QnlBc3NldFJlc3VsdAABCgFpAQtjb25zdHJ1Y3RvcgMNbWluTG9ja0Ftb3VudBVzdXBwb3J0ZWRSZXdhcmRBc3NldHMNc3Rha2VkQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEVBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEQa2V5TWluTG9ja0Ftb3VudAAFDW1pbkxvY2tBbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGGtleVN1cHBvcnRlZFJld2FyZEFzc2V0cwAFFXN1cHBvcnRlZFJld2FyZEFzc2V0cwkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5U3Rha2VkQXNzZXRJZAAFDXN0YWtlZEFzc2V0SWQFA25pbAFpAQVzdGFrZQAJAQtjb21tb25TdGFrZQIIBQFpBmNhbGxlcgUBaQFpARNzdGFrZUJ5T3JpZ2luQ2FsbGVyAAkBC2NvbW1vblN0YWtlAggFAWkMb3JpZ2luQ2FsbGVyBQFpAWkBB3Vuc3Rha2UBBmFtb3VudAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECI3Vuc3Rha2UgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50BAt1c2VyQWRkcmVzcwgFAWkGY2FsbGVyBA51c2VyQWRkcmVzc1N0cgkApQgBBQt1c2VyQWRkcmVzcwQNJHQwMTY3NDExNjc5NQkBD2dldFBhcmFtc09yRmFpbAAEDXN0YWtlZEFzc2V0SWQIBQ0kdDAxNjc0MTE2Nzk1Al8xBA1taW5Mb2NrQW1vdW50CAUNJHQwMTY3NDExNjc5NQJfMgQNJHQwMTY3OTgxNjg4MgkBE2dldFVzZXJQYXJhbXNPckZhaWwBBQt1c2VyQWRkcmVzcwQJaXNOZXdVc2VyCAUNJHQwMTY3OTgxNjg4MgJfMQQMc3Rha2VkQW1vdW50CAUNJHQwMTY3OTgxNjg4MgJfMgQRdnBFZmZlY3RpdmVIZWlnaHQIBQ0kdDAxNjc5ODE2ODgyAl8zBBBzd2FwUGFyYW1zU1RSVUNUCQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/QcEBRBuZXV0cmlub0NvbnRyYWN0Ahtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgAABQNuaWwFA25pbAQUc3dhcExpbWl0U3BlbnRJblVzZG4IBRBzd2FwUGFyYW1zU1RSVUNUAl8yBA5ibGNrczJMbXRSZXNldAgFEHN3YXBQYXJhbXNTVFJVQ1QCXzMDCQBmAgUUc3dhcExpbWl0U3BlbnRJblVzZG4AAAkAAgEJAKwCAgkArAICAi1Zb3UgaGF2ZSBhbHJlYWR5IG1hZGUgYSBzd2FwIG9wZXJhdGlvbi4gV2FpdCAJAKQDAQkAZAIFBmhlaWdodAUOYmxja3MyTG10UmVzZXQCEiBoZWlnaHQgdG8gdW5zdGFrZQMJAGcCAAAFDHN0YWtlZEFtb3VudAkAAgECEk5vdGhpbmcgdG8gdW5zdGFrZQMJAGYCBQZhbW91bnQFDHN0YWtlZEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgICClJlcXVlc3RlZCAJAKQDAQUGYW1vdW50AhIsIGJ1dCBzdGFrZWQgb25seSAJAKQDAQUMc3Rha2VkQW1vdW50BA9zdGFrZWRBbW91bnRORVcJAGUCBQxzdGFrZWRBbW91bnQFBmFtb3VudAQNJHQwMTc1MjAxNzY3OAkBC1N0YXRzUmVzdWx0AwkBAS0BBQZhbW91bnQDCQAAAgUGYW1vdW50BQxzdGFrZWRBbW91bnQA////////////AQAAAwkAAAIFBmFtb3VudAUMc3Rha2VkQW1vdW50AP///////////wEAAAQMc3RhdHNFbnRyaWVzCAUNJHQwMTc1MjAxNzY3OAJfMQQLdG90YWxTdGFrZWQIBQ0kdDAxNzUyMDE3Njc4Al8yBA50b3RhbFN0YWtlZE5ldwgFDSR0MDE3NTIwMTc2NzgCXzMJAM4IAgkAzggCCQDOCAIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFBmFtb3VudAUNc3Rha2VkQXNzZXRJZAkAzAgCCQESSGlzdG9yeVJlY29yZEVudHJ5BwIHdW5zdGFrZQULdXNlckFkZHJlc3MIBQFpDXRyYW5zYWN0aW9uSWQFDHN0YWtlZEFtb3VudAURdnBFZmZlY3RpdmVIZWlnaHQFD3N0YWtlZEFtb3VudE5FVwURdnBFZmZlY3RpdmVIZWlnaHQFA25pbAkBDVJld2FyZEVudHJpZXMDBwUOdXNlckFkZHJlc3NTdHIFDHN0YWtlZEFtb3VudAkBD0xvY2tQYXJhbXNFbnRyeQMFC3VzZXJBZGRyZXNzBQ9zdGFrZWRBbW91bnRORVcFEXZwRWZmZWN0aXZlSGVpZ2h0BQxzdGF0c0VudHJpZXMBaQEHZGVwb3NpdAADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAh9leGFjdCAxIHBheW1lbnQgaXMgYWxsb3dlZCBvbmx5BANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQGYW1vdW50CAUDcG10BmFtb3VudAQKcG10QXNzZXRJZAkBC3ZhbHVlT3JFbHNlAggFA3BtdAdhc3NldElkBQZVU0ROSUQEDXBtdEFzc2V0SWRTdHIJANgEAQUKcG10QXNzZXRJZAQIcG10TXVsdFgDCQAAAgUKcG10QXNzZXRJZAUGVVNETklEBQZNVUxUWDgFBk1VTFRYNgQHYW1vdW50WAkAtgIBBQZhbW91bnQEC3RvdGFsU3Rha2VkCQEMZ2V0SW50T3JFbHNlAgkBF2tleUxvY2tQYXJhbVRvdGFsQW1vdW50AAAABAx0b3RhbFN0YWtlZFgJALYCAQULdG90YWxTdGFrZWQDCQBmAgAABQt0b3RhbFN0YWtlZAkAAgECG1RPRE86IGNhc2UgaXMgbm90IHN1cHBvcnRlZAMJAAACBQt0b3RhbFN0YWtlZAAACQEiSW5jcmVtZW50Tm90RGlzdHJpYnV0ZWRSZXdhcmRFbnRyeQIFDXBtdEFzc2V0SWRTdHIFBmFtb3VudAQQcmV3YXJkUGVyTnNidFgxOAkAvAIDBQdhbW91bnRYBQdNVUxUWDE4BQx0b3RhbFN0YWtlZFgEEWRlcG9zaXROdW1MYXN0S0VZCQERa2V5RGVwb3NpdE51bUxhc3QABA5kZXBvc2l0TnVtTGFzdAkBDGdldEludE9yRWxzZQIFEWRlcG9zaXROdW1MYXN0S0VZAP///////////wEEDWRlcG9zaXROdW1OZXcJAGQCBQ5kZXBvc2l0TnVtTGFzdAABAwkBASEBCQEIY29udGFpbnMCBRJzdXBwb3J0ZWRBc3NldHNTdHIFDXBtdEFzc2V0SWRTdHIJAAIBCQCsAgIJAKwCAgUSc3VwcG9ydGVkQXNzZXRzU3RyAhEgZG9lc24ndCBjb250YWluIAUNcG10QXNzZXRJZFN0cgoBF3JlZnJlc2hSZXdhcmRQZXJOc2J0U1VNAgVhY2N1bQluZXh0QXNzZXQEFnJld2FyZFBlck5zYnRTdW1OZXdLRVkJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ1kZXBvc2l0TnVtTmV3BQluZXh0QXNzZXQECnN1bUxhc3RTdHIJAQxnZXRTdHJPckVsc2UCCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bUxhc3QFCW5leHRBc3NldAIBMAkAzQgCBQVhY2N1bQMJAAACBQluZXh0QXNzZXQFDXBtdEFzc2V0SWRTdHIJAQtTdHJpbmdFbnRyeQIFFnJld2FyZFBlck5zYnRTdW1OZXdLRVkJAKYDAQkAtwICCQCnAwEFCnN1bUxhc3RTdHIFEHJld2FyZFBlck5zYnRYMTgJAQtTdHJpbmdFbnRyeQIFFnJld2FyZFBlck5zYnRTdW1OZXdLRVkFCnN1bUxhc3RTdHIJAM0IAgoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARdyZWZyZXNoUmV3YXJkUGVyTnNidFNVTQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkBDEludGVnZXJFbnRyeQIFEWRlcG9zaXROdW1MYXN0S0VZBQ1kZXBvc2l0TnVtTmV3AWkBDGNsYWltUmV3YXJkcwAJAQtjb21tb25DbGFpbQIIBQFpBmNhbGxlcgUBaQFpARpjbGFpbVJld2FyZHNCeU9yaWdpbkNhbGxlcgAJAQtjb21tb25DbGFpbQIIBQFpDG9yaWdpbkNhbGxlcgUBaQFpARh1bmNsYWltZWRSZXdhcmRzUkVBRE9OTFkBDnVzZXJBZGRyZXNzU3RyCgEWZm9yRWFjaEFzc2V0WmVyb1Jld2FyZAIFYWNjdW0FYXNzZXQJAKwCAgkArAICBQVhY2N1bQkAuQkCCQDMCAIFBWFzc2V0CQDMCAICATAJAMwIAgIBMAUDbmlsAgE6AgFfBBJ1bmNsYWltZWRSZXdhcmRTdHIDCQAAAgUOdXNlckFkZHJlc3NTdHICAAoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARZmb3JFYWNoQXNzZXRaZXJvUmV3YXJkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAt1c2VyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUOdXNlckFkZHJlc3NTdHIEDSR0MDIwMjUwMjAzNTUJAQt2YWx1ZU9yRWxzZQIJARNnZXRVc2VyUGFyYW1zT3JVbml0AQULdXNlckFkZHJlc3MJAJUKAwYAAAAABAlpc05ld1VzZXIIBQ0kdDAyMDI1MDIwMzU1Al8xBAxzdGFrZWRBbW91bnQIBQ0kdDAyMDI1MDIwMzU1Al8yBAxzdGFraW5nU3RhcnQIBQ0kdDAyMDI1MDIwMzU1Al8zBA1zdGFrZWRBbW91bnRYCQC2AgEFDHN0YWtlZEFtb3VudAQbdXNlclJld2FyZEZyb21EZXBvc2l0TnVtS0VZCQEba2V5VXNlclJld2FyZEZyb21EZXBvc2l0TnVtAQUOdXNlckFkZHJlc3NTdHIEDmRlcG9zaXROdW1Vc2VyCQEMZ2V0SW50T3JFbHNlAgUbdXNlclJld2FyZEZyb21EZXBvc2l0TnVtS0VZAP///////////wEEDmRlcG9zaXROdW1MYXN0CQEMZ2V0SW50T3JFbHNlAgkBEWtleURlcG9zaXROdW1MYXN0AAD///////////8BCgEfZm9yRWFjaEFzc2V0Q2FsY1VuY2xhaW1lZFJld2FyZAIFYWNjdW0FYXNzZXQEDSR0MDIwNzAxMjA4MzkJAQpjYWxjUmV3YXJkBQUOdXNlckFkZHJlc3NTdHIFBWFzc2V0BQ1zdGFrZWRBbW91bnRYBQ5kZXBvc2l0TnVtVXNlcgUOZGVwb3NpdE51bUxhc3QEC3Jld2FyZFRvdGFsCAUNJHQwMjA3MDEyMDgzOQJfMQQGY2FjaGVkCAUNJHQwMjA3MDEyMDgzOQJfMgQHZHluYW1pYwgFDSR0MDIwNzAxMjA4MzkCXzMEE3Jld2FyZENhY2hlZFBhcnRLRVkIBQ0kdDAyMDcwMTIwODM5Al80BAdjbGFpbWVkCQELdmFsdWVPckVsc2UCCQCfCAEJAQprZXlDbGFpbWVkAgUOdXNlckFkZHJlc3NTdHIFBWFzc2V0AAAJAKwCAgkArAICBQVhY2N1bQkAuQkCCQDMCAIFBWFzc2V0CQDMCAIJAKQDAQULcmV3YXJkVG90YWwJAMwIAgkApAMBBQdjbGFpbWVkBQNuaWwCAToCAV8KAAIkbAUTc3VwcG9ydGVkQXNzZXRzTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEfZm9yRWFjaEFzc2V0Q2FsY1VuY2xhaW1lZFJld2FyZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAlAoCBQNuaWwJALMCAgUSdW5jbGFpbWVkUmV3YXJkU3RyAAEBaQEWdXNkblN0YWtpbmdTWVNSRUFET05MWQIVdXNlckFkZHJlc3NTdHJPckVtcHR5CHVzZG5EaWZmBAl1c2RuVG90YWwJAQxnZXRJbnRPckVsc2UCCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAAADCQAAAgUVdXNlckFkZHJlc3NTdHJPckVtcHR5AgAJAJQKAgUDbmlsCQDMCAIAAAkAzAgCBQl1c2RuVG90YWwJAMwIAgAACQDMCAIAAAkAzAgCAAAJAMwIAgUGaGVpZ2h0CQDMCAIFBmhlaWdodAUDbmlsBAt1c2VyQWRkcmVzcwkBD3RvQWRkcmVzc09yRmFpbAEFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQQKbWVyZ2VkRGF0YQkBCm1lcmdlU3Rha2UCBQt1c2VyQWRkcmVzcwUIdXNkbkRpZmYECWlzTmV3VXNlcggFCm1lcmdlZERhdGECXzEEDHN0YWtlZEFtb3VudAgFCm1lcmdlZERhdGECXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUKbWVyZ2VkRGF0YQJfMwQPc3Rha2VkQW1vdW50TkVXCAUKbWVyZ2VkRGF0YQJfNAQUdnBFZmZlY3RpdmVIZWlnaHRORVcIBQptZXJnZWREYXRhAl81BAh1c2RuVXNlcgUMc3Rha2VkQW1vdW50CQCUCgIFA25pbAkAzAgCBQh1c2RuVXNlcgkAzAgCBQl1c2RuVG90YWwJAMwIAgAACQDMCAIAAAkAzAgCBRF2cEVmZmVjdGl2ZUhlaWdodAkAzAgCBRR2cEVmZmVjdGl2ZUhlaWdodE5FVwUDbmlsAWkBEWNvbmZpZ1NZU1JFQURPTkxZAAQKbWluTG9ja0FtdAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBEGtleU1pbkxvY2tBbW91bnQACQCUCgIFA25pbAkAzAgCBQptaW5Mb2NrQW10BQNuaWwAXx1Q8w==", "height": 2268311, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: E3yMgRXnYujy2oV8W5LDv98PeUamSkJTT1ZuDPSXTS8W Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let revisionNum = ""
5+
6+let separator = "__"
7+
8+let SEP = "__"
9+
10+let MULT6 = 1000000
11+
12+let MULT8 = 100000000
13+
14+let MULTX6 = toBigInt(MULT6)
15+
16+let MULTX8 = toBigInt(MULT8)
17+
18+let MULTX18 = toBigInt(1000000000000000000)
19+
20+let USDNIDSTR = "USDN"
21+
22+let USDNID = fromBase58String(USDNIDSTR)
23+
24+let IdxControlCfgNeutrinoDapp = 1
25+
26+let IdxControlCfgAuctionDapp = 2
27+
28+let IdxControlCfgRpdDapp = 3
29+
30+let IdxControlCfgMathDapp = 4
31+
32+let IdxControlCfgLiquidationDapp = 5
33+
34+let IdxControlCfgRestDapp = 6
35+
36+let IdxControlCfgNodeRegistryDapp = 7
37+
38+let IdxControlCfgNsbtStakingDapp = 8
39+
40+let IdxControlCfgMediatorDapp = 9
41+
42+let IdxControlCfgSurfStakingDapp = 10
43+
44+let IdxControlCfgGnsbtControllerDapp = 11
45+
46+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
47+
48+
49+func keyControlAddress () = "%s%s__config__controlAddress"
50+
51+
52+func keyControlCfg () = "%s__controlConfig"
53+
54+
55+func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
56+
57+
58+func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
59+
60+
61+let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
62+
63+let controlCfg = readControlCfgOrFail(controlContract)
64+
65+let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
66+
67+let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
68+
69+let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
70+
71+func keyBondAsset () = "bond_asset_id"
72+
73+
74+func keyAuctionContractAddress () = "auction_contract"
75+
76+
77+func keyMinLockAmount () = "%s__minLockAmount"
78+
79+
80+func keyStakedAssetId () = "%s__stakedAssetId"
81+
82+
83+func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "amount"], separator)
84+
85+
86+func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
87+
88+
89+func keyLockParamVotingPowerEffectiveHeight (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "vpEffectiveHeight"], separator)
90+
91+
92+func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
93+
94+
95+func keyLockParamTotalAmount () = makeString(["%s%s", "stats", "activeTotalLocked"], separator)
96+
97+
98+func keyStatsLocksCount () = makeString(["%s%s", "stats", "locksCount"], separator)
99+
100+
101+func keyStatsUsersCount () = makeString(["%s%s", "stats", "activeUsersCount"], separator)
102+
103+
104+func keyNextPeriod () = "%s__nextPeriod"
105+
106+
107+func keySupportedRewardAssets () = "supportedRewardAssets"
108+
109+
110+func keyDepositNumLast () = makeString(["%s%s%s", "dep", "lastNum"], separator)
111+
112+
113+func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s%s", "userRwdFromDepNum", userAddress], separator)
114+
115+
116+func keyRewardPerNsbtSumAt (depositNum,tkn) = makeString(["%s%d", "rwdPerNsbtSumByDepNum", toString(depositNum), tkn], separator)
117+
118+
119+func keyReward (userAddress,tkn) = makeString(["%s%s%s", "rwd", userAddress, tkn], separator)
120+
121+
122+func keyClaimed (userAddress,tkn) = makeString(["%s%s%s", "clm", userAddress, tkn], separator)
123+
124+
125+func keyNotDistributedReward (tkn) = makeString(["%s%s", "notDistributed", tkn], separator)
126+
127+
128+func toX18 (origVal,origMult) = fraction(toBigInt(origVal), MULTX18, origMult)
129+
130+
131+func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
132+
133+
134+func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
135+
136+
137+func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
138+
139+
140+func getStrOrElse (key,defaultVal) = valueOrElse(getString(this, key), defaultVal)
141+
142+
143+func toAddressOrFail (addressStr) = valueOrErrorMessage(addressFromString(addressStr), ("couldn't parse passed addressStr=" + addressStr))
144+
145+
146+func toAssetVect (assetStr) = if ((assetStr == USDNIDSTR))
147+ then unit
148+ else fromBase58String(assetStr)
149+
150+
151+func asInt (val) = match val {
152+ case valInt: Int =>
153+ valInt
154+ case _ =>
155+ throw("fail to cast into Int")
156+}
157+
158+
159+func asSwapParamsSTRUCT (v) = match v {
160+ case struct: (Int, Int, Int, Int, Int, Int, Int) =>
161+ struct
162+ case _ =>
163+ throw("fail to cast into Int")
164+}
165+
166+
167+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)
168+
169+
170+func formatClaimHistoryRecord (user,claimedRewards) = makeString(["%s%d%d%s", user, toString(lastBlock.height), toString(lastBlock.timestamp), claimedRewards], separator)
171+
172+
173+func HistoryRecordEntry (type,userAddress,txId,oldAmount,oldStart,newAmount,newStart) = StringEntry(keyHistoryRecord(type, userAddress, txId), formatHistoryRecord(oldAmount, oldStart, newAmount, newStart))
174+
175+
176+func ClaimHistoryEntry (userAddress,txId,claimedRewards) = StringEntry(keyHistoryRecord("claim", userAddress, txId), formatClaimHistoryRecord(toString(userAddress), claimedRewards))
177+
178+
179+func StatsResult (totalLockedInc,lockCountInc,usersCountInc) = {
180+ let locksCount = getIntOrZero(keyStatsLocksCount())
181+ let usersCount = getIntOrZero(keyStatsUsersCount())
182+ let totalAmount = getIntOrZero(keyLockParamTotalAmount())
183+ let totalAmountNew = (totalAmount + totalLockedInc)
184+ $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew)], totalAmount, totalAmountNew)
185+ }
186+
187+
188+func LockParamsEntry (userAddress,amount,votingPowerEffectiveHeight) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), votingPowerEffectiveHeight)]
189+
190+
191+func getParamsOrFail () = $Tuple2(fromBase58String(getStringOrFail(this, keyStakedAssetId())), getIntOrFail(keyMinLockAmount()))
192+
193+
194+func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
195+
196+
197+func getUserParamsOrUnit (userAddress) = if (isActiveUser(userAddress))
198+ then $Tuple3(false, getIntOrFail(keyLockParamUserAmount(userAddress)), getIntOrFail(keyLockParamStartBlock(userAddress)))
199+ else unit
200+
201+
202+func getUserParamsOrFail (userAddress) = valueOrErrorMessage(getUserParamsOrUnit(userAddress), (("User " + toString(userAddress)) + " is not defined"))
203+
204+
205+let supportedAssetsStr = getStrOrElse(keySupportedRewardAssets(), "")
206+
207+let supportedAssetsList = split(supportedAssetsStr, "_")
208+
209+func calcReward (userAddress,assetId,stakedAmountX,depositNumUser,depositNumLast) = {
210+ let rewardPerNsbtSumLastKEY = keyRewardPerNsbtSumAt(depositNumLast, assetId)
211+ let sumLastX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, assetId), "0"))
212+ let sumUserX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumUser, assetId), "0"))
213+ let rewardDynamicPart = toInt(fraction((sumLastX18 - sumUserX18), stakedAmountX, MULTX18))
214+ let rewardCachedPartKEY = keyReward(userAddress, assetId)
215+ let rewardCachedPart = getIntOrElse(rewardCachedPartKEY, 0)
216+ $Tuple4((rewardCachedPart + rewardDynamicPart), rewardCachedPart, rewardDynamicPart, rewardCachedPartKEY)
217+ }
218+
219+
220+func RewardEntries (isNewUser,userAddress,stakedAmount) = {
221+ let stakedAmountX = toBigInt(stakedAmount)
222+ let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddress)
223+ let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
224+ let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
225+ func forEachAssetCacheUserReward (accum,asset) = {
226+ let $t087978932 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
227+ let rewardTotal = $t087978932._1
228+ let cached = $t087978932._2
229+ let dynamic = $t087978932._3
230+ let rewardCachedPartKEY = $t087978932._4
231+ (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
232+ }
233+
234+ if (if ((depositNumLast == -1))
235+ then (depositNumUser == -1)
236+ else false)
237+ then nil
238+ else if (if ((depositNumLast == -1))
239+ then (depositNumUser > -1)
240+ else false)
241+ then throw("invalid depositNumLast and depositNumUser state")
242+ else if (if ((depositNumLast > -1))
243+ then (depositNumUser >= -1)
244+ else false)
245+ then if (isNewUser)
246+ then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
247+ else ({
248+ let $l = supportedAssetsList
249+ let $s = size($l)
250+ let $acc0 = nil
251+ func $f0_1 ($a,$i) = if (($i >= $s))
252+ then $a
253+ else forEachAssetCacheUserReward($a, $l[$i])
254+
255+ func $f0_2 ($a,$i) = if (($i >= $s))
256+ then $a
257+ else throw("List size exceeds 10")
258+
259+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
260+ } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
261+ else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
262+ }
263+
264+
265+func IncrementNotDistributedRewardEntry (tkn,amountInc) = {
266+ let notDistributedRewardKEY = keyNotDistributedReward(tkn)
267+ let notDistributedReward = getIntOrElse(notDistributedRewardKEY, 0)
268+[IntegerEntry(notDistributedRewardKEY, (notDistributedReward + amountInc))]
269+ }
270+
271+
272+func mergeVotingPowerEffectiveHeight (quarantinePeriod,vpEffectiveHeight,stakedAmt,stakedAmtNEW) = {
273+ let remainingToWait = (vpEffectiveHeight - height)
274+ if ((0 >= remainingToWait))
275+ then (height + quarantinePeriod)
276+ else {
277+ let alreadyWaited = (quarantinePeriod - remainingToWait)
278+ let kX8 = if ((stakedAmtNEW != 0))
279+ then fraction(stakedAmt, MULT8, stakedAmtNEW)
280+ else vpEffectiveHeight
281+ ((quarantinePeriod + height) - fraction(alreadyWaited, kX8, MULT8))
282+ }
283+ }
284+
285+
286+func mergeStake (userAddress,amountToAdd) = {
287+ let $t01251712627 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
288+ let isNewUser = $t01251712627._1
289+ let stakedAmount = $t01251712627._2
290+ let vpEffectiveHeight = $t01251712627._3
291+ let stakedAmountNEW = if (isNewUser)
292+ then amountToAdd
293+ else (amountToAdd + stakedAmount)
294+ let quarantinePeriod = (1440 * 14)
295+ let vpEffectiveHeightNEW = if (isNewUser)
296+ then (quarantinePeriod + height)
297+ else mergeVotingPowerEffectiveHeight(quarantinePeriod, vpEffectiveHeight, stakedAmount, stakedAmountNEW)
298+ $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)
299+ }
300+
301+
302+func commonStake (userAddress,i) = {
303+ let $t01311313167 = getParamsOrFail()
304+ let stakedAssetId = $t01311313167._1
305+ let minLockAmount = $t01311313167._2
306+ if ((size(i.payments) != 1))
307+ then throw("Invalid payments size")
308+ else {
309+ let payment = i.payments[0]
310+ let amount = payment.amount
311+ let invalidAssetMessage = (("Invalid asset. " + toBase58String(stakedAssetId)) + " is expected")
312+ let assetId = valueOrErrorMessage(payment.assetId, invalidAssetMessage)
313+ if ((assetId != stakedAssetId))
314+ then throw(invalidAssetMessage)
315+ else {
316+ let userAddressStr = toString(userAddress)
317+ let mergedData = mergeStake(userAddress, amount)
318+ let isNewUser = mergedData._1
319+ let stakedAmount = mergedData._2
320+ let vpEffectiveHeight = mergedData._3
321+ let stakedAmountNEW = mergedData._4
322+ let vpEffectiveHeightNEW = mergedData._5
323+ if ((minLockAmount > stakedAmountNEW))
324+ then throw(("Min lock amount is " + toString(minLockAmount)))
325+ else {
326+ let $t01396614068 = StatsResult(amount, 1, if (isNewUser)
327+ then 1
328+ else 0)
329+ let statsEntries = $t01396614068._1
330+ let totalStaked = $t01396614068._2
331+ let totalStakedNew = $t01396614068._3
332+ ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries)
333+ }
334+ }
335+ }
336+ }
337+
338+
339+func commonClaim (userAddress,i) = {
340+ let userAddressStr = toString(userAddress)
341+ if ((size(i.payments) > 0))
342+ then throw("payments are not accepted")
343+ else {
344+ let $t01454714652 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
345+ let isNewUser = $t01454714652._1
346+ let stakedAmount = $t01454714652._2
347+ let stakingStart = $t01454714652._3
348+ let stakedAmountX = toBigInt(stakedAmount)
349+ let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
350+ let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
351+ let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
352+ func forEachAssetCalcUnclaimedReward (accum,asset) = {
353+ let $t01502315161 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
354+ let rewardTotal = $t01502315161._1
355+ let cached = $t01502315161._2
356+ let dynamic = $t01502315161._3
357+ let rewardCachedPartKEY = $t01502315161._4
358+ let claimedKEY = keyClaimed(userAddressStr, asset)
359+ let $t01522115258 = accum
360+ let data = $t01522115258._1
361+ let claimedAmtByAsset = $t01522115258._2
362+ let newPart = makeString([asset, toString(rewardTotal)], ":")
363+ let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
364+ if ((0 >= rewardTotal))
365+ then $Tuple2(data, claimedAmtByAssetNew)
366+ else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
367+ }
368+
369+ let $t01571815832 = {
370+ let $l = supportedAssetsList
371+ let $s = size($l)
372+ let $acc0 = $Tuple2(nil, "")
373+ func $f0_1 ($a,$i) = if (($i >= $s))
374+ then $a
375+ else forEachAssetCalcUnclaimedReward($a, $l[$i])
376+
377+ func $f0_2 ($a,$i) = if (($i >= $s))
378+ then $a
379+ else throw("List size exceeds 10")
380+
381+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
382+ }
383+ let transfers = $t01571815832._1
384+ let claimedAmtByAssetResult = $t01571815832._2
385+ if ((0 >= size(transfers)))
386+ then nil
387+ else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
388+ }
389+ }
390+
391+
392+@Callable(i)
393+func constructor (minLockAmount,supportedRewardAssets,stakedAssetId) = if ((i.caller != this))
394+ then throw("Permission denied")
395+ else [IntegerEntry(keyMinLockAmount(), minLockAmount), StringEntry(keySupportedRewardAssets(), supportedRewardAssets), StringEntry(keyStakedAssetId(), stakedAssetId)]
396+
397+
398+
399+@Callable(i)
400+func stake () = commonStake(i.caller, i)
401+
402+
403+
404+@Callable(i)
405+func stakeByOriginCaller () = commonStake(i.originCaller, i)
406+
407+
408+
409+@Callable(i)
410+func unstake (amount) = if ((size(i.payments) != 0))
411+ then throw("unstake doesn't require any payment")
412+ else {
413+ let userAddress = i.caller
414+ let userAddressStr = toString(userAddress)
415+ let $t01674116795 = getParamsOrFail()
416+ let stakedAssetId = $t01674116795._1
417+ let minLockAmount = $t01674116795._2
418+ let $t01679816882 = getUserParamsOrFail(userAddress)
419+ let isNewUser = $t01679816882._1
420+ let stakedAmount = $t01679816882._2
421+ let vpEffectiveHeight = $t01679816882._3
422+ let swapParamsSTRUCT = asSwapParamsSTRUCT(reentrantInvoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStr, 0], nil))
423+ let swapLimitSpentInUsdn = swapParamsSTRUCT._2
424+ let blcks2LmtReset = swapParamsSTRUCT._3
425+ if ((swapLimitSpentInUsdn > 0))
426+ then throw((("You have already made a swap operation. Wait " + toString((height + blcks2LmtReset))) + " height to unstake"))
427+ else if ((0 >= stakedAmount))
428+ then throw("Nothing to unstake")
429+ else if ((amount > stakedAmount))
430+ then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(stakedAmount)))
431+ else {
432+ let stakedAmountNEW = (stakedAmount - amount)
433+ let $t01752017678 = StatsResult(-(amount), if ((amount == stakedAmount))
434+ then -1
435+ else 0, if ((amount == stakedAmount))
436+ then -1
437+ else 0)
438+ let statsEntries = $t01752017678._1
439+ let totalStaked = $t01752017678._2
440+ let totalStakedNew = $t01752017678._3
441+ ((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeight)] ++ RewardEntries(false, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeight)) ++ statsEntries)
442+ }
443+ }
444+
445+
446+
447+@Callable(i)
448+func deposit () = if ((size(i.payments) != 1))
449+ then throw("exact 1 payment is allowed only")
450+ else {
451+ let pmt = i.payments[0]
452+ let amount = pmt.amount
453+ let pmtAssetId = valueOrElse(pmt.assetId, USDNID)
454+ let pmtAssetIdStr = toBase58String(pmtAssetId)
455+ let pmtMultX = if ((pmtAssetId == USDNID))
456+ then MULTX8
457+ else MULTX6
458+ let amountX = toBigInt(amount)
459+ let totalStaked = getIntOrElse(keyLockParamTotalAmount(), 0)
460+ let totalStakedX = toBigInt(totalStaked)
461+ if ((0 > totalStaked))
462+ then throw("TODO: case is not supported")
463+ else if ((totalStaked == 0))
464+ then IncrementNotDistributedRewardEntry(pmtAssetIdStr, amount)
465+ else {
466+ let rewardPerNsbtX18 = fraction(amountX, MULTX18, totalStakedX)
467+ let depositNumLastKEY = keyDepositNumLast()
468+ let depositNumLast = getIntOrElse(depositNumLastKEY, -1)
469+ let depositNumNew = (depositNumLast + 1)
470+ if (!(contains(supportedAssetsStr, pmtAssetIdStr)))
471+ then throw(((supportedAssetsStr + " doesn't contain ") + pmtAssetIdStr))
472+ else {
473+ func refreshRewardPerNsbtSUM (accum,nextAsset) = {
474+ let rewardPerNsbtSumNewKEY = keyRewardPerNsbtSumAt(depositNumNew, nextAsset)
475+ let sumLastStr = getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, nextAsset), "0")
476+ (accum :+ (if ((nextAsset == pmtAssetIdStr))
477+ then StringEntry(rewardPerNsbtSumNewKEY, toString((parseBigIntValue(sumLastStr) + rewardPerNsbtX18)))
478+ else StringEntry(rewardPerNsbtSumNewKEY, sumLastStr)))
479+ }
480+
481+ ({
482+ let $l = supportedAssetsList
483+ let $s = size($l)
484+ let $acc0 = nil
485+ func $f0_1 ($a,$i) = if (($i >= $s))
486+ then $a
487+ else refreshRewardPerNsbtSUM($a, $l[$i])
488+
489+ func $f0_2 ($a,$i) = if (($i >= $s))
490+ then $a
491+ else throw("List size exceeds 10")
492+
493+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
494+ } :+ IntegerEntry(depositNumLastKEY, depositNumNew))
495+ }
496+ }
497+ }
498+
499+
500+
501+@Callable(i)
502+func claimRewards () = commonClaim(i.caller, i)
503+
504+
505+
506+@Callable(i)
507+func claimRewardsByOriginCaller () = commonClaim(i.originCaller, i)
508+
509+
510+
511+@Callable(i)
512+func unclaimedRewardsREADONLY (userAddressStr) = {
513+ func forEachAssetZeroReward (accum,asset) = ((accum + makeString([asset, "0", "0"], ":")) + "_")
514+
515+ let unclaimedRewardStr = if ((userAddressStr == ""))
516+ then {
517+ let $l = supportedAssetsList
518+ let $s = size($l)
519+ let $acc0 = ""
520+ func $f0_1 ($a,$i) = if (($i >= $s))
521+ then $a
522+ else forEachAssetZeroReward($a, $l[$i])
523+
524+ func $f0_2 ($a,$i) = if (($i >= $s))
525+ then $a
526+ else throw("List size exceeds 10")
527+
528+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
529+ }
530+ else {
531+ let userAddress = addressFromStringValue(userAddressStr)
532+ let $t02025020355 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
533+ let isNewUser = $t02025020355._1
534+ let stakedAmount = $t02025020355._2
535+ let stakingStart = $t02025020355._3
536+ let stakedAmountX = toBigInt(stakedAmount)
537+ let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
538+ let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
539+ let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
540+ func forEachAssetCalcUnclaimedReward (accum,asset) = {
541+ let $t02070120839 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
542+ let rewardTotal = $t02070120839._1
543+ let cached = $t02070120839._2
544+ let dynamic = $t02070120839._3
545+ let rewardCachedPartKEY = $t02070120839._4
546+ let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
547+ ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
548+ }
549+
550+ let $l = supportedAssetsList
551+ let $s = size($l)
552+ let $acc0 = ""
553+ func $f0_1 ($a,$i) = if (($i >= $s))
554+ then $a
555+ else forEachAssetCalcUnclaimedReward($a, $l[$i])
556+
557+ func $f0_2 ($a,$i) = if (($i >= $s))
558+ then $a
559+ else throw("List size exceeds 10")
560+
561+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
562+ }
563+ $Tuple2(nil, dropRight(unclaimedRewardStr, 1))
564+ }
565+
566+
567+
568+@Callable(i)
569+func usdnStakingSYSREADONLY (userAddressStrOrEmpty,usdnDiff) = {
570+ let usdnTotal = getIntOrElse(keyLockParamTotalAmount(), 0)
571+ if ((userAddressStrOrEmpty == ""))
572+ then $Tuple2(nil, [0, usdnTotal, 0, 0, 0, height, height])
573+ else {
574+ let userAddress = toAddressOrFail(userAddressStrOrEmpty)
575+ let mergedData = mergeStake(userAddress, usdnDiff)
576+ let isNewUser = mergedData._1
577+ let stakedAmount = mergedData._2
578+ let vpEffectiveHeight = mergedData._3
579+ let stakedAmountNEW = mergedData._4
580+ let vpEffectiveHeightNEW = mergedData._5
581+ let usdnUser = stakedAmount
582+ $Tuple2(nil, [usdnUser, usdnTotal, 0, 0, vpEffectiveHeight, vpEffectiveHeightNEW])
583+ }
584+ }
585+
586+
587+
588+@Callable(i)
589+func configSYSREADONLY () = {
590+ let minLockAmt = getIntegerValue(keyMinLockAmount())
591+ $Tuple2(nil, [minLockAmt])
592+ }
593+
594+

github/deemru/w8io/3ef1775 
45.96 ms