tx · 5HtetvPxVF4qncRXZvhm9D3z1uCBUy7ehSNoELQHYnro

3N5yarEiTQccnnuerogYT3BxM5Zc5bRgDZy:  -0.04000000 Waves

2022.08.05 06:28 [2170645] smart account 3N5yarEiTQccnnuerogYT3BxM5Zc5bRgDZy > SELF 0.00000000 Waves

{ "type": 13, "id": "5HtetvPxVF4qncRXZvhm9D3z1uCBUy7ehSNoELQHYnro", "fee": 4000000, "feeAssetId": null, "timestamp": 1659670026130, "version": 1, "sender": "3N5yarEiTQccnnuerogYT3BxM5Zc5bRgDZy", "senderPublicKey": "FK9j3YFWVChXKESTn33fMZz1JseCNMMqHhfB7smxJo4e", "proofs": [ "51M6nNDFsdbbDWTTQxSD71RSC6QsQDRSyivLJSuQZwHKHwnsKZKhwwv8vqTCVfEXeXeUgUnAUjd6B9FxKXFWVMi3" ], "script": "base64:BgIlCAISBQoDAQgIEgASABIDCgEBEgASABIAEgMKAQgSBAoCCAESAE0ACXNlcGFyYXRvcgICX18AA1NFUAICX18ABU1VTFQ2AMCEPQAFTVVMVDgAgMLXLwAGTVVMVFg2CQC2AgEFBU1VTFQ2AAZNVUxUWDgJALYCAQUFTVVMVDgAB01VTFRYMTgJALYCAQCAgJC7utat8A0ACldBVkVTSURTVFICBVdBVkVTAAdXQVZFU0lECQDZBAEFCldBVkVTSURTVFIAGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAAQAYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwAAIAFElkeENvbnRyb2xDZmdScGREYXBwAAMAFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAEABxJZHhDb250cm9sQ2ZnTGlxdWlkYXRpb25EYXBwAAUAFUlkeENvbnRyb2xDZmdSZXN0RGFwcAAGAB1JZHhDb250cm9sQ2ZnTm9kZVJlZ2lzdHJ5RGFwcAAHABxJZHhDb250cm9sQ2ZnTnNidFN0YWtpbmdEYXBwAAgAGUlkeENvbnRyb2xDZmdNZWRpYXRvckRhcHAACQAcSWR4Q29udHJvbENmZ1N1cmZTdGFraW5nRGFwcAAKACBJZHhDb250cm9sQ2ZnR25zYnRDb250cm9sbGVyRGFwcAALAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQCsAgIJAKwCAgkArAICCQCsAgICCm1hbmRhdG9yeSAJAKUIAQUHYWRkcmVzcwIBLgUDa2V5Ag8gaXMgbm90IGRlZmluZWQBEWtleUNvbnRyb2xBZGRyZXNzAAIcJXMlc19fY29uZmlnX19jb250cm9sQWRkcmVzcwENa2V5Q29udHJvbENmZwACESVzX19jb250cm9sQ29uZmlnARRyZWFkQ29udHJvbENmZ09yRmFpbAEHY29udHJvbAkAtQkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUHY29udHJvbAkBDWtleUNvbnRyb2xDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIKY29udHJvbENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCmNvbnRyb2xDZmcFA2lkeAkArAICAi1Db250cm9sIGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AA9jb250cm9sQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBEWtleUNvbnRyb2xBZGRyZXNzAAIjM040TlM3ZDRKbzlhNkYxNExpRlVLS1lWZFVra2YyZVA0WngACmNvbnRyb2xDZmcJARRyZWFkQ29udHJvbENmZ09yRmFpbAEFD2NvbnRyb2xDb250cmFjdAAMbWF0aENvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUVSWR4Q29udHJvbENmZ01hdGhEYXBwABBuZXV0cmlub0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAAPYXVjdGlvbkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwAQxrZXlCb25kQXNzZXQAAg1ib25kX2Fzc2V0X2lkARlrZXlBdWN0aW9uQ29udHJhY3RBZGRyZXNzAAIQYXVjdGlvbl9jb250cmFjdAEQa2V5TWluTG9ja0Ftb3VudAACESVzX19taW5Mb2NrQW1vdW50ARBrZXlTdGFrZWRBc3NldElkAAIRJXNfX3N0YWtlZEFzc2V0SWQBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIJAKUIAQULdXNlckFkZHJlc3MJAMwIAgIGYW1vdW50BQNuaWwFCXNlcGFyYXRvcgEWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgILcGFyYW1CeVVzZXIJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwkAzAgCAgVzdGFydAUDbmlsBQlzZXBhcmF0b3IBJmtleUxvY2tQYXJhbVZvdGluZ1Bvd2VyRWZmZWN0aXZlSGVpZ2h0AQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgtwYXJhbUJ5VXNlcgkAzAgCCQClCAEFC3VzZXJBZGRyZXNzCQDMCAICEXZwRWZmZWN0aXZlSGVpZ2h0BQNuaWwFCXNlcGFyYXRvcgEQa2V5SGlzdG9yeVJlY29yZAMEdHlwZQt1c2VyQWRkcmVzcwR0eElkCQC5CQIJAMwIAgIIJXMlcyVzJXMJAMwIAgIHaGlzdG9yeQkAzAgCBQR0eXBlCQDMCAIJAKUIAQULdXNlckFkZHJlc3MJAMwIAgkA2AQBBQR0eElkBQNuaWwFCXNlcGFyYXRvcgEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVzdGF0cwkAzAgCAhFhY3RpdmVUb3RhbExvY2tlZAUDbmlsBQlzZXBhcmF0b3IBEmtleVN0YXRzTG9ja3NDb3VudAAJALkJAgkAzAgCAgQlcyVzCQDMCAICBXN0YXRzCQDMCAICCmxvY2tzQ291bnQFA25pbAUJc2VwYXJhdG9yARJrZXlTdGF0c1VzZXJzQ291bnQACQC5CQIJAMwIAgIEJXMlcwkAzAgCAgVzdGF0cwkAzAgCAhBhY3RpdmVVc2Vyc0NvdW50BQNuaWwFCXNlcGFyYXRvcgENa2V5TmV4dFBlcmlvZAACDiVzX19uZXh0UGVyaW9kARhrZXlTdXBwb3J0ZWRSZXdhcmRBc3NldHMAAhVzdXBwb3J0ZWRSZXdhcmRBc3NldHMBEWtleURlcG9zaXROdW1MYXN0AAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgNkZXAJAMwIAgIHbGFzdE51bQUDbmlsBQlzZXBhcmF0b3IBG2tleVVzZXJSZXdhcmRGcm9tRGVwb3NpdE51bQELdXNlckFkZHJlc3MJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIRdXNlclJ3ZEZyb21EZXBOdW0JAMwIAgULdXNlckFkZHJlc3MFA25pbAUJc2VwYXJhdG9yARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCCmRlcG9zaXROdW0DdGtuCQC5CQIJAMwIAgIEJXMlZAkAzAgCAhVyd2RQZXJOc2J0U3VtQnlEZXBOdW0JAMwIAgkApAMBBQpkZXBvc2l0TnVtCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBCWtleVJld2FyZAILdXNlckFkZHJlc3MDdGtuCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICA3J3ZAkAzAgCBQt1c2VyQWRkcmVzcwkAzAgCBQN0a24FA25pbAUJc2VwYXJhdG9yAQprZXlDbGFpbWVkAgt1c2VyQWRkcmVzcwN0a24JALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIDY2xtCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBF2tleU5vdERpc3RyaWJ1dGVkUmV3YXJkAQN0a24JALkJAgkAzAgCAgQlcyVzCQDMCAICDm5vdERpc3RyaWJ1dGVkCQDMCAIFA3RrbgUDbmlsBQlzZXBhcmF0b3IBBXRvWDE4AgdvcmlnVmFsCG9yaWdNdWx0CQC8AgMJALYCAQUHb3JpZ1ZhbAUHTVVMVFgxOAUIb3JpZ011bHQBDGdldEludE9yWmVybwEDa2V5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQxnZXRJbnRPckVsc2UCA2tleQpkZWZhdWx0VmFsCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQUKZGVmYXVsdFZhbAEMZ2V0SW50T3JGYWlsAQNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQNrZXkJAKwCAgkArAICAg9NYW5kYXRvcnkgdGhpcy4FA2tleQIPIGlzIG5vdCBkZWZpbmVkAQxnZXRTdHJPckVsc2UCA2tleQpkZWZhdWx0VmFsCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFA2tleQUKZGVmYXVsdFZhbAEPdG9BZGRyZXNzT3JGYWlsAQphZGRyZXNzU3RyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUKYWRkcmVzc1N0cgkArAICAiFjb3VsZG4ndCBwYXJzZSBwYXNzZWQgYWRkcmVzc1N0cj0FCmFkZHJlc3NTdHIBC3RvQXNzZXRWZWN0AQhhc3NldFN0cgMJAAACBQhhc3NldFN0cgUKV0FWRVNJRFNUUgUEdW5pdAkA2QQBBQhhc3NldFN0cgEFYXNJbnQBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACA0ludAQGdmFsSW50BQckbWF0Y2gwBQZ2YWxJbnQJAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBE2Zvcm1hdEhpc3RvcnlSZWNvcmQECW9sZEFtb3VudAhvbGRTdGFydAluZXdBbW91bnQIbmV3U3RhcnQJALkJAgkAzAgCAgwlZCVkJWQlZCVkJWQJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUJb2xkQW1vdW50CQDMCAIJAKQDAQUIb2xkU3RhcnQJAMwIAgkApAMBBQluZXdBbW91bnQJAMwIAgkApAMBBQhuZXdTdGFydAUDbmlsBQlzZXBhcmF0b3IBGGZvcm1hdENsYWltSGlzdG9yeVJlY29yZAIEdXNlcg5jbGFpbWVkUmV3YXJkcwkAuQkCCQDMCAICCCVzJWQlZCVzCQDMCAIFBHVzZXIJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIFDmNsYWltZWRSZXdhcmRzBQNuaWwFCXNlcGFyYXRvcgESSGlzdG9yeVJlY29yZEVudHJ5BwR0eXBlC3VzZXJBZGRyZXNzBHR4SWQJb2xkQW1vdW50CG9sZFN0YXJ0CW5ld0Ftb3VudAhuZXdTdGFydAkBC1N0cmluZ0VudHJ5AgkBEGtleUhpc3RvcnlSZWNvcmQDBQR0eXBlBQt1c2VyQWRkcmVzcwUEdHhJZAkBE2Zvcm1hdEhpc3RvcnlSZWNvcmQEBQlvbGRBbW91bnQFCG9sZFN0YXJ0BQluZXdBbW91bnQFCG5ld1N0YXJ0ARFDbGFpbUhpc3RvcnlFbnRyeQMLdXNlckFkZHJlc3MEdHhJZA5jbGFpbWVkUmV3YXJkcwkBC1N0cmluZ0VudHJ5AgkBEGtleUhpc3RvcnlSZWNvcmQDAgVjbGFpbQULdXNlckFkZHJlc3MFBHR4SWQJARhmb3JtYXRDbGFpbUhpc3RvcnlSZWNvcmQCCQClCAEFC3VzZXJBZGRyZXNzBQ5jbGFpbWVkUmV3YXJkcwELU3RhdHNSZXN1bHQDDnRvdGFsTG9ja2VkSW5jDGxvY2tDb3VudEluYw11c2Vyc0NvdW50SW5jBApsb2Nrc0NvdW50CQEMZ2V0SW50T3JaZXJvAQkBEmtleVN0YXRzTG9ja3NDb3VudAAECnVzZXJzQ291bnQJAQxnZXRJbnRPclplcm8BCQESa2V5U3RhdHNVc2Vyc0NvdW50AAQLdG90YWxBbW91bnQJAQxnZXRJbnRPclplcm8BCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQABA50b3RhbEFtb3VudE5ldwkAZAIFC3RvdGFsQW1vdW50BQ50b3RhbExvY2tlZEluYwkAlQoDCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESa2V5U3RhdHNMb2Nrc0NvdW50AAkAZAIFCmxvY2tzQ291bnQFDGxvY2tDb3VudEluYwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleVN0YXRzVXNlcnNDb3VudAAJAGQCBQp1c2Vyc0NvdW50BQ11c2Vyc0NvdW50SW5jCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQABQ50b3RhbEFtb3VudE5ldwUDbmlsBQt0b3RhbEFtb3VudAUOdG90YWxBbW91bnROZXcBD0xvY2tQYXJhbXNFbnRyeQMLdXNlckFkZHJlc3MGYW1vdW50GnZvdGluZ1Bvd2VyRWZmZWN0aXZlSGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEFC3VzZXJBZGRyZXNzBQZhbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJARZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAQULdXNlckFkZHJlc3MFGnZvdGluZ1Bvd2VyRWZmZWN0aXZlSGVpZ2h0BQNuaWwBD2dldFBhcmFtc09yRmFpbAAJAJQKAgkA2QQBCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwkBEGtleVN0YWtlZEFzc2V0SWQACQEMZ2V0SW50T3JGYWlsAQkBEGtleU1pbkxvY2tBbW91bnQAAQxpc0FjdGl2ZVVzZXIBC3VzZXJBZGRyZXNzCQBmAgkBDGdldEludE9yRWxzZQIJARZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AQULdXNlckFkZHJlc3MAAAAAARNnZXRVc2VyUGFyYW1zT3JVbml0AQt1c2VyQWRkcmVzcwMJAQxpc0FjdGl2ZVVzZXIBBQt1c2VyQWRkcmVzcwkAlQoDBwkBDGdldEludE9yRmFpbAEJARZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AQULdXNlckFkZHJlc3MJAQxnZXRJbnRPckZhaWwBCQEWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawEFC3VzZXJBZGRyZXNzBQR1bml0ARNnZXRVc2VyUGFyYW1zT3JGYWlsAQt1c2VyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQETZ2V0VXNlclBhcmFtc09yVW5pdAEFC3VzZXJBZGRyZXNzCQCsAgIJAKwCAgIFVXNlciAJAKUIAQULdXNlckFkZHJlc3MCDyBpcyBub3QgZGVmaW5lZAASc3VwcG9ydGVkQXNzZXRzU3RyCQEMZ2V0U3RyT3JFbHNlAgkBGGtleVN1cHBvcnRlZFJld2FyZEFzc2V0cwACAAATc3VwcG9ydGVkQXNzZXRzTGlzdAkAtQkCBRJzdXBwb3J0ZWRBc3NldHNTdHICAV8BCmNhbGNSZXdhcmQFC3VzZXJBZGRyZXNzB2Fzc2V0SWQNc3Rha2VkQW1vdW50WA5kZXBvc2l0TnVtVXNlcg5kZXBvc2l0TnVtTGFzdAQXcmV3YXJkUGVyTnNidFN1bUxhc3RLRVkJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ5kZXBvc2l0TnVtTGFzdAUHYXNzZXRJZAQKc3VtTGFzdFgxOAkApwMBCQEMZ2V0U3RyT3JFbHNlAgkBFWtleVJld2FyZFBlck5zYnRTdW1BdAIFDmRlcG9zaXROdW1MYXN0BQdhc3NldElkAgEwBApzdW1Vc2VyWDE4CQCnAwEJAQxnZXRTdHJPckVsc2UCCQEVa2V5UmV3YXJkUGVyTnNidFN1bUF0AgUOZGVwb3NpdE51bVVzZXIFB2Fzc2V0SWQCATAEEXJld2FyZER5bmFtaWNQYXJ0CQCgAwEJALwCAwkAuAICBQpzdW1MYXN0WDE4BQpzdW1Vc2VyWDE4BQ1zdGFrZWRBbW91bnRYBQdNVUxUWDE4BBNyZXdhcmRDYWNoZWRQYXJ0S0VZCQEJa2V5UmV3YXJkAgULdXNlckFkZHJlc3MFB2Fzc2V0SWQEEHJld2FyZENhY2hlZFBhcnQJAQxnZXRJbnRPckVsc2UCBRNyZXdhcmRDYWNoZWRQYXJ0S0VZAAAJAJYKBAkAZAIFEHJld2FyZENhY2hlZFBhcnQFEXJld2FyZER5bmFtaWNQYXJ0BRByZXdhcmRDYWNoZWRQYXJ0BRFyZXdhcmREeW5hbWljUGFydAUTcmV3YXJkQ2FjaGVkUGFydEtFWQENUmV3YXJkRW50cmllcwMJaXNOZXdVc2VyC3VzZXJBZGRyZXNzDHN0YWtlZEFtb3VudAQNc3Rha2VkQW1vdW50WAkAtgIBBQxzdGFrZWRBbW91bnQEG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQkBG2tleVVzZXJSZXdhcmRGcm9tRGVwb3NpdE51bQEFC3VzZXJBZGRyZXNzBA5kZXBvc2l0TnVtVXNlcgkBDGdldEludE9yRWxzZQIFG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQD///////////8BBA5kZXBvc2l0TnVtTGFzdAkBDGdldEludE9yRWxzZQIJARFrZXlEZXBvc2l0TnVtTGFzdAAA////////////AQoBG2ZvckVhY2hBc3NldENhY2hlVXNlclJld2FyZAIFYWNjdW0FYXNzZXQECyR0MDg2Mzk4Nzc0CQEKY2FsY1Jld2FyZAUFC3VzZXJBZGRyZXNzBQVhc3NldAUNc3Rha2VkQW1vdW50WAUOZGVwb3NpdE51bVVzZXIFDmRlcG9zaXROdW1MYXN0BAtyZXdhcmRUb3RhbAgFCyR0MDg2Mzk4Nzc0Al8xBAZjYWNoZWQIBQskdDA4NjM5ODc3NAJfMgQHZHluYW1pYwgFCyR0MDg2Mzk4Nzc0Al8zBBNyZXdhcmRDYWNoZWRQYXJ0S0VZCAULJHQwODYzOTg3NzQCXzQJAM0IAgUFYWNjdW0JAQxJbnRlZ2VyRW50cnkCBRNyZXdhcmRDYWNoZWRQYXJ0S0VZBQtyZXdhcmRUb3RhbAMDCQAAAgUOZGVwb3NpdE51bUxhc3QA////////////AQkAAAIFDmRlcG9zaXROdW1Vc2VyAP///////////wEHBQNuaWwDAwkAAAIFDmRlcG9zaXROdW1MYXN0AP///////////wEJAGYCBQ5kZXBvc2l0TnVtVXNlcgD///////////8BBwkAAgECL2ludmFsaWQgZGVwb3NpdE51bUxhc3QgYW5kIGRlcG9zaXROdW1Vc2VyIHN0YXRlAwMJAGYCBQ5kZXBvc2l0TnVtTGFzdAD///////////8BCQBnAgUOZGVwb3NpdE51bVVzZXIA////////////AQcDBQlpc05ld1VzZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQUOZGVwb3NpdE51bUxhc3QFA25pbAkAzQgCCgACJGwFE3N1cHBvcnRlZEFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBG2ZvckVhY2hBc3NldENhY2hlVXNlclJld2FyZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkBDEludGVnZXJFbnRyeQIFG3VzZXJSZXdhcmRGcm9tRGVwb3NpdE51bUtFWQUOZGVwb3NpdE51bUxhc3QJAAIBCQCsAgIJAKwCAgkArAICAiR1bmNvdmVyZWQgY29uZGl0aW9uOiBkZXBvc2l0TnVtTGFzdD0JAKQDAQUOZGVwb3NpdE51bUxhc3QCECBkZXBvc2l0TnVtVXNlcj0JAKQDAQUOZGVwb3NpdE51bVVzZXIBIkluY3JlbWVudE5vdERpc3RyaWJ1dGVkUmV3YXJkRW50cnkCA3RrbglhbW91bnRJbmMEF25vdERpc3RyaWJ1dGVkUmV3YXJkS0VZCQEXa2V5Tm90RGlzdHJpYnV0ZWRSZXdhcmQBBQN0a24EFG5vdERpc3RyaWJ1dGVkUmV3YXJkCQEMZ2V0SW50T3JFbHNlAgUXbm90RGlzdHJpYnV0ZWRSZXdhcmRLRVkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXbm90RGlzdHJpYnV0ZWRSZXdhcmRLRVkJAGQCBRRub3REaXN0cmlidXRlZFJld2FyZAUJYW1vdW50SW5jBQNuaWwBC3N1cmZUb0duc2J0AQdzdXJmQW10CQBpAgUHc3VyZkFtdAA8AR9tZXJnZVZvdGluZ1Bvd2VyRWZmZWN0aXZlSGVpZ2h0BBBxdWFyYW50aW5lUGVyaW9kEXZwRWZmZWN0aXZlSGVpZ2h0CXN0YWtlZEFtdAxzdGFrZWRBbXRORVcED3JlbWFpbmluZ1RvV2FpdAkAZQIFEXZwRWZmZWN0aXZlSGVpZ2h0BQZoZWlnaHQDCQBnAgAABQ9yZW1haW5pbmdUb1dhaXQJAGQCBQZoZWlnaHQFEHF1YXJhbnRpbmVQZXJpb2QEDWFscmVhZHlXYWl0ZWQJAGUCBRBxdWFyYW50aW5lUGVyaW9kBQ9yZW1haW5pbmdUb1dhaXQEA2tYOAkAawMFCXN0YWtlZEFtdAUFTVVMVDgFDHN0YWtlZEFtdE5FVwkAZQIJAGQCBRBxdWFyYW50aW5lUGVyaW9kBQZoZWlnaHQJAGsDBQ1hbHJlYWR5V2FpdGVkBQNrWDgFBU1VTFQ4AQptZXJnZVN0YWtlAgt1c2VyQWRkcmVzcwthbW91bnRUb0FkZAQNJHQwMTIzNjcxMjQ3NwkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDEyMzY3MTI0NzcCXzEEDHN0YWtlZEFtb3VudAgFDSR0MDEyMzY3MTI0NzcCXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUNJHQwMTIzNjcxMjQ3NwJfMwQPc3Rha2VkQW1vdW50TkVXAwUJaXNOZXdVc2VyBQthbW91bnRUb0FkZAkAZAIFC2Ftb3VudFRvQWRkBQxzdGFrZWRBbW91bnQEEHF1YXJhbnRpbmVQZXJpb2QJAGgCAKALAA4EFHZwRWZmZWN0aXZlSGVpZ2h0TkVXAwUJaXNOZXdVc2VyCQBkAgUQcXVhcmFudGluZVBlcmlvZAUGaGVpZ2h0CQEfbWVyZ2VWb3RpbmdQb3dlckVmZmVjdGl2ZUhlaWdodAQFEHF1YXJhbnRpbmVQZXJpb2QFEXZwRWZmZWN0aXZlSGVpZ2h0BQxzdGFrZWRBbW91bnQFD3N0YWtlZEFtb3VudE5FVwkAlwoFBQlpc05ld1VzZXIFDHN0YWtlZEFtb3VudAURdnBFZmZlY3RpdmVIZWlnaHQFD3N0YWtlZEFtb3VudE5FVwUUdnBFZmZlY3RpdmVIZWlnaHRORVcBC2NvbW1vblN0YWtlAgt1c2VyQWRkcmVzcwFpBA0kdDAxMjk2MzEzMDE3CQEPZ2V0UGFyYW1zT3JGYWlsAAQNc3Rha2VkQXNzZXRJZAgFDSR0MDEyOTYzMTMwMTcCXzEEDW1pbkxvY2tBbW91bnQIBQ0kdDAxMjk2MzEzMDE3Al8yAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIVSW52YWxpZCBwYXltZW50cyBzaXplBAdwYXltZW50CQCRAwIIBQFpCHBheW1lbnRzAAAEBmFtb3VudAgFB3BheW1lbnQGYW1vdW50BBNpbnZhbGlkQXNzZXRNZXNzYWdlCQCsAgIJAKwCAgIPSW52YWxpZCBhc3NldC4gCQDYBAEFDXN0YWtlZEFzc2V0SWQCDCBpcyBleHBlY3RlZAQHYXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAUHcGF5bWVudAdhc3NldElkBRNpbnZhbGlkQXNzZXRNZXNzYWdlAwkBAiE9AgUHYXNzZXRJZAUNc3Rha2VkQXNzZXRJZAkAAgEFE2ludmFsaWRBc3NldE1lc3NhZ2UEDnVzZXJBZGRyZXNzU3RyCQClCAEFC3VzZXJBZGRyZXNzBAptZXJnZWREYXRhCQEKbWVyZ2VTdGFrZQIFC3VzZXJBZGRyZXNzBQZhbW91bnQECWlzTmV3VXNlcggFCm1lcmdlZERhdGECXzEEDHN0YWtlZEFtb3VudAgFCm1lcmdlZERhdGECXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUKbWVyZ2VkRGF0YQJfMwQPc3Rha2VkQW1vdW50TkVXCAUKbWVyZ2VkRGF0YQJfNAQUdnBFZmZlY3RpdmVIZWlnaHRORVcIBQptZXJnZWREYXRhAl81AwkAZgIFDW1pbkxvY2tBbW91bnQFD3N0YWtlZEFtb3VudE5FVwkAAgEJAKwCAgITTWluIGxvY2sgYW1vdW50IGlzIAkApAMBBQ1taW5Mb2NrQW1vdW50BA0kdDAxMzgxNjEzOTE4CQELU3RhdHNSZXN1bHQDBQZhbW91bnQAAQMFCWlzTmV3VXNlcgABAAAEDHN0YXRzRW50cmllcwgFDSR0MDEzODE2MTM5MTgCXzEEC3RvdGFsU3Rha2VkCAUNJHQwMTM4MTYxMzkxOAJfMgQOdG90YWxTdGFrZWROZXcIBQ0kdDAxMzgxNjEzOTE4Al8zCQDOCAIJAM4IAgkAzggCCQDMCAIJARJIaXN0b3J5UmVjb3JkRW50cnkHAgVzdGFrZQULdXNlckFkZHJlc3MIBQFpDXRyYW5zYWN0aW9uSWQFDHN0YWtlZEFtb3VudAURdnBFZmZlY3RpdmVIZWlnaHQFD3N0YWtlZEFtb3VudE5FVwUUdnBFZmZlY3RpdmVIZWlnaHRORVcFA25pbAkBDVJld2FyZEVudHJpZXMDBQlpc05ld1VzZXIFDnVzZXJBZGRyZXNzU3RyBQxzdGFrZWRBbW91bnQJAQ9Mb2NrUGFyYW1zRW50cnkDBQt1c2VyQWRkcmVzcwUPc3Rha2VkQW1vdW50TkVXBRR2cEVmZmVjdGl2ZUhlaWdodE5FVwUMc3RhdHNFbnRyaWVzAQtjb21tb25DbGFpbQILdXNlckFkZHJlc3MBaQQOdXNlckFkZHJlc3NTdHIJAKUIAQULdXNlckFkZHJlc3MDCQBmAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIZcGF5bWVudHMgYXJlIG5vdCBhY2NlcHRlZAQNJHQwMTQzOTcxNDUwMgkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDE0Mzk3MTQ1MDICXzEEDHN0YWtlZEFtb3VudAgFDSR0MDE0Mzk3MTQ1MDICXzIEDHN0YWtpbmdTdGFydAgFDSR0MDE0Mzk3MTQ1MDICXzMEDXN0YWtlZEFtb3VudFgJALYCAQUMc3Rha2VkQW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQ51c2VyQWRkcmVzc1N0cgQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgVhY2N1bQVhc3NldAQNJHQwMTQ4NzMxNTAxMQkBCmNhbGNSZXdhcmQFBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQ0kdDAxNDg3MzE1MDExAl8xBAZjYWNoZWQIBQ0kdDAxNDg3MzE1MDExAl8yBAdkeW5hbWljCAUNJHQwMTQ4NzMxNTAxMQJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFDSR0MDE0ODczMTUwMTECXzQECmNsYWltZWRLRVkJAQprZXlDbGFpbWVkAgUOdXNlckFkZHJlc3NTdHIFBWFzc2V0BA0kdDAxNTA3MTE1MTA4BQVhY2N1bQQEZGF0YQgFDSR0MDE1MDcxMTUxMDgCXzEEEWNsYWltZWRBbXRCeUFzc2V0CAUNJHQwMTUwNzExNTEwOAJfMgQHbmV3UGFydAkAuQkCCQDMCAIFBWFzc2V0CQDMCAIJAKQDAQULcmV3YXJkVG90YWwFA25pbAIBOgQUY2xhaW1lZEFtdEJ5QXNzZXROZXcJALkJAgkAzAgCBRFjbGFpbWVkQW10QnlBc3NldAkAzAgCBQduZXdQYXJ0BQNuaWwCAV8DCQBnAgAABQtyZXdhcmRUb3RhbAkAlAoCBQRkYXRhBRRjbGFpbWVkQW10QnlBc3NldE5ldwkAlAoCCQDNCAIJAM0IAgkAzQgCBQRkYXRhCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwULcmV3YXJkVG90YWwJAQt0b0Fzc2V0VmVjdAEFBWFzc2V0CQEMSW50ZWdlckVudHJ5AgUKY2xhaW1lZEtFWQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUKY2xhaW1lZEtFWQAABQtyZXdhcmRUb3RhbAkBDEludGVnZXJFbnRyeQIFE3Jld2FyZENhY2hlZFBhcnRLRVkAAAUUY2xhaW1lZEFtdEJ5QXNzZXROZXcEDSR0MDE1NTY4MTU2ODIKAAIkbAUTc3VwcG9ydGVkQXNzZXRzTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBH2ZvckVhY2hBc3NldENhbGNVbmNsYWltZWRSZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoECXRyYW5zZmVycwgFDSR0MDE1NTY4MTU2ODICXzEEF2NsYWltZWRBbXRCeUFzc2V0UmVzdWx0CAUNJHQwMTU1NjgxNTY4MgJfMgMJAGcCAAAJAJADAQUJdHJhbnNmZXJzBQNuaWwJAM0IAgkAzQgCBQl0cmFuc2ZlcnMJAQxJbnRlZ2VyRW50cnkCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkFDmRlcG9zaXROdW1MYXN0CQERQ2xhaW1IaXN0b3J5RW50cnkDBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAkAsAICBRdjbGFpbWVkQW10QnlBc3NldFJlc3VsdAABCgFpAQtjb25zdHJ1Y3RvcgMNbWluTG9ja0Ftb3VudBVzdXBwb3J0ZWRSZXdhcmRBc3NldHMNc3Rha2VkQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEVBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEQa2V5TWluTG9ja0Ftb3VudAAFDW1pbkxvY2tBbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGGtleVN1cHBvcnRlZFJld2FyZEFzc2V0cwAFFXN1cHBvcnRlZFJld2FyZEFzc2V0cwkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5U3Rha2VkQXNzZXRJZAAFDXN0YWtlZEFzc2V0SWQFA25pbAFpAQVzdGFrZQAJAQtjb21tb25TdGFrZQIIBQFpBmNhbGxlcgUBaQFpARNzdGFrZUJ5T3JpZ2luQ2FsbGVyAAkBC2NvbW1vblN0YWtlAggFAWkMb3JpZ2luQ2FsbGVyBQFpAWkBB3Vuc3Rha2UBBmFtb3VudAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECI3Vuc3Rha2UgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50BAt1c2VyQWRkcmVzcwgFAWkGY2FsbGVyBA51c2VyQWRkcmVzc1N0cgkApQgBBQt1c2VyQWRkcmVzcwQNJHQwMTY1OTExNjY0NQkBD2dldFBhcmFtc09yRmFpbAAEDXN0YWtlZEFzc2V0SWQIBQ0kdDAxNjU5MTE2NjQ1Al8xBA1taW5Mb2NrQW1vdW50CAUNJHQwMTY1OTExNjY0NQJfMgQNJHQwMTY2NDgxNjcyMgkBE2dldFVzZXJQYXJhbXNPckZhaWwBBQt1c2VyQWRkcmVzcwQJaXNOZXdVc2VyCAUNJHQwMTY2NDgxNjcyMgJfMQQKbG9ja0Ftb3VudAgFDSR0MDE2NjQ4MTY3MjICXzIECWxvY2tTdGFydAgFDSR0MDE2NjQ4MTY3MjICXzMDCQBnAgAABQpsb2NrQW1vdW50CQACAQISTm90aGluZyB0byB1bnN0YWtlAwkAZgIFBmFtb3VudAUKbG9ja0Ftb3VudAkAAgEJAKwCAgkArAICCQCsAgICClJlcXVlc3RlZCAJAKQDAQUGYW1vdW50AhIsIGJ1dCBzdGFrZWQgb25seSAJAKQDAQUKbG9ja0Ftb3VudAQNJHQwMTY5MTIxNzA2NgkBC1N0YXRzUmVzdWx0AwkBAS0BBQZhbW91bnQDCQAAAgUGYW1vdW50BQpsb2NrQW1vdW50AP///////////wEAAAMJAAACBQZhbW91bnQFCmxvY2tBbW91bnQA////////////AQAABAxzdGF0c0VudHJpZXMIBQ0kdDAxNjkxMjE3MDY2Al8xBAt0b3RhbFN0YWtlZAgFDSR0MDE2OTEyMTcwNjYCXzIEDnRvdGFsU3Rha2VkTmV3CAUNJHQwMTY5MTIxNzA2NgJfMwkAzggCCQDOCAIJAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQt1c2VyQWRkcmVzcwUGYW1vdW50BQ1zdGFrZWRBc3NldElkCQDMCAIJARJIaXN0b3J5UmVjb3JkRW50cnkHAgd1bnN0YWtlBQt1c2VyQWRkcmVzcwgFAWkNdHJhbnNhY3Rpb25JZAUKbG9ja0Ftb3VudAUJbG9ja1N0YXJ0CQBlAgUKbG9ja0Ftb3VudAUGYW1vdW50BQlsb2NrU3RhcnQFA25pbAkBDVJld2FyZEVudHJpZXMDBwUOdXNlckFkZHJlc3NTdHIFCmxvY2tBbW91bnQJAQ9Mb2NrUGFyYW1zRW50cnkDBQt1c2VyQWRkcmVzcwkAZQIFCmxvY2tBbW91bnQFBmFtb3VudAUJbG9ja1N0YXJ0BQxzdGF0c0VudHJpZXMBaQEHZGVwb3NpdAADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAh9leGFjdCAxIHBheW1lbnQgaXMgYWxsb3dlZCBvbmx5BANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQGYW1vdW50CAUDcG10BmFtb3VudAQKcG10QXNzZXRJZAkBC3ZhbHVlT3JFbHNlAggFA3BtdAdhc3NldElkBQdXQVZFU0lEBA1wbXRBc3NldElkU3RyCQDYBAEFCnBtdEFzc2V0SWQECHBtdE11bHRYAwkAAAIFCnBtdEFzc2V0SWQFB1dBVkVTSUQFBk1VTFRYOAUGTVVMVFg2BAdhbW91bnRYCQC2AgEFBmFtb3VudAQLdG90YWxTdGFrZWQJAQxnZXRJbnRPckVsc2UCCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAAAEDHRvdGFsU3Rha2VkWAkAtgIBBQt0b3RhbFN0YWtlZAMJAGYCAAAFC3RvdGFsU3Rha2VkCQACAQIbVE9ETzogY2FzZSBpcyBub3Qgc3VwcG9ydGVkAwkAAAIFC3RvdGFsU3Rha2VkAAAJASJJbmNyZW1lbnROb3REaXN0cmlidXRlZFJld2FyZEVudHJ5AgUNcG10QXNzZXRJZFN0cgUGYW1vdW50BBByZXdhcmRQZXJOc2J0WDE4CQC8AgMFB2Ftb3VudFgFB01VTFRYMTgFDHRvdGFsU3Rha2VkWAQRZGVwb3NpdE51bUxhc3RLRVkJARFrZXlEZXBvc2l0TnVtTGFzdAAEDmRlcG9zaXROdW1MYXN0CQEMZ2V0SW50T3JFbHNlAgURZGVwb3NpdE51bUxhc3RLRVkA////////////AQQNZGVwb3NpdE51bU5ldwkAZAIFDmRlcG9zaXROdW1MYXN0AAEDCQEBIQEJAQhjb250YWlucwIFEnN1cHBvcnRlZEFzc2V0c1N0cgUNcG10QXNzZXRJZFN0cgkAAgEJAKwCAgkArAICBRJzdXBwb3J0ZWRBc3NldHNTdHICESBkb2Vzbid0IGNvbnRhaW4gBQ1wbXRBc3NldElkU3RyCgEXcmVmcmVzaFJld2FyZFBlck5zYnRTVU0CBWFjY3VtCW5leHRBc3NldAQWcmV3YXJkUGVyTnNidFN1bU5ld0tFWQkBFWtleVJld2FyZFBlck5zYnRTdW1BdAIFDWRlcG9zaXROdW1OZXcFCW5leHRBc3NldAQKc3VtTGFzdFN0cgkBDGdldFN0ck9yRWxzZQIJARVrZXlSZXdhcmRQZXJOc2J0U3VtQXQCBQ5kZXBvc2l0TnVtTGFzdAUJbmV4dEFzc2V0AgEwCQDNCAIFBWFjY3VtAwkAAAIFCW5leHRBc3NldAUNcG10QXNzZXRJZFN0cgkBC1N0cmluZ0VudHJ5AgUWcmV3YXJkUGVyTnNidFN1bU5ld0tFWQkApgMBCQC3AgIJAKcDAQUKc3VtTGFzdFN0cgUQcmV3YXJkUGVyTnNidFgxOAkBC1N0cmluZ0VudHJ5AgUWcmV3YXJkUGVyTnNidFN1bU5ld0tFWQUKc3VtTGFzdFN0cgkAzQgCCgACJGwFE3N1cHBvcnRlZEFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBF3JlZnJlc2hSZXdhcmRQZXJOc2J0U1VNAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQEMSW50ZWdlckVudHJ5AgURZGVwb3NpdE51bUxhc3RLRVkFDWRlcG9zaXROdW1OZXcBaQEMY2xhaW1SZXdhcmRzAAkBC2NvbW1vbkNsYWltAggFAWkGY2FsbGVyBQFpAWkBGmNsYWltUmV3YXJkc0J5T3JpZ2luQ2FsbGVyAAkBC2NvbW1vbkNsYWltAggFAWkMb3JpZ2luQ2FsbGVyBQFpAWkBGHVuY2xhaW1lZFJld2FyZHNSRUFET05MWQEOdXNlckFkZHJlc3NTdHIKARZmb3JFYWNoQXNzZXRaZXJvUmV3YXJkAgVhY2N1bQVhc3NldAkArAICCQCsAgIFBWFjY3VtCQC5CQIJAMwIAgUFYXNzZXQJAMwIAgIBMAkAzAgCAgEwBQNuaWwCAToCAV8EEnVuY2xhaW1lZFJld2FyZFN0cgMJAAACBQ51c2VyQWRkcmVzc1N0cgIACgACJGwFE3N1cHBvcnRlZEFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBFmZvckVhY2hBc3NldFplcm9SZXdhcmQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEC3VzZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQ51c2VyQWRkcmVzc1N0cgQNJHQwMTk2MjAxOTcyNQkBC3ZhbHVlT3JFbHNlAgkBE2dldFVzZXJQYXJhbXNPclVuaXQBBQt1c2VyQWRkcmVzcwkAlQoDBgAAAAAECWlzTmV3VXNlcggFDSR0MDE5NjIwMTk3MjUCXzEEDHN0YWtlZEFtb3VudAgFDSR0MDE5NjIwMTk3MjUCXzIEDHN0YWtpbmdTdGFydAgFDSR0MDE5NjIwMTk3MjUCXzMEDXN0YWtlZEFtb3VudFgJALYCAQUMc3Rha2VkQW1vdW50BBt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJARtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0BBQ51c2VyQWRkcmVzc1N0cgQOZGVwb3NpdE51bVVzZXIJAQxnZXRJbnRPckVsc2UCBRt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA////////////AQQOZGVwb3NpdE51bUxhc3QJAQxnZXRJbnRPckVsc2UCCQERa2V5RGVwb3NpdE51bUxhc3QAAP///////////wEKAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgVhY2N1bQVhc3NldAQNJHQwMjAwNzEyMDIwOQkBCmNhbGNSZXdhcmQFBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQFDXN0YWtlZEFtb3VudFgFDmRlcG9zaXROdW1Vc2VyBQ5kZXBvc2l0TnVtTGFzdAQLcmV3YXJkVG90YWwIBQ0kdDAyMDA3MTIwMjA5Al8xBAZjYWNoZWQIBQ0kdDAyMDA3MTIwMjA5Al8yBAdkeW5hbWljCAUNJHQwMjAwNzEyMDIwOQJfMwQTcmV3YXJkQ2FjaGVkUGFydEtFWQgFDSR0MDIwMDcxMjAyMDkCXzQEB2NsYWltZWQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBCmtleUNsYWltZWQCBQ51c2VyQWRkcmVzc1N0cgUFYXNzZXQAAAkArAICCQCsAgIFBWFjY3VtCQC5CQIJAMwIAgUFYXNzZXQJAMwIAgkApAMBBQtyZXdhcmRUb3RhbAkAzAgCCQCkAwEFB2NsYWltZWQFA25pbAIBOgIBXwoAAiRsBRNzdXBwb3J0ZWRBc3NldHNMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAR9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQCUCgIFA25pbAkAswICBRJ1bmNsYWltZWRSZXdhcmRTdHIAAQFpARZzdXJmU3Rha2luZ1NZU1JFQURPTkxZAhV1c2VyQWRkcmVzc1N0ck9yRW1wdHkIc3VyZkRpZmYECXN1cmZUb3RhbAkBDGdldEludE9yRWxzZQIJARdrZXlMb2NrUGFyYW1Ub3RhbEFtb3VudAAAAAQSZ25zYnRGcm9tU3VyZlRvdGFsCQELc3VyZlRvR25zYnQBBQlzdXJmVG90YWwDCQAAAgUVdXNlckFkZHJlc3NTdHJPckVtcHR5AgAJAJQKAgUDbmlsCQDMCAIAAAkAzAgCBQlzdXJmVG90YWwJAMwIAgAACQDMCAIFEmduc2J0RnJvbVN1cmZUb3RhbAkAzAgCAAAJAMwIAgUGaGVpZ2h0CQDMCAIFBmhlaWdodAUDbmlsBAt1c2VyQWRkcmVzcwkBD3RvQWRkcmVzc09yRmFpbAEFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQQKbWVyZ2VkRGF0YQkBCm1lcmdlU3Rha2UCBQt1c2VyQWRkcmVzcwUIc3VyZkRpZmYECWlzTmV3VXNlcggFCm1lcmdlZERhdGECXzEEDHN0YWtlZEFtb3VudAgFCm1lcmdlZERhdGECXzIEEXZwRWZmZWN0aXZlSGVpZ2h0CAUKbWVyZ2VkRGF0YQJfMwQPc3Rha2VkQW1vdW50TkVXCAUKbWVyZ2VkRGF0YQJfNAQUdnBFZmZlY3RpdmVIZWlnaHRORVcIBQptZXJnZWREYXRhAl81BAhzdXJmVXNlcgUMc3Rha2VkQW1vdW50BBFnbnNidEZyb21TdXJmVXNlcgkBC3N1cmZUb0duc2J0AQUIc3VyZlVzZXIJAJQKAgUDbmlsCQDMCAIFCHN1cmZVc2VyCQDMCAIFCXN1cmZUb3RhbAkAzAgCBRFnbnNidEZyb21TdXJmVXNlcgkAzAgCBRJnbnNidEZyb21TdXJmVG90YWwJAMwIAgURdnBFZmZlY3RpdmVIZWlnaHQJAMwIAgUUdnBFZmZlY3RpdmVIZWlnaHRORVcFA25pbAFpARFjb25maWdTWVNSRUFET05MWQAECm1pbkxvY2tBbXQJARFAZXh0ck5hdGl2ZSgxMDU1KQEJARBrZXlNaW5Mb2NrQW1vdW50AAQSZ25zYnRGcm9tU3VyZkNvZWZmCQBoAgA8BQVNVUxUNgQgc3VyZlZvdGluZ1Bvd2VyUmVzdHJpY3RpdmVQZXJpb2QJAGgCAKALAA4EG2JyVG9TdGFydFN1cmZUcmFuc2Zvcm1hdGlvbgCwmEYJAJQKAgUDbmlsCQDMCAIFCm1pbkxvY2tBbXQJAMwIAgUSZ25zYnRGcm9tU3VyZkNvZWZmCQDMCAIFIHN1cmZWb3RpbmdQb3dlclJlc3RyaWN0aXZlUGVyaW9kCQDMCAIFG2JyVG9TdGFydFN1cmZUcmFuc2Zvcm1hdGlvbgUDbmlsAKfFJNE=", "chainId": 84, "height": 2170645, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: FFYCwJFGmeUJNTzFug8KKXGm2fuXWAmtVZZd3Bzvx6fs Next: ATGScZ2BnkhhsgpdgkAYoeFEXYbXSJHxdc4eZnYCaAtS Diff:
OldNewDifferences
8282
8383
8484 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
85+
86+
87+func keyLockParamVotingPowerEffectiveHeight (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "vpEffectiveHeight"], separator)
8588
8689
8790 func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
172175 }
173176
174177
175-func LockParamsEntry (userAddress,amount,start) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
178+func LockParamsEntry (userAddress,amount,votingPowerEffectiveHeight) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), votingPowerEffectiveHeight)]
176179
177180
178181 func getParamsOrFail () = $Tuple2(fromBase58String(getStringOrFail(this, keyStakedAssetId())), getIntOrFail(keyMinLockAmount()))
210213 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
211214 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
212215 func forEachAssetCacheUserReward (accum,asset) = {
213- let $t084368571 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
214- let rewardTotal = $t084368571._1
215- let cached = $t084368571._2
216- let dynamic = $t084368571._3
217- let rewardCachedPartKEY = $t084368571._4
216+ let $t086398774 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
217+ let rewardTotal = $t086398774._1
218+ let cached = $t086398774._2
219+ let dynamic = $t086398774._3
220+ let rewardCachedPartKEY = $t086398774._4
218221 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
219222 }
220223
259262 func surfToGnsbt (surfAmt) = (surfAmt / 60)
260263
261264
265+func mergeVotingPowerEffectiveHeight (quarantinePeriod,vpEffectiveHeight,stakedAmt,stakedAmtNEW) = {
266+ let remainingToWait = (vpEffectiveHeight - height)
267+ if ((0 >= remainingToWait))
268+ then (height + quarantinePeriod)
269+ else {
270+ let alreadyWaited = (quarantinePeriod - remainingToWait)
271+ let kX8 = fraction(stakedAmt, MULT8, stakedAmtNEW)
272+ ((quarantinePeriod + height) - fraction(alreadyWaited, kX8, MULT8))
273+ }
274+ }
275+
276+
277+func mergeStake (userAddress,amountToAdd) = {
278+ let $t01236712477 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
279+ let isNewUser = $t01236712477._1
280+ let stakedAmount = $t01236712477._2
281+ let vpEffectiveHeight = $t01236712477._3
282+ let stakedAmountNEW = if (isNewUser)
283+ then amountToAdd
284+ else (amountToAdd + stakedAmount)
285+ let quarantinePeriod = (1440 * 14)
286+ let vpEffectiveHeightNEW = if (isNewUser)
287+ then (quarantinePeriod + height)
288+ else mergeVotingPowerEffectiveHeight(quarantinePeriod, vpEffectiveHeight, stakedAmount, stakedAmountNEW)
289+ $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)
290+ }
291+
292+
262293 func commonStake (userAddress,i) = {
263- let $t01145511509 = getParamsOrFail()
264- let stakedAssetId = $t01145511509._1
265- let minLockAmount = $t01145511509._2
294+ let $t01296313017 = getParamsOrFail()
295+ let stakedAssetId = $t01296313017._1
296+ let minLockAmount = $t01296313017._2
266297 if ((size(i.payments) != 1))
267298 then throw("Invalid payments size")
268299 else {
274305 then throw(invalidAssetMessage)
275306 else {
276307 let userAddressStr = toString(userAddress)
277- let gnsbtAmtUser = 0
278- let gnsbtAmtTotal = 0
279- let $t01197812087 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
280- let isNewUser = $t01197812087._1
281- let stakedAmount = $t01197812087._2
282- let lockStartHeight = $t01197812087._3
283- let stakedAmountNew = if (isNewUser)
284- then amount
285- else (amount + stakedAmount)
286- let mergedStartHeight = if (isNewUser)
287- then height
288- else (height + (1440 * 14))
289- if ((minLockAmount > stakedAmountNew))
308+ let mergedData = mergeStake(userAddress, amount)
309+ let isNewUser = mergedData._1
310+ let stakedAmount = mergedData._2
311+ let vpEffectiveHeight = mergedData._3
312+ let stakedAmountNEW = mergedData._4
313+ let vpEffectiveHeightNEW = mergedData._5
314+ if ((minLockAmount > stakedAmountNEW))
290315 then throw(("Min lock amount is " + toString(minLockAmount)))
291316 else {
292- let $t01239012492 = StatsResult(amount, 1, if (isNewUser)
317+ let $t01381613918 = StatsResult(amount, 1, if (isNewUser)
293318 then 1
294319 else 0)
295- let statsEntries = $t01239012492._1
296- let totalStaked = $t01239012492._2
297- let totalStakedNew = $t01239012492._3
298- ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, lockStartHeight, stakedAmountNew, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNew, mergedStartHeight)) ++ statsEntries)
320+ let statsEntries = $t01381613918._1
321+ let totalStaked = $t01381613918._2
322+ let totalStakedNew = $t01381613918._3
323+ ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries)
299324 }
300325 }
301326 }
307332 if ((size(i.payments) > 0))
308333 then throw("payments are not accepted")
309334 else {
310- let $t01296313068 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
311- let isNewUser = $t01296313068._1
312- let stakedAmount = $t01296313068._2
313- let stakingStart = $t01296313068._3
335+ let $t01439714502 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
336+ let isNewUser = $t01439714502._1
337+ let stakedAmount = $t01439714502._2
338+ let stakingStart = $t01439714502._3
314339 let stakedAmountX = toBigInt(stakedAmount)
315340 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
316341 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
317342 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
318343 func forEachAssetCalcUnclaimedReward (accum,asset) = {
319- let $t01343913577 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
320- let rewardTotal = $t01343913577._1
321- let cached = $t01343913577._2
322- let dynamic = $t01343913577._3
323- let rewardCachedPartKEY = $t01343913577._4
344+ let $t01487315011 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
345+ let rewardTotal = $t01487315011._1
346+ let cached = $t01487315011._2
347+ let dynamic = $t01487315011._3
348+ let rewardCachedPartKEY = $t01487315011._4
324349 let claimedKEY = keyClaimed(userAddressStr, asset)
325- let $t01363713674 = accum
326- let data = $t01363713674._1
327- let claimedAmtByAsset = $t01363713674._2
350+ let $t01507115108 = accum
351+ let data = $t01507115108._1
352+ let claimedAmtByAsset = $t01507115108._2
328353 let newPart = makeString([asset, toString(rewardTotal)], ":")
329354 let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
330355 if ((0 >= rewardTotal))
332357 else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
333358 }
334359
335- let $t01413414248 = {
360+ let $t01556815682 = {
336361 let $l = supportedAssetsList
337362 let $s = size($l)
338363 let $acc0 = $Tuple2(nil, "")
346371
347372 $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)
348373 }
349- let transfers = $t01413414248._1
350- let claimedAmtByAssetResult = $t01413414248._2
374+ let transfers = $t01556815682._1
375+ let claimedAmtByAssetResult = $t01556815682._2
351376 if ((0 >= size(transfers)))
352377 then nil
353378 else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
378403 else {
379404 let userAddress = i.caller
380405 let userAddressStr = toString(userAddress)
381- let $t01515715211 = getParamsOrFail()
382- let stakedAssetId = $t01515715211._1
383- let minLockAmount = $t01515715211._2
384- let $t01521415288 = getUserParamsOrFail(userAddress)
385- let isNewUser = $t01521415288._1
386- let lockAmount = $t01521415288._2
387- let lockStart = $t01521415288._3
406+ let $t01659116645 = getParamsOrFail()
407+ let stakedAssetId = $t01659116645._1
408+ let minLockAmount = $t01659116645._2
409+ let $t01664816722 = getUserParamsOrFail(userAddress)
410+ let isNewUser = $t01664816722._1
411+ let lockAmount = $t01664816722._2
412+ let lockStart = $t01664816722._3
388413 if ((0 >= lockAmount))
389414 then throw("Nothing to unstake")
390415 else if ((amount > lockAmount))
391416 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(lockAmount)))
392417 else {
393- let $t01547815632 = StatsResult(-(amount), if ((amount == lockAmount))
418+ let $t01691217066 = StatsResult(-(amount), if ((amount == lockAmount))
394419 then -1
395420 else 0, if ((amount == lockAmount))
396421 then -1
397422 else 0)
398- let statsEntries = $t01547815632._1
399- let totalStaked = $t01547815632._2
400- let totalStakedNew = $t01547815632._3
423+ let statsEntries = $t01691217066._1
424+ let totalStaked = $t01691217066._2
425+ let totalStakedNew = $t01691217066._3
401426 ((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
402427 }
403428 }
489514 }
490515 else {
491516 let userAddress = addressFromStringValue(userAddressStr)
492- let $t01818618291 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
493- let isNewUser = $t01818618291._1
494- let stakedAmount = $t01818618291._2
495- let stakingStart = $t01818618291._3
517+ let $t01962019725 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
518+ let isNewUser = $t01962019725._1
519+ let stakedAmount = $t01962019725._2
520+ let stakingStart = $t01962019725._3
496521 let stakedAmountX = toBigInt(stakedAmount)
497522 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
498523 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
499524 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
500525 func forEachAssetCalcUnclaimedReward (accum,asset) = {
501- let $t01863718775 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
502- let rewardTotal = $t01863718775._1
503- let cached = $t01863718775._2
504- let dynamic = $t01863718775._3
505- let rewardCachedPartKEY = $t01863718775._4
526+ let $t02007120209 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
527+ let rewardTotal = $t02007120209._1
528+ let cached = $t02007120209._2
529+ let dynamic = $t02007120209._3
530+ let rewardCachedPartKEY = $t02007120209._4
506531 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
507532 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
508533 }
526551
527552
528553 @Callable(i)
529-func surfStakingSYSREADONLY (userAddressStrOrEmpty) = {
554+func surfStakingSYSREADONLY (userAddressStrOrEmpty,surfDiff) = {
530555 let surfTotal = getIntOrElse(keyLockParamTotalAmount(), 0)
531556 let gnsbtFromSurfTotal = surfToGnsbt(surfTotal)
532557 if ((userAddressStrOrEmpty == ""))
533- then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, 0])
558+ then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, 0, height, height])
534559 else {
535560 let userAddress = toAddressOrFail(userAddressStrOrEmpty)
536- let $t01946719568 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
537- let isNewUser = $t01946719568._1
538- let surfUser = $t01946719568._2
539- let stakingStart = $t01946719568._3
561+ let mergedData = mergeStake(userAddress, surfDiff)
562+ let isNewUser = mergedData._1
563+ let stakedAmount = mergedData._2
564+ let vpEffectiveHeight = mergedData._3
565+ let stakedAmountNEW = mergedData._4
566+ let vpEffectiveHeightNEW = mergedData._5
567+ let surfUser = stakedAmount
540568 let gnsbtFromSurfUser = surfToGnsbt(surfUser)
541- $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, stakingStart])
569+ $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, vpEffectiveHeight, vpEffectiveHeightNEW])
542570 }
543571 }
544572
549577 let minLockAmt = getIntegerValue(keyMinLockAmount())
550578 let gnsbtFromSurfCoeff = (60 * MULT6)
551579 let surfVotingPowerRestrictivePeriod = (1440 * 14)
552- let brToStartSurfTransformation = 1200000
580+ let brToStartSurfTransformation = 1150000
553581 $Tuple2(nil, [minLockAmt, gnsbtFromSurfCoeff, surfVotingPowerRestrictivePeriod, brToStartSurfTransformation])
554582 }
555583
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 IdxControlCfgNeutrinoDapp = 1
2323
2424 let IdxControlCfgAuctionDapp = 2
2525
2626 let IdxControlCfgRpdDapp = 3
2727
2828 let IdxControlCfgMathDapp = 4
2929
3030 let IdxControlCfgLiquidationDapp = 5
3131
3232 let IdxControlCfgRestDapp = 6
3333
3434 let IdxControlCfgNodeRegistryDapp = 7
3535
3636 let IdxControlCfgNsbtStakingDapp = 8
3737
3838 let IdxControlCfgMediatorDapp = 9
3939
4040 let IdxControlCfgSurfStakingDapp = 10
4141
4242 let IdxControlCfgGnsbtControllerDapp = 11
4343
4444 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
4545
4646
4747 func keyControlAddress () = "%s%s__config__controlAddress"
4848
4949
5050 func keyControlCfg () = "%s__controlConfig"
5151
5252
5353 func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
5454
5555
5656 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
5757
5858
5959 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3N4NS7d4Jo9a6F14LiFUKKYVdUkkf2eP4Zx"))
6060
6161 let controlCfg = readControlCfgOrFail(controlContract)
6262
6363 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
6464
6565 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
6666
6767 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
6868
6969 func keyBondAsset () = "bond_asset_id"
7070
7171
7272 func keyAuctionContractAddress () = "auction_contract"
7373
7474
7575 func keyMinLockAmount () = "%s__minLockAmount"
7676
7777
7878 func keyStakedAssetId () = "%s__stakedAssetId"
7979
8080
8181 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "amount"], separator)
8282
8383
8484 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
85+
86+
87+func keyLockParamVotingPowerEffectiveHeight (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "vpEffectiveHeight"], separator)
8588
8689
8790 func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
8891
8992
9093 func keyLockParamTotalAmount () = makeString(["%s%s", "stats", "activeTotalLocked"], separator)
9194
9295
9396 func keyStatsLocksCount () = makeString(["%s%s", "stats", "locksCount"], separator)
9497
9598
9699 func keyStatsUsersCount () = makeString(["%s%s", "stats", "activeUsersCount"], separator)
97100
98101
99102 func keyNextPeriod () = "%s__nextPeriod"
100103
101104
102105 func keySupportedRewardAssets () = "supportedRewardAssets"
103106
104107
105108 func keyDepositNumLast () = makeString(["%s%s%s", "dep", "lastNum"], separator)
106109
107110
108111 func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s%s", "userRwdFromDepNum", userAddress], separator)
109112
110113
111114 func keyRewardPerNsbtSumAt (depositNum,tkn) = makeString(["%s%d", "rwdPerNsbtSumByDepNum", toString(depositNum), tkn], separator)
112115
113116
114117 func keyReward (userAddress,tkn) = makeString(["%s%s%s", "rwd", userAddress, tkn], separator)
115118
116119
117120 func keyClaimed (userAddress,tkn) = makeString(["%s%s%s", "clm", userAddress, tkn], separator)
118121
119122
120123 func keyNotDistributedReward (tkn) = makeString(["%s%s", "notDistributed", tkn], separator)
121124
122125
123126 func toX18 (origVal,origMult) = fraction(toBigInt(origVal), MULTX18, origMult)
124127
125128
126129 func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
127130
128131
129132 func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
130133
131134
132135 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
133136
134137
135138 func getStrOrElse (key,defaultVal) = valueOrElse(getString(this, key), defaultVal)
136139
137140
138141 func toAddressOrFail (addressStr) = valueOrErrorMessage(addressFromString(addressStr), ("couldn't parse passed addressStr=" + addressStr))
139142
140143
141144 func toAssetVect (assetStr) = if ((assetStr == WAVESIDSTR))
142145 then unit
143146 else fromBase58String(assetStr)
144147
145148
146149 func asInt (val) = match val {
147150 case valInt: Int =>
148151 valInt
149152 case _ =>
150153 throw("fail to cast into Int")
151154 }
152155
153156
154157 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)
155158
156159
157160 func formatClaimHistoryRecord (user,claimedRewards) = makeString(["%s%d%d%s", user, toString(lastBlock.height), toString(lastBlock.timestamp), claimedRewards], separator)
158161
159162
160163 func HistoryRecordEntry (type,userAddress,txId,oldAmount,oldStart,newAmount,newStart) = StringEntry(keyHistoryRecord(type, userAddress, txId), formatHistoryRecord(oldAmount, oldStart, newAmount, newStart))
161164
162165
163166 func ClaimHistoryEntry (userAddress,txId,claimedRewards) = StringEntry(keyHistoryRecord("claim", userAddress, txId), formatClaimHistoryRecord(toString(userAddress), claimedRewards))
164167
165168
166169 func StatsResult (totalLockedInc,lockCountInc,usersCountInc) = {
167170 let locksCount = getIntOrZero(keyStatsLocksCount())
168171 let usersCount = getIntOrZero(keyStatsUsersCount())
169172 let totalAmount = getIntOrZero(keyLockParamTotalAmount())
170173 let totalAmountNew = (totalAmount + totalLockedInc)
171174 $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew)], totalAmount, totalAmountNew)
172175 }
173176
174177
175-func LockParamsEntry (userAddress,amount,start) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
178+func LockParamsEntry (userAddress,amount,votingPowerEffectiveHeight) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), votingPowerEffectiveHeight)]
176179
177180
178181 func getParamsOrFail () = $Tuple2(fromBase58String(getStringOrFail(this, keyStakedAssetId())), getIntOrFail(keyMinLockAmount()))
179182
180183
181184 func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
182185
183186
184187 func getUserParamsOrUnit (userAddress) = if (isActiveUser(userAddress))
185188 then $Tuple3(false, getIntOrFail(keyLockParamUserAmount(userAddress)), getIntOrFail(keyLockParamStartBlock(userAddress)))
186189 else unit
187190
188191
189192 func getUserParamsOrFail (userAddress) = valueOrErrorMessage(getUserParamsOrUnit(userAddress), (("User " + toString(userAddress)) + " is not defined"))
190193
191194
192195 let supportedAssetsStr = getStrOrElse(keySupportedRewardAssets(), "")
193196
194197 let supportedAssetsList = split(supportedAssetsStr, "_")
195198
196199 func calcReward (userAddress,assetId,stakedAmountX,depositNumUser,depositNumLast) = {
197200 let rewardPerNsbtSumLastKEY = keyRewardPerNsbtSumAt(depositNumLast, assetId)
198201 let sumLastX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, assetId), "0"))
199202 let sumUserX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumUser, assetId), "0"))
200203 let rewardDynamicPart = toInt(fraction((sumLastX18 - sumUserX18), stakedAmountX, MULTX18))
201204 let rewardCachedPartKEY = keyReward(userAddress, assetId)
202205 let rewardCachedPart = getIntOrElse(rewardCachedPartKEY, 0)
203206 $Tuple4((rewardCachedPart + rewardDynamicPart), rewardCachedPart, rewardDynamicPart, rewardCachedPartKEY)
204207 }
205208
206209
207210 func RewardEntries (isNewUser,userAddress,stakedAmount) = {
208211 let stakedAmountX = toBigInt(stakedAmount)
209212 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddress)
210213 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
211214 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
212215 func forEachAssetCacheUserReward (accum,asset) = {
213- let $t084368571 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
214- let rewardTotal = $t084368571._1
215- let cached = $t084368571._2
216- let dynamic = $t084368571._3
217- let rewardCachedPartKEY = $t084368571._4
216+ let $t086398774 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
217+ let rewardTotal = $t086398774._1
218+ let cached = $t086398774._2
219+ let dynamic = $t086398774._3
220+ let rewardCachedPartKEY = $t086398774._4
218221 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
219222 }
220223
221224 if (if ((depositNumLast == -1))
222225 then (depositNumUser == -1)
223226 else false)
224227 then nil
225228 else if (if ((depositNumLast == -1))
226229 then (depositNumUser > -1)
227230 else false)
228231 then throw("invalid depositNumLast and depositNumUser state")
229232 else if (if ((depositNumLast > -1))
230233 then (depositNumUser >= -1)
231234 else false)
232235 then if (isNewUser)
233236 then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
234237 else ({
235238 let $l = supportedAssetsList
236239 let $s = size($l)
237240 let $acc0 = nil
238241 func $f0_1 ($a,$i) = if (($i >= $s))
239242 then $a
240243 else forEachAssetCacheUserReward($a, $l[$i])
241244
242245 func $f0_2 ($a,$i) = if (($i >= $s))
243246 then $a
244247 else throw("List size exceeds 10")
245248
246249 $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)
247250 } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
248251 else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
249252 }
250253
251254
252255 func IncrementNotDistributedRewardEntry (tkn,amountInc) = {
253256 let notDistributedRewardKEY = keyNotDistributedReward(tkn)
254257 let notDistributedReward = getIntOrElse(notDistributedRewardKEY, 0)
255258 [IntegerEntry(notDistributedRewardKEY, (notDistributedReward + amountInc))]
256259 }
257260
258261
259262 func surfToGnsbt (surfAmt) = (surfAmt / 60)
260263
261264
265+func mergeVotingPowerEffectiveHeight (quarantinePeriod,vpEffectiveHeight,stakedAmt,stakedAmtNEW) = {
266+ let remainingToWait = (vpEffectiveHeight - height)
267+ if ((0 >= remainingToWait))
268+ then (height + quarantinePeriod)
269+ else {
270+ let alreadyWaited = (quarantinePeriod - remainingToWait)
271+ let kX8 = fraction(stakedAmt, MULT8, stakedAmtNEW)
272+ ((quarantinePeriod + height) - fraction(alreadyWaited, kX8, MULT8))
273+ }
274+ }
275+
276+
277+func mergeStake (userAddress,amountToAdd) = {
278+ let $t01236712477 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
279+ let isNewUser = $t01236712477._1
280+ let stakedAmount = $t01236712477._2
281+ let vpEffectiveHeight = $t01236712477._3
282+ let stakedAmountNEW = if (isNewUser)
283+ then amountToAdd
284+ else (amountToAdd + stakedAmount)
285+ let quarantinePeriod = (1440 * 14)
286+ let vpEffectiveHeightNEW = if (isNewUser)
287+ then (quarantinePeriod + height)
288+ else mergeVotingPowerEffectiveHeight(quarantinePeriod, vpEffectiveHeight, stakedAmount, stakedAmountNEW)
289+ $Tuple5(isNewUser, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)
290+ }
291+
292+
262293 func commonStake (userAddress,i) = {
263- let $t01145511509 = getParamsOrFail()
264- let stakedAssetId = $t01145511509._1
265- let minLockAmount = $t01145511509._2
294+ let $t01296313017 = getParamsOrFail()
295+ let stakedAssetId = $t01296313017._1
296+ let minLockAmount = $t01296313017._2
266297 if ((size(i.payments) != 1))
267298 then throw("Invalid payments size")
268299 else {
269300 let payment = i.payments[0]
270301 let amount = payment.amount
271302 let invalidAssetMessage = (("Invalid asset. " + toBase58String(stakedAssetId)) + " is expected")
272303 let assetId = valueOrErrorMessage(payment.assetId, invalidAssetMessage)
273304 if ((assetId != stakedAssetId))
274305 then throw(invalidAssetMessage)
275306 else {
276307 let userAddressStr = toString(userAddress)
277- let gnsbtAmtUser = 0
278- let gnsbtAmtTotal = 0
279- let $t01197812087 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
280- let isNewUser = $t01197812087._1
281- let stakedAmount = $t01197812087._2
282- let lockStartHeight = $t01197812087._3
283- let stakedAmountNew = if (isNewUser)
284- then amount
285- else (amount + stakedAmount)
286- let mergedStartHeight = if (isNewUser)
287- then height
288- else (height + (1440 * 14))
289- if ((minLockAmount > stakedAmountNew))
308+ let mergedData = mergeStake(userAddress, amount)
309+ let isNewUser = mergedData._1
310+ let stakedAmount = mergedData._2
311+ let vpEffectiveHeight = mergedData._3
312+ let stakedAmountNEW = mergedData._4
313+ let vpEffectiveHeightNEW = mergedData._5
314+ if ((minLockAmount > stakedAmountNEW))
290315 then throw(("Min lock amount is " + toString(minLockAmount)))
291316 else {
292- let $t01239012492 = StatsResult(amount, 1, if (isNewUser)
317+ let $t01381613918 = StatsResult(amount, 1, if (isNewUser)
293318 then 1
294319 else 0)
295- let statsEntries = $t01239012492._1
296- let totalStaked = $t01239012492._2
297- let totalStakedNew = $t01239012492._3
298- ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, lockStartHeight, stakedAmountNew, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNew, mergedStartHeight)) ++ statsEntries)
320+ let statsEntries = $t01381613918._1
321+ let totalStaked = $t01381613918._2
322+ let totalStakedNew = $t01381613918._3
323+ ((([HistoryRecordEntry("stake", userAddress, i.transactionId, stakedAmount, vpEffectiveHeight, stakedAmountNEW, vpEffectiveHeightNEW)] ++ RewardEntries(isNewUser, userAddressStr, stakedAmount)) ++ LockParamsEntry(userAddress, stakedAmountNEW, vpEffectiveHeightNEW)) ++ statsEntries)
299324 }
300325 }
301326 }
302327 }
303328
304329
305330 func commonClaim (userAddress,i) = {
306331 let userAddressStr = toString(userAddress)
307332 if ((size(i.payments) > 0))
308333 then throw("payments are not accepted")
309334 else {
310- let $t01296313068 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
311- let isNewUser = $t01296313068._1
312- let stakedAmount = $t01296313068._2
313- let stakingStart = $t01296313068._3
335+ let $t01439714502 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
336+ let isNewUser = $t01439714502._1
337+ let stakedAmount = $t01439714502._2
338+ let stakingStart = $t01439714502._3
314339 let stakedAmountX = toBigInt(stakedAmount)
315340 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
316341 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
317342 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
318343 func forEachAssetCalcUnclaimedReward (accum,asset) = {
319- let $t01343913577 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
320- let rewardTotal = $t01343913577._1
321- let cached = $t01343913577._2
322- let dynamic = $t01343913577._3
323- let rewardCachedPartKEY = $t01343913577._4
344+ let $t01487315011 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
345+ let rewardTotal = $t01487315011._1
346+ let cached = $t01487315011._2
347+ let dynamic = $t01487315011._3
348+ let rewardCachedPartKEY = $t01487315011._4
324349 let claimedKEY = keyClaimed(userAddressStr, asset)
325- let $t01363713674 = accum
326- let data = $t01363713674._1
327- let claimedAmtByAsset = $t01363713674._2
350+ let $t01507115108 = accum
351+ let data = $t01507115108._1
352+ let claimedAmtByAsset = $t01507115108._2
328353 let newPart = makeString([asset, toString(rewardTotal)], ":")
329354 let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
330355 if ((0 >= rewardTotal))
331356 then $Tuple2(data, claimedAmtByAssetNew)
332357 else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
333358 }
334359
335- let $t01413414248 = {
360+ let $t01556815682 = {
336361 let $l = supportedAssetsList
337362 let $s = size($l)
338363 let $acc0 = $Tuple2(nil, "")
339364 func $f0_1 ($a,$i) = if (($i >= $s))
340365 then $a
341366 else forEachAssetCalcUnclaimedReward($a, $l[$i])
342367
343368 func $f0_2 ($a,$i) = if (($i >= $s))
344369 then $a
345370 else throw("List size exceeds 10")
346371
347372 $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)
348373 }
349- let transfers = $t01413414248._1
350- let claimedAmtByAssetResult = $t01413414248._2
374+ let transfers = $t01556815682._1
375+ let claimedAmtByAssetResult = $t01556815682._2
351376 if ((0 >= size(transfers)))
352377 then nil
353378 else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
354379 }
355380 }
356381
357382
358383 @Callable(i)
359384 func constructor (minLockAmount,supportedRewardAssets,stakedAssetId) = if ((i.caller != this))
360385 then throw("Permission denied")
361386 else [IntegerEntry(keyMinLockAmount(), minLockAmount), StringEntry(keySupportedRewardAssets(), supportedRewardAssets), StringEntry(keyStakedAssetId(), stakedAssetId)]
362387
363388
364389
365390 @Callable(i)
366391 func stake () = commonStake(i.caller, i)
367392
368393
369394
370395 @Callable(i)
371396 func stakeByOriginCaller () = commonStake(i.originCaller, i)
372397
373398
374399
375400 @Callable(i)
376401 func unstake (amount) = if ((size(i.payments) != 0))
377402 then throw("unstake doesn't require any payment")
378403 else {
379404 let userAddress = i.caller
380405 let userAddressStr = toString(userAddress)
381- let $t01515715211 = getParamsOrFail()
382- let stakedAssetId = $t01515715211._1
383- let minLockAmount = $t01515715211._2
384- let $t01521415288 = getUserParamsOrFail(userAddress)
385- let isNewUser = $t01521415288._1
386- let lockAmount = $t01521415288._2
387- let lockStart = $t01521415288._3
406+ let $t01659116645 = getParamsOrFail()
407+ let stakedAssetId = $t01659116645._1
408+ let minLockAmount = $t01659116645._2
409+ let $t01664816722 = getUserParamsOrFail(userAddress)
410+ let isNewUser = $t01664816722._1
411+ let lockAmount = $t01664816722._2
412+ let lockStart = $t01664816722._3
388413 if ((0 >= lockAmount))
389414 then throw("Nothing to unstake")
390415 else if ((amount > lockAmount))
391416 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(lockAmount)))
392417 else {
393- let $t01547815632 = StatsResult(-(amount), if ((amount == lockAmount))
418+ let $t01691217066 = StatsResult(-(amount), if ((amount == lockAmount))
394419 then -1
395420 else 0, if ((amount == lockAmount))
396421 then -1
397422 else 0)
398- let statsEntries = $t01547815632._1
399- let totalStaked = $t01547815632._2
400- let totalStakedNew = $t01547815632._3
423+ let statsEntries = $t01691217066._1
424+ let totalStaked = $t01691217066._2
425+ let totalStakedNew = $t01691217066._3
401426 ((([ScriptTransfer(userAddress, amount, stakedAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
402427 }
403428 }
404429
405430
406431
407432 @Callable(i)
408433 func deposit () = if ((size(i.payments) != 1))
409434 then throw("exact 1 payment is allowed only")
410435 else {
411436 let pmt = i.payments[0]
412437 let amount = pmt.amount
413438 let pmtAssetId = valueOrElse(pmt.assetId, WAVESID)
414439 let pmtAssetIdStr = toBase58String(pmtAssetId)
415440 let pmtMultX = if ((pmtAssetId == WAVESID))
416441 then MULTX8
417442 else MULTX6
418443 let amountX = toBigInt(amount)
419444 let totalStaked = getIntOrElse(keyLockParamTotalAmount(), 0)
420445 let totalStakedX = toBigInt(totalStaked)
421446 if ((0 > totalStaked))
422447 then throw("TODO: case is not supported")
423448 else if ((totalStaked == 0))
424449 then IncrementNotDistributedRewardEntry(pmtAssetIdStr, amount)
425450 else {
426451 let rewardPerNsbtX18 = fraction(amountX, MULTX18, totalStakedX)
427452 let depositNumLastKEY = keyDepositNumLast()
428453 let depositNumLast = getIntOrElse(depositNumLastKEY, -1)
429454 let depositNumNew = (depositNumLast + 1)
430455 if (!(contains(supportedAssetsStr, pmtAssetIdStr)))
431456 then throw(((supportedAssetsStr + " doesn't contain ") + pmtAssetIdStr))
432457 else {
433458 func refreshRewardPerNsbtSUM (accum,nextAsset) = {
434459 let rewardPerNsbtSumNewKEY = keyRewardPerNsbtSumAt(depositNumNew, nextAsset)
435460 let sumLastStr = getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, nextAsset), "0")
436461 (accum :+ (if ((nextAsset == pmtAssetIdStr))
437462 then StringEntry(rewardPerNsbtSumNewKEY, toString((parseBigIntValue(sumLastStr) + rewardPerNsbtX18)))
438463 else StringEntry(rewardPerNsbtSumNewKEY, sumLastStr)))
439464 }
440465
441466 ({
442467 let $l = supportedAssetsList
443468 let $s = size($l)
444469 let $acc0 = nil
445470 func $f0_1 ($a,$i) = if (($i >= $s))
446471 then $a
447472 else refreshRewardPerNsbtSUM($a, $l[$i])
448473
449474 func $f0_2 ($a,$i) = if (($i >= $s))
450475 then $a
451476 else throw("List size exceeds 10")
452477
453478 $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)
454479 } :+ IntegerEntry(depositNumLastKEY, depositNumNew))
455480 }
456481 }
457482 }
458483
459484
460485
461486 @Callable(i)
462487 func claimRewards () = commonClaim(i.caller, i)
463488
464489
465490
466491 @Callable(i)
467492 func claimRewardsByOriginCaller () = commonClaim(i.originCaller, i)
468493
469494
470495
471496 @Callable(i)
472497 func unclaimedRewardsREADONLY (userAddressStr) = {
473498 func forEachAssetZeroReward (accum,asset) = ((accum + makeString([asset, "0", "0"], ":")) + "_")
474499
475500 let unclaimedRewardStr = if ((userAddressStr == ""))
476501 then {
477502 let $l = supportedAssetsList
478503 let $s = size($l)
479504 let $acc0 = ""
480505 func $f0_1 ($a,$i) = if (($i >= $s))
481506 then $a
482507 else forEachAssetZeroReward($a, $l[$i])
483508
484509 func $f0_2 ($a,$i) = if (($i >= $s))
485510 then $a
486511 else throw("List size exceeds 10")
487512
488513 $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)
489514 }
490515 else {
491516 let userAddress = addressFromStringValue(userAddressStr)
492- let $t01818618291 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
493- let isNewUser = $t01818618291._1
494- let stakedAmount = $t01818618291._2
495- let stakingStart = $t01818618291._3
517+ let $t01962019725 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
518+ let isNewUser = $t01962019725._1
519+ let stakedAmount = $t01962019725._2
520+ let stakingStart = $t01962019725._3
496521 let stakedAmountX = toBigInt(stakedAmount)
497522 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
498523 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
499524 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
500525 func forEachAssetCalcUnclaimedReward (accum,asset) = {
501- let $t01863718775 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
502- let rewardTotal = $t01863718775._1
503- let cached = $t01863718775._2
504- let dynamic = $t01863718775._3
505- let rewardCachedPartKEY = $t01863718775._4
526+ let $t02007120209 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
527+ let rewardTotal = $t02007120209._1
528+ let cached = $t02007120209._2
529+ let dynamic = $t02007120209._3
530+ let rewardCachedPartKEY = $t02007120209._4
506531 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
507532 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
508533 }
509534
510535 let $l = supportedAssetsList
511536 let $s = size($l)
512537 let $acc0 = ""
513538 func $f0_1 ($a,$i) = if (($i >= $s))
514539 then $a
515540 else forEachAssetCalcUnclaimedReward($a, $l[$i])
516541
517542 func $f0_2 ($a,$i) = if (($i >= $s))
518543 then $a
519544 else throw("List size exceeds 10")
520545
521546 $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)
522547 }
523548 $Tuple2(nil, dropRight(unclaimedRewardStr, 1))
524549 }
525550
526551
527552
528553 @Callable(i)
529-func surfStakingSYSREADONLY (userAddressStrOrEmpty) = {
554+func surfStakingSYSREADONLY (userAddressStrOrEmpty,surfDiff) = {
530555 let surfTotal = getIntOrElse(keyLockParamTotalAmount(), 0)
531556 let gnsbtFromSurfTotal = surfToGnsbt(surfTotal)
532557 if ((userAddressStrOrEmpty == ""))
533- then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, 0])
558+ then $Tuple2(nil, [0, surfTotal, 0, gnsbtFromSurfTotal, 0, height, height])
534559 else {
535560 let userAddress = toAddressOrFail(userAddressStrOrEmpty)
536- let $t01946719568 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
537- let isNewUser = $t01946719568._1
538- let surfUser = $t01946719568._2
539- let stakingStart = $t01946719568._3
561+ let mergedData = mergeStake(userAddress, surfDiff)
562+ let isNewUser = mergedData._1
563+ let stakedAmount = mergedData._2
564+ let vpEffectiveHeight = mergedData._3
565+ let stakedAmountNEW = mergedData._4
566+ let vpEffectiveHeightNEW = mergedData._5
567+ let surfUser = stakedAmount
540568 let gnsbtFromSurfUser = surfToGnsbt(surfUser)
541- $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, stakingStart])
569+ $Tuple2(nil, [surfUser, surfTotal, gnsbtFromSurfUser, gnsbtFromSurfTotal, vpEffectiveHeight, vpEffectiveHeightNEW])
542570 }
543571 }
544572
545573
546574
547575 @Callable(i)
548576 func configSYSREADONLY () = {
549577 let minLockAmt = getIntegerValue(keyMinLockAmount())
550578 let gnsbtFromSurfCoeff = (60 * MULT6)
551579 let surfVotingPowerRestrictivePeriod = (1440 * 14)
552- let brToStartSurfTransformation = 1200000
580+ let brToStartSurfTransformation = 1150000
553581 $Tuple2(nil, [minLockAmt, gnsbtFromSurfCoeff, surfVotingPowerRestrictivePeriod, brToStartSurfTransformation])
554582 }
555583
556584

github/deemru/w8io/026f985 
88.00 ms