2023.05.11 17:41 [3638820] smart account 3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE > SELF 0.00000000 Waves

{ "type": 13, "id": "4VURPAEc2M9S47VYAj1wcF9B838jACvRk8djxyKn9gED", "fee": 2200000, "feeAssetId": null, "timestamp": 1683818129094, "version": 1, "sender": "3P9vKqQKjUdmpXAfiWau8krREYAY1Xr69pE", "senderPublicKey": "7AUMX54ukYMYvPmma7yoFf5NjZhs4Bu5nz3Ez9EV8sur", "proofs": [ "2sHDbxCvS3pjCDB2quMSmENj5dpFXyuyrcDmrGnnordMs5cYec5VynfT9wq2sFSJKALVGf9azT1ErTDK3Tzc25qY" ], "script": "base64:BgI6CAISBwoFAQgIAQESBQoDCAgIEgASAwoBCBIDCgEIEgYKBAgIAQESAwoBCBIGCgQBAQgIEgUKAwgICEoAA1NFUAICX18ABU1VTFQ2AMCEPQAFTVVMVDgAgMLXLwAKV0FWRVNJRFNUUgIFV0FWRVMAB1dBVkVTSUQJANkEAQUKV0FWRVNJRFNUUgEMZ2V0SW50T3JGYWlsAQNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQNrZXkJAKwCAgkArAICAg9NYW5kYXRvcnkgdGhpcy4FA2tleQIPIGlzIG5vdCBkZWZpbmVkAQxnZXRJbnRPckVsc2UCA2tleQN2YWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5BQN2YWwBDGdldFN0ck9yRWxzZQMHYWRkcmVzcwNrZXkKZGVmYXVsdFZhbAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQdhZGRyZXNzBQNrZXkFCmRlZmF1bHRWYWwBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJAKwCAgkArAICAg9NYW5kYXRvcnkgdGhpcy4FA2tleQIPIGlzIG5vdCBkZWZpbmVkARBnZXRBZGRyZXNzT3JGYWlsAQNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwUDa2V5CQCsAgIJAKwCAgIVRmFpbCB0byBjb252ZXJ0IHRoaXMuBQNrZXkCEyB2YWx1ZSBpbnRvIEFkZHJlc3MBCWFzQW55TGlzdAEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAp2YWxBbnlMaXN0BQckbWF0Y2gwBQp2YWxBbnlMaXN0CQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQVhc0ludAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgNJbnQEAWkFByRtYXRjaDAFAWkJAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBC2FzQnl0ZVZlY290AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWkFByRtYXRjaDAFAWkJAAIBAhxmYWlsIHRvIGNhc3QgaW50byBCeXRlVmVjdG9yARV2YWxpZGF0ZUFkZHJlc3NPckZhaWwBCmFkZHJlc3NTdHIEB2FkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQphZGRyZXNzU3RyCQCsAgICHWZhaWwgdG8gY29udmVydCBpbnRvIGFkZHJlc3MgBQphZGRyZXNzU3RyAwkAZgIAAAgJAO8HAQUHYWRkcmVzcwlhdmFpbGFibGUJAQV0aHJvdwAFCmFkZHJlc3NTdHIBD2tleU5vZGVSZWdpc3RyeQEHYWRkcmVzcwkArAICAgQlc19fBQdhZGRyZXNzARRrZXlOb2RlUmV3YXJkc1RvdGFscwEHYWRkcmVzcwkArAICAg4lcyVzX190b3RhbHNfXwUHYWRkcmVzcwETa2V5QXBwcm92ZWROb2RlTGlzdAACFCVzX19hcHByb3ZlZE5vZGVMaXN0ARBrZXlEZXBvc2l0QW1vdW50AAIYJXMlc19fY2ZnX19kZXBvc2l0QW1vdW50ARVrZXlOZXV0cmlub0FkZHJlc3NTdHIAAholcyVzX19jZmdfX25ldXRyaW5vQWRkcmVzcwEXa2V5TWFzdGVyTm9kZUFkZHJlc3NTdHIAAiIlcyVzX19jZmdfX21haW5OZXV0cmlub05vZGVBZGRyZXNzARFrZXlQcm90b2NvbFBhcnRYNgACGSVzJXNfX2NmZ19fcHJvdG9jb2xQYXJ0WDYBE2tleUJlbmlmaWNhcnlQYXJ0WDYAAhslcyVzX19jZmdfX2JlbmlmaWNhcnlQYXJ0WDYBFmtleU1pbkRpc3RyaWJ1dGVBbW91bnQAAh4lcyVzX19jZmdfX21pbkRpc3RyaWJ1dGVBbW91bnQBHGtleVN3b3BmaVVzZHRVc2RuUG9vbEFkZHJlc3MAAiQlcyVzX19jZmdfX3N3b3BmaVVzZHRVc2RuUG9vbEFkZHJlc3MBEGtleVd4U3dhcEFkZHJlc3MAAhglcyVzX19jZmdfX3d4U3dhcEFkZHJlc3MBEWtleVNhdmluZ3NBZGRyZXNzAAIZJXMlc19fY2ZnX19zYXZpbmdzQWRkcmVzcwEVa2V5QmVuZWZpY2lhcnlBZGRyZXNzAAIdJXMlc19fY2ZnX19iZW5lZmljaWFyeUFkZHJlc3MBFWtleU5vZGVzVm90aW5nTmV4dE51bQACIyVzJXNfX25vZGVzVm90aW5nQ2ZnX19uZXh0Vm90aW5nTnVtARdrZXlOb2Rlc1ZvdGluZ09wdGlvbktleQIJdm90aW5nTnVtCW9wdGlvbk51bQkAuQkCCQDMCAICFiVzJWQlc19fbm9kZXNWb3RpbmdDZmcJAMwIAgUJdm90aW5nTnVtCQDMCAIFCW9wdGlvbk51bQUDbmlsBQNTRVABEmtleU5vZGVzVm90aW5nRGVzYwEJdm90aW5nTnVtCQC5CQIJAMwIAgIWJXMlZCVzX19ub2Rlc1ZvdGluZ0NmZwkAzAgCBQl2b3RpbmdOdW0JAMwIAgILZGVzY3JpcHRpb24FA25pbAUDU0VQARlrZXlOb2Rlc1ZvdGluZ1N0YXJ0SGVpZ2h0AQl2b3RpbmdOdW0JALkJAgkAzAgCAhYlcyVkJXNfX25vZGVzVm90aW5nQ2ZnCQDMCAIFCXZvdGluZ051bQkAzAgCAhF2b3RpbmdTdGFydEhlaWdodAUDbmlsBQNTRVABF2tleU5vZGVzVm90aW5nRW5kSGVpZ2h0AQl2b3RpbmdOdW0JALkJAgkAzAgCAhYlcyVkJXNfX25vZGVzVm90aW5nQ2ZnCQDMCAIFCXZvdGluZ051bQkAzAgCAg92b3RpbmdFbmRIZWlnaHQFA25pbAUDU0VQAR5rZXlOb2Rlc1ZvdGluZ09wdGlvblRvdGFsVm90ZXMCCXZvdGluZ051bQlvcHRpb25OdW0JALkJAgkAzAgCAhklcyVkJXMlc19fbm9kZXNWb3RpbmdEYXRhCQDMCAIFCXZvdGluZ051bQkAzAgCAhBvcHRpb25Ub3RhbFZvdGVzCQDMCAIFCW9wdGlvbk51bQUDbmlsBQNTRVABGGtleU5vZGVzVm90aW5nTm9kZUNob2ljZQIJdm90aW5nTnVtDm5vZGVBZGRyZXNzU3RyCQC5CQIJAMwIAgIZJXMlZCVzJXNfX25vZGVzVm90aW5nRGF0YQkAzAgCBQl2b3RpbmdOdW0JAMwIAgIKbm9kZUNob2ljZQkAzAgCBQ5ub2RlQWRkcmVzc1N0cgUDbmlsBQNTRVAAGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAAQAYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwAAIAFElkeENvbnRyb2xDZmdScGREYXBwAAMAFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAEABxJZHhDb250cm9sQ2ZnTGlxdWlkYXRpb25EYXBwAAUAFUlkeENvbnRyb2xDZmdSZXN0RGFwcAAGAB1JZHhDb250cm9sQ2ZnTm9kZVJlZ2lzdHJ5RGFwcAAHABxJZHhDb250cm9sQ2ZnTnNidFN0YWtpbmdEYXBwAAgAGUlkeENvbnRyb2xDZmdNZWRpYXRvckRhcHAACQAcSWR4Q29udHJvbENmZ1N1cmZTdGFraW5nRGFwcAAKACBJZHhDb250cm9sQ2ZnR25zYnRDb250cm9sbGVyRGFwcAALABdJZHhDb250cm9sQ2ZnUmVzdFYyRGFwcAAMABtJZHhDb250cm9sQ2ZnR292ZXJuYW5jZURhcHAADQERa2V5Q29udHJvbEFkZHJlc3MAAhwlcyVzX19jb25maWdfX2NvbnRyb2xBZGRyZXNzAQ1rZXlDb250cm9sQ2ZnAAIRJXNfX2NvbnRyb2xDb25maWcBDmtleVVzZG5Bc3NldElkAAIRbmV1dHJpbm9fYXNzZXRfaWQBFHJlYWRDb250cm9sQ2ZnT3JGYWlsAQdjb250cm9sCQC8CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQdjb250cm9sCQENa2V5Q29udHJvbENmZwAFA1NFUAEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgpjb250cm9sQ2ZnA2lkeAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUKY29udHJvbENmZwUDaWR4CQCsAgICLUNvbnRyb2wgY2ZnIGRvZXNuJ3QgY29udGFpbiBhZGRyZXNzIGF0IGluZGV4IAkApAMBBQNpZHgAD2NvbnRyb2xDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQERa2V5Q29udHJvbEFkZHJlc3MAAiMzUDVCZmQ1OFBQZk52Qk0ySHk4UWZiY0RxTWVOdHpnN0tmUAAKY29udHJvbENmZwkBFHJlYWRDb250cm9sQ2ZnT3JGYWlsAQUPY29udHJvbENvbnRyYWN0ABBuZXV0cmlub0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUZSWR4Q29udHJvbENmZ05ldXRyaW5vRGFwcAAOdXNkbkFzc2V0SWRTdHIJAQxnZXRTdHJPckVsc2UDBRBuZXV0cmlub0NvbnRyYWN0CQEOa2V5VXNkbkFzc2V0SWQAAixERzJ4RmtQZER3S1VvQmt6R0FoUXRMcFNHemZYTGlDWVBFemVLSDJBZDI0cAALdXNkbkFzc2V0SWQJANkEAQUOdXNkbkFzc2V0SWRTdHIADG5SZWdJZHhUeEFkZAABABBuUmVnSWR4SGVpZ2h0QWRkAAIADm5SZWdJZHhUaW1lQWRkAAMADm5SZWdJZHhEZXBvQW10AAQAEm5SZWdJZHhEZXBvQW10TGVmdAAFAA1uUmVnSWR4U3RhdHVzAAYAGW5SZWdJZHhTdGF0dXNDaGFuZ2VIZWlnaHQABwAXblJlZ0lkeFN0YXR1c0NoYW5nZVRpbWUACAEQZm9ybWF0RGVwb3NpdEFkZAQHdHhJZFN0cg1kZXBvc2l0QW1vdW50FnJlbWFpbmluZ0RlcG9zaXRBbW91bnQGc3RhdHVzCQC5CQIJAMwIAgIQJXMlZCVkJWQlZCVzJWQlZAkAzAgCBQd0eElkU3RyCQDMCAIJAKQDAQgFCWxhc3RCbG9jawZoZWlnaHQJAMwIAgkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQCkAwEFDWRlcG9zaXRBbW91bnQJAMwIAgkApAMBBRZyZW1haW5pbmdEZXBvc2l0QW1vdW50CQDMCAIFBnN0YXR1cwkAzAgCAgEwCQDMCAICATAFA25pbAUDU0VQARlmb3JtYXREZXBvc2l0Q2hhbmdlU3RhdHVzAgVvcmlnUwluZXdTdGF0dXMEBG9yaWcJALUJAgUFb3JpZ1MFA1NFUAkAuQkCCQDMCAICECVzJWQlZCVkJWQlcyVkJWQJAMwIAgkAkQMCBQRvcmlnBQxuUmVnSWR4VHhBZGQJAMwIAgkAkQMCBQRvcmlnBRBuUmVnSWR4SGVpZ2h0QWRkCQDMCAIJAJEDAgUEb3JpZwUOblJlZ0lkeFRpbWVBZGQJAMwIAgkAkQMCBQRvcmlnBQ5uUmVnSWR4RGVwb0FtdAkAzAgCCQCRAwIFBG9yaWcFEm5SZWdJZHhEZXBvQW10TGVmdAkAzAgCBQluZXdTdGF0dXMJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQNuaWwFA1NFUAEQa2V5UmV3YXJkSGlzdG9yeQILbm9kZUFkZHJlc3MEdHhJZAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAgdoaXN0b3J5CQDMCAIJAKUIAQULbm9kZUFkZHJlc3MJAMwIAgkA2AQBBQR0eElkBQNuaWwFA1NFUAERZGF0YVJld2FyZEhpc3RvcnkFEHdhdmVzQW1vdW50VG90YWwOYmVuZWZpY2lhcnlBbXQLcHJvdG9jb2xBbXQQcHJvdG9jb2xBbXRQYXJ0MRBwcm90b2NvbEFtdFBhcnQyCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUQd2F2ZXNBbW91bnRUb3RhbAkAzAgCCQCkAwEFDmJlbmVmaWNpYXJ5QW10CQDMCAIJAKQDAQULcHJvdG9jb2xBbXQJAMwIAgkApAMBBRBwcm90b2NvbEFtdFBhcnQxCQDMCAIJAKQDAQUQcHJvdG9jb2xBbXRQYXJ0MgUDbmlsBQNTRVABElJld2FyZEhpc3RvcnlFbnRyeQcLbm9kZUFkZHJlc3MEdHhJZAhtaW5lZEFtdA5iZW5lZmljaWFyeUFtdAtwcm90b2NvbEFtdAxwcm90b2NvbEFtdDEMcHJvdG9jb2xBbXQyCQELU3RyaW5nRW50cnkCCQEQa2V5UmV3YXJkSGlzdG9yeQIFC25vZGVBZGRyZXNzBQR0eElkCQERZGF0YVJld2FyZEhpc3RvcnkFBQhtaW5lZEFtdAUOYmVuZWZpY2lhcnlBbXQFC3Byb3RvY29sQW10BQxwcm90b2NvbEFtdDEFDHByb3RvY29sQW10MgEQZGF0YVJld2FyZFRvdGFscwUIbWluZWRBbXQOYmVuZWZpY2lhcnlBbXQLcHJvdG9jb2xBbXQQcHJvdG9jb2xBbXRQYXJ0MRBwcm90b2NvbEFtdFBhcnQyCQC5CQIJAMwIAgIKJWQlZCVkJWQlZAkAzAgCCQCkAwEFCG1pbmVkQW10CQDMCAIJAKQDAQUOYmVuZWZpY2lhcnlBbXQJAMwIAgkApAMBBQtwcm90b2NvbEFtdAkAzAgCCQCkAwEFEHByb3RvY29sQW10UGFydDEJAMwIAgkApAMBBRBwcm90b2NvbEFtdFBhcnQyBQNuaWwFA1NFUAERUmV3YXJkVG90YWxzRW50cnkGBW1pbmVyCG1pbmVkQW10DmJlbmVmaWNpYXJ5QW10C3Byb3RvY29sQW10EHByb3RvY29sQW10UGFydDEQcHJvdG9jb2xBbXRQYXJ0MgQUbm9kZVJld2FyZHNUb3RhbHNLRVkJARRrZXlOb2RlUmV3YXJkc1RvdGFscwEJAKUIAQUFbWluZXIEEG5vZGVSZXdhcmRzQXJyYXkJALUJAgkBDGdldFN0ck9yRWxzZQMFBHRoaXMFFG5vZGVSZXdhcmRzVG90YWxzS0VZCQEQZGF0YVJld2FyZFRvdGFscwUAAAAAAAAAAAAABQNTRVAEC25ld01pbmVkQW10CQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEG5vZGVSZXdhcmRzQXJyYXkAAQUIbWluZWRBbXQEEW5ld0JlbmVmaWNpYXJ5QW10CQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEG5vZGVSZXdhcmRzQXJyYXkAAgUOYmVuZWZpY2lhcnlBbXQEDm5ld1Byb3RvY29sQW10CQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEG5vZGVSZXdhcmRzQXJyYXkAAwULcHJvdG9jb2xBbXQEE25ld1Byb3RvY29sQW10UGFydDEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUQbm9kZVJld2FyZHNBcnJheQAEBRBwcm90b2NvbEFtdFBhcnQxBBNuZXdQcm90b2NvbEFtdFBhcnQyCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFEG5vZGVSZXdhcmRzQXJyYXkABQUQcHJvdG9jb2xBbXRQYXJ0MgkBC1N0cmluZ0VudHJ5AgUUbm9kZVJld2FyZHNUb3RhbHNLRVkJARBkYXRhUmV3YXJkVG90YWxzBQULbmV3TWluZWRBbXQFEW5ld0JlbmVmaWNpYXJ5QW10BQ5uZXdQcm90b2NvbEFtdAUTbmV3UHJvdG9jb2xBbXRQYXJ0MQUTbmV3UHJvdG9jb2xBbXRQYXJ0MgEUcmVzb2x2ZUJlbmVmaWNpYXJpZXMCDG1pbmVyQWRkcmVzcxRiZW5lZmljaWFyeUZyb21QYXJhbQQZYmVuZWZpY2lhcnlGcm9tTWluZXJTdGF0ZQkBEUBleHRyTmF0aXZlKDEwNjIpAQkBD2dldFN0cmluZ09yRmFpbAIFDG1pbmVyQWRkcmVzcwkBFWtleUJlbmVmaWNpYXJ5QWRkcmVzcwADCQAAAgkA8QcBBQxtaW5lckFkZHJlc3MFBHVuaXQFFGJlbmVmaWNpYXJ5RnJvbVBhcmFtBRliZW5lZmljaWFyeUZyb21NaW5lclN0YXRlAR1yZWFkTm9kZURhdGFBbmRWYWxpZGF0ZVN0YXR1cwIIbm9kZUFkZHIOZXhwZWN0ZWRTdGF0dXMEC25vZGVEYXRhT3B0CQCiCAEJAQ9rZXlOb2RlUmVnaXN0cnkBBQhub2RlQWRkcgMJAQEhAQkBCWlzRGVmaW5lZAEFC25vZGVEYXRhT3B0CQACAQkArAICAg1Vbmtub3duIE5vZGUgBQhub2RlQWRkcgQLbm9kZURhdGFTdHIJAQV2YWx1ZQEFC25vZGVEYXRhT3B0BAhub2RlRGF0YQkAtQkCBQtub2RlRGF0YVN0cgUDU0VQBApub2RlU3RhdHVzAwkAZwIJAJADAQUIbm9kZURhdGEACQkAkQMCBQhub2RlRGF0YQUNblJlZ0lkeFN0YXR1cwIHUEVORElORwMJAQIhPQIFCm5vZGVTdGF0dXMFDmV4cGVjdGVkU3RhdHVzCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICBU5vZGUgBQhub2RlQWRkcgISIHN0YXR1cyBzaG91bGQgYmUgBQ5leHBlY3RlZFN0YXR1cwIPLCBidXQgYWN0dWFsbHkgBQpub2RlU3RhdHVzBQtub2RlRGF0YVN0cgkBaQENY29uc3RydWN0b3JWMQUNZGVwb3NpdEFtb3VudBJuZXV0cmlub0FkZHJlc3NTdHIUbWFzdGVyTm9kZUFkZHJlc3NTdHIOcHJvdG9jb2xQYXJ0WDYQYmVuaWZpY2FyeVBhcnRYNgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEnBlcm1pc3Npb25zIGRlbmllZAMJAGYCAAAFDWRlcG9zaXRBbW91bnQJAAIBAhxkZXBvc2l0QW1vdW50IGxlc3MgdGhlbiB6ZXJvAwkAZgIAAAUOcHJvdG9jb2xQYXJ0WDYJAAIBAh1wcm90b2NvbFBhcnRYNiBsZXNzIHRoZW4gemVybwMJAGYCAAAFEGJlbmlmaWNhcnlQYXJ0WDYJAAIBAh9iZW5pZmljYXJ5UGFydFg2IGxlc3MgdGhlbiB6ZXJvAwkBAiE9AgkAZAIFDnByb3RvY29sUGFydFg2BRBiZW5pZmljYXJ5UGFydFg2BQVNVUxUNgkAAgECE3BhcnRzIHN1bSBtdXN0IGJlIDEJAMwIAgkBDEludGVnZXJFbnRyeQIJARBrZXlEZXBvc2l0QW1vdW50AAUNZGVwb3NpdEFtb3VudAkAzAgCCQELU3RyaW5nRW50cnkCCQEVa2V5TmV1dHJpbm9BZGRyZXNzU3RyAAkBFXZhbGlkYXRlQWRkcmVzc09yRmFpbAEFEm5ldXRyaW5vQWRkcmVzc1N0cgkAzAgCCQELU3RyaW5nRW50cnkCCQEXa2V5TWFzdGVyTm9kZUFkZHJlc3NTdHIACQEVdmFsaWRhdGVBZGRyZXNzT3JGYWlsAQUUbWFzdGVyTm9kZUFkZHJlc3NTdHIJAMwIAgkBDEludGVnZXJFbnRyeQIJARFrZXlQcm90b2NvbFBhcnRYNgAFDnByb3RvY29sUGFydFg2CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQETa2V5QmVuaWZpY2FyeVBhcnRYNgAFEGJlbmlmaWNhcnlQYXJ0WDYFA25pbAFpAQ1jb25zdHJ1Y3RvclYyAxBzd29wZmlBZGRyZXNzU3RyEWNvbnRyb2xBZGRyZXNzU3RyEXNhdmluZ3NBZGRyZXNzU3RyAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIScGVybWlzc2lvbnMgZGVuaWVkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARxrZXlTd29wZmlVc2R0VXNkblBvb2xBZGRyZXNzAAkBFXZhbGlkYXRlQWRkcmVzc09yRmFpbAEFEHN3b3BmaUFkZHJlc3NTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUNvbnRyb2xBZGRyZXNzAAkBFXZhbGlkYXRlQWRkcmVzc09yRmFpbAEFEWNvbnRyb2xBZGRyZXNzU3RyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlTYXZpbmdzQWRkcmVzcwAJARV2YWxpZGF0ZUFkZHJlc3NPckZhaWwBBRFzYXZpbmdzQWRkcmVzc1N0cgUDbmlsAWkBEXN1bWJpdEFwcGxpY2F0aW9uAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECIGV4YWN0IDEgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkAwkBAiE9AggFAWkGY2FsbGVyCAUBaQxvcmlnaW5DYWxsZXIJAAIBAiJkYXBwIHRvIGRhcHAgY2FsbHMgYXJlIG5vdCBhbGxvd2VkBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQHZGVwb3NpdAgFA3BtdAZhbW91bnQECnBtdEFzc2V0SWQJAQt2YWx1ZU9yRWxzZQIIBQNwbXQHYXNzZXRJZAUHV0FWRVNJRAQVZXhwZWN0ZWREZXBvc2l0QW1vdW50CQEMZ2V0SW50T3JGYWlsAQkBEGtleURlcG9zaXRBbW91bnQABAR0eElkCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQEC25vZGVBZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQPbm9kZVJlZ2lzdHJ5S0VZCQEPa2V5Tm9kZVJlZ2lzdHJ5AQULbm9kZUFkZHJlc3MDCQECIT0CBQpwbXRBc3NldElkBQdXQVZFU0lECQACAQIib25seSBXYXZlcyBjYW4gYmUgdXNlZCBmb3IgZGVwb3NpdAMJAQIhPQIFB2RlcG9zaXQFFWV4cGVjdGVkRGVwb3NpdEFtb3VudAkAAgEJAKwCAgkArAICAghleGFjdGx5IAkApAMBBRVleHBlY3RlZERlcG9zaXRBbW91bnQCFiBXYXZlbGV0cyBhcmUgZXhwZWN0ZWQDCQECIT0CCQEMZ2V0U3RyT3JFbHNlAwUEdGhpcwUPbm9kZVJlZ2lzdHJ5S0VZAgACAAkAAgECHHlvdXIgbm9kZSBhbHJlYWR5IHJlZ2lzdGVyZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUPbm9kZVJlZ2lzdHJ5S0VZCQEQZm9ybWF0RGVwb3NpdEFkZAQFBHR4SWQFB2RlcG9zaXQFB2RlcG9zaXQCB1BFTkRJTkcFA25pbAFpARVkaXN0cmlidXRlTWluZXJSZXdhcmQBFWJlbmVmaWNpYXJ5QWRkcmVzc1N0cgQTbWluRGlzdHJpYnV0ZUFtb3VudAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEWa2V5TWluRGlzdHJpYnV0ZUFtb3VudAAJAGgCABgFBU1VTFQ4AwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIgZXhhY3QgMSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQDCQECIT0CCAUBaQZjYWxsZXIIBQFpDG9yaWdpbkNhbGxlcgkAAgECImRhcHAgdG8gZGFwcCBjYWxscyBhcmUgbm90IGFsbG93ZWQEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAABApwbXRBc3NldElkCQELdmFsdWVPckVsc2UCCAUDcG10B2Fzc2V0SWQFB1dBVkVTSUQEBmZlZUFtdAgFAWkDZmVlBApmZWVBc3NldElkCQELdmFsdWVPckVsc2UCCAUBaQpmZWVBc3NldElkBQdXQVZFU0lEBApjYWxsUmV3YXJkCQBoAgUGZmVlQW10AAMECG1pbmVkQW10CQBlAggFA3BtdAZhbW91bnQFCmNhbGxSZXdhcmQDCQECIT0CCAUDcG10BmFtb3VudAUTbWluRGlzdHJpYnV0ZUFtb3VudAkAAgEJAKwCAgkArAICAh9hdHRhY2hlZCBwYXltZW50IG11c3QgYmUgZXhhY3QgCQCkAwEFE21pbkRpc3RyaWJ1dGVBbW91bnQCCSBXYXZlbGV0cwMJAQIhPQIFCnBtdEFzc2V0SWQFB1dBVkVTSUQJAAIBAiFvbmx5IFdhdmVzIGNhbiBiZSB1c2VkIGluIHBheW1lbnQDCQECIT0CBQpmZWVBc3NldElkBQdXQVZFU0lECQACAQIeb25seSBXYXZlcyBjYW4gYmUgdXNlZCBpbiBmZWVzAwkBAiE9AgUGZmVlQW10CQBpAgkAaAIABQUFTVVMVDgA6AcJAAIBAiBmZWUgYW1vdW50IGNvdWxkbid0IGV4Y2VlZCAwLjAwNQQPbmV1dHJpbm9BZGRyZXNzCQEQZ2V0QWRkcmVzc09yRmFpbAEJARVrZXlOZXV0cmlub0FkZHJlc3NTdHIABBFtYXN0ZXJOb2RlQWRkcmVzcwkBEGdldEFkZHJlc3NPckZhaWwBCQEXa2V5TWFzdGVyTm9kZUFkZHJlc3NTdHIABAxtaW5lckFkZHJlc3MIBQFpBmNhbGxlcgQUYmVuZWZpY2lhcnlGcm9tUGFyYW0JARFAZXh0ck5hdGl2ZSgxMDYyKQEFFWJlbmVmaWNpYXJ5QWRkcmVzc1N0cgQSYmVuZWZpY2lhcnlBZGRyZXNzCQEUcmVzb2x2ZUJlbmVmaWNpYXJpZXMCBQxtaW5lckFkZHJlc3MFFGJlbmVmaWNpYXJ5RnJvbVBhcmFtBBB0eFJld2FyZFJlY2VpdmVyBRRiZW5lZmljaWFyeUZyb21QYXJhbQQMcHJvdG9jb2xQYXJ0CQEMZ2V0SW50T3JGYWlsAQkBEWtleVByb3RvY29sUGFydFg2AAQPYmVuZWZpY2lhcnlQYXJ0CQEMZ2V0SW50T3JGYWlsAQkBE2tleUJlbmlmaWNhcnlQYXJ0WDYABA5iZW5lZmljaWFyeUFtdAkAawMFCG1pbmVkQW10BQ9iZW5lZmljaWFyeVBhcnQFBU1VTFQ2BAtwcm90b2NvbEFtdAkAZQIFCG1pbmVkQW10BQ5iZW5lZmljaWFyeUFtdAQKYnV5QmFja0FtdAkAaAIAeAUFTVVMVDgEDnNhdmluZ3NBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBCQEMZ2V0U3RyT3JFbHNlAwUEdGhpcwkBEWtleVNhdmluZ3NBZGRyZXNzAAIjM1BDN0RCaW1hdXlLeXR4OHRYaEtvNXUyRUNiNkZzbmRZS0gECnNhdmluZ3NBbXQJAQVhc0ludAEJAPwHBAUOc2F2aW5nc0FkZHJlc3MCCHdpdGhkcmF3CQDMCAIFCmJ1eUJhY2tBbXQFA25pbAUDbmlsBAx3eEFzc2V0SWRTdHICLEF0cXY1OUVZempGR3VpdEtWbk1SazZIOEZ1a2pvVjNrdFBvcmJFeXMyNW9uBA13eFN3YXBBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBCQEMZ2V0U3RyT3JFbHNlAwUEdGhpcwkBEGtleVd4U3dhcEFkZHJlc3MAAiMzUDY4ek5pdWZzdTF2aVpwdTFhWTNjZGFoUlJLY3ZWNU45MwQKc3dhcFJlc3VsdAkA/AcEBQ13eFN3YXBBZGRyZXNzAgRzd2FwCQDMCAIAAQkAzAgCBQx3eEFzc2V0SWRTdHIJAMwIAgkApQgBBRBuZXV0cmlub0NvbnRyYWN0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFBHVuaXQFCnNhdmluZ3NBbXQFA25pbAMJAAACBQpzd2FwUmVzdWx0BQpzd2FwUmVzdWx0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFEmJlbmVmaWNpYXJ5QWRkcmVzcwUOYmVuZWZpY2lhcnlBbXQFBHVuaXQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUQbmV1dHJpbm9Db250cmFjdAULcHJvdG9jb2xBbXQFBHVuaXQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUQdHhSZXdhcmRSZWNlaXZlcgUKY2FsbFJld2FyZAUEdW5pdAkAzAgCCQESUmV3YXJkSGlzdG9yeUVudHJ5BwUMbWluZXJBZGRyZXNzCAUBaQ10cmFuc2FjdGlvbklkBQhtaW5lZEFtdAUOYmVuZWZpY2lhcnlBbXQFC3Byb3RvY29sQW10BQtwcm90b2NvbEFtdAAACQDMCAIJARFSZXdhcmRUb3RhbHNFbnRyeQYFDG1pbmVyQWRkcmVzcwUIbWluZWRBbXQFDmJlbmVmaWNpYXJ5QW10BQtwcm90b2NvbEFtdAULcHJvdG9jb2xBbXQAAAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBGnZhbGlkYXRlQW5kQXBwcm92ZUxlYXNpbmdzAQZuTGlzdFMEBW5JZHhzCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcFA25pbAQFbkxpc3QJALUJAgUGbkxpc3RTBQNTRVAEDWV4cGVjdGVkQ291bnQJAJADAQUFbklkeHMED25ldXRyaW5vQWRkcmVzcwkBEGdldEFkZHJlc3NPckZhaWwBCQEVa2V5TmV1dHJpbm9BZGRyZXNzU3RyAAMJAQIhPQIIBQFpBmNhbGxlcgUPbmV1dHJpbm9BZGRyZXNzCQACAQIpdmFsaWRhdGVBbmRBcHByb3ZlTGVhc2luZ3Mgbm90IGF1dGhvcml6ZWQDCQECIT0CCQBqAgkAkAMBBQVuTGlzdAACAAAJAAIBAiRPbmx5IGV2ZW4gbnVtYmVyIG9mIG5vZGVzIGlzIGFsbG93ZWQDCQECIT0CCQCQAwEFBW5MaXN0BQ1leHBlY3RlZENvdW50CQACAQkArAICCQCsAgICBU9ubHkgCQCkAwEFDWV4cGVjdGVkQ291bnQCIiBvZiBub2RlcycgYWRkcmVzc2VzIGNhbiBiZSBwYXNzZWQKARdmb3JFYWNoTm9kZUNoYW5nZVN0YXR1cwIDYWNjAWkECG5vZGVBZGRyCQCRAwIFBW5MaXN0BQFpBAtub2RlRGF0YVN0cgkBHXJlYWROb2RlRGF0YUFuZFZhbGlkYXRlU3RhdHVzAgUIbm9kZUFkZHICB1BFTkRJTkcJAM0IAgUDYWNjCQELU3RyaW5nRW50cnkCCQEPa2V5Tm9kZVJlZ2lzdHJ5AQUIbm9kZUFkZHIJARlmb3JtYXREZXBvc2l0Q2hhbmdlU3RhdHVzAgULbm9kZURhdGFTdHICCEFQUFJPVkVEBBFhcHByb3ZlZE5vZGVzRGF0YQoAAiRsBQVuSWR4cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEXZm9yRWFjaE5vZGVDaGFuZ2VTdGF0dXMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDgJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAICQCUCgIFEWFwcHJvdmVkTm9kZXNEYXRhBQNuaWwBaQETcmVwbGFjZUFwcHJvdmVkTm9kZQQOb2xkTm9kZUFkZHJTdHIObmV3Tm9kZUFkZHJTdHIIZ3JvdXBOdW0NcGVuYWx0eUFtb3VudAMJAQIhPQIIBQFpBmNhbGxlcgUQbmV1dHJpbm9Db250cmFjdAkAAgECEnBlcm1pc3Npb25zIGRlbmllZAQKb2xkRGF0YVN0cgkBHXJlYWROb2RlRGF0YUFuZFZhbGlkYXRlU3RhdHVzAgUOb2xkTm9kZUFkZHJTdHICCEFQUFJPVkVEBApuZXdEYXRhU3RyCQEdcmVhZE5vZGVEYXRhQW5kVmFsaWRhdGVTdGF0dXMCBQ5uZXdOb2RlQWRkclN0cgIHUEVORElORwQRYXBwcm92ZWROb2RlTGlzdFMJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQETa2V5QXBwcm92ZWROb2RlTGlzdAADCQEBIQEJAQhjb250YWlucwIFEWFwcHJvdmVkTm9kZUxpc3RTBQ5vbGROb2RlQWRkclN0cgkAAgEJAKwCAgIiYXBwcm92ZWROb2RlTGlzdCBkb2VzIG5vdCBjb250YWluIAUOb2xkTm9kZUFkZHJTdHIEEHVwZGF0ZWROb2RlTGlzdFMJALoJAgkAvAkCBRFhcHByb3ZlZE5vZGVMaXN0UwUOb2xkTm9kZUFkZHJTdHIFDm5ld05vZGVBZGRyU3RyBAtvbGROb2RlQWRkcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUOb2xkTm9kZUFkZHJTdHIEEmJlbmVmaWNpYXJ5QWRkcmVzcwkBFHJlc29sdmVCZW5lZmljaWFyaWVzAgULb2xkTm9kZUFkZHIFC29sZE5vZGVBZGRyBApkZXBvQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCBQpvbGREYXRhU3RyBQNTRVAFDm5SZWdJZHhEZXBvQW10BAdhY3Rpb25zCQDMCAIJAQtTdHJpbmdFbnRyeQIJARNrZXlBcHByb3ZlZE5vZGVMaXN0AAUQdXBkYXRlZE5vZGVMaXN0UwkAzAgCCQELRGVsZXRlRW50cnkBCQEPa2V5Tm9kZVJlZ2lzdHJ5AQUOb2xkTm9kZUFkZHJTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleU5vZGVSZWdpc3RyeQEFDm5ld05vZGVBZGRyU3RyCQEZZm9ybWF0RGVwb3NpdENoYW5nZVN0YXR1cwIFCm5ld0RhdGFTdHICCEFQUFJPVkVEBQNuaWwJAJQKAgMJAGYCBQpkZXBvQW1vdW50BQ1wZW5hbHR5QW1vdW50CQDNCAIFB2FjdGlvbnMJAQ5TY3JpcHRUcmFuc2ZlcgMFEmJlbmVmaWNpYXJ5QWRkcmVzcwkAZQIFCmRlcG9BbW91bnQFDXBlbmFsdHlBbW91bnQFBHVuaXQFB2FjdGlvbnMFBHVuaXQBaQENcmV0dXJuRGVwb3NpdAEObm9kZUFkZHJlc3NTdHIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhNObyBwYXltZW50cyBhbGxvd2VkBA1jYWxsZXJBZGRyZXNzCAUBaQZjYWxsZXIED25vZGVSZWdpc3RyeUtFWQkBD2tleU5vZGVSZWdpc3RyeQEFDm5vZGVBZGRyZXNzU3RyBAtub2RlRGF0YU9wdAkAnQgCBQR0aGlzBQ9ub2RlUmVnaXN0cnlLRVkDCQEBIQEJAQlpc0RlZmluZWQBBQtub2RlRGF0YU9wdAkAAgEJAKwCAgIpQWRkcmVzcyBpcyBub3QgYXBwbGllZCBhcyBuZXV0cmlubyBub2RlOiAFDm5vZGVBZGRyZXNzU3RyBBBhcHByb3ZlZE5vZGVMaXN0CQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwkBE2tleUFwcHJvdmVkTm9kZUxpc3QAAwkBCGNvbnRhaW5zAgUQYXBwcm92ZWROb2RlTGlzdAUObm9kZUFkZHJlc3NTdHIJAAIBAkxJbXBvc3NpYmxlIHRvIHJldHVybiBkZXBvc2l0IGZyb20gYXBwcm92ZWQgTm9kZSwgcGxlYXNlIGNvbnRhY3Qgc3VwcG9ydCB0ZWFtBAhub2RlRGF0YQkAtQkCCQEFdmFsdWUBBQtub2RlRGF0YU9wdAUDU0VQBAZzdGF0dXMDCQBnAgkAkAMBBQhub2RlRGF0YQAJCQCRAwIFCG5vZGVEYXRhBQ1uUmVnSWR4U3RhdHVzAgdQRU5ESU5HAwkBAiE9AgUGc3RhdHVzAgdQRU5ESU5HCQACAQIiQXBwbGljYXRpb24gc3RhdHVzIGlzIG5vdCBQRU5ESU5HIQQKZGVwb0Ftb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCG5vZGVEYXRhBQ5uUmVnSWR4RGVwb0FtdAQLbm9kZUFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDm5vZGVBZGRyZXNzU3RyBBJiZW5lZmljaWFyeUFkZHJlc3MJARRyZXNvbHZlQmVuZWZpY2lhcmllcwIFC25vZGVBZGRyZXNzBQtub2RlQWRkcmVzcwMJAQEhAQMDCQAAAgUNY2FsbGVyQWRkcmVzcwUEdGhpcwYDCQECIT0CBRJiZW5lZmljaWFyeUFkZHJlc3MFC25vZGVBZGRyZXNzCQAAAgUNY2FsbGVyQWRkcmVzcwUSYmVuZWZpY2lhcnlBZGRyZXNzBwYDCQAAAgUSYmVuZWZpY2lhcnlBZGRyZXNzBQtub2RlQWRkcmVzcwkAAAIFDWNhbGxlckFkZHJlc3MFC25vZGVBZGRyZXNzBwkAAgECIHJldHVybkRlcG9zaXQgcGVybWlzc2lvbnMgZGVuaWVkCQDMCAIJAQtEZWxldGVFbnRyeQEFD25vZGVSZWdpc3RyeUtFWQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBRJiZW5lZmljaWFyeUFkZHJlc3MFCmRlcG9BbW91bnQFBHVuaXQFA25pbAFpAQ9pbml0Tm9kZXNWb3RpbmcEC3N0YXJ0SGVpZ2h0CWVuZEhlaWdodAdvcHRpb25zC2Rlc2NyaXB0aW9uAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIScGVybWlzc2lvbnMgZGVuaWVkBAxvcHRpb25zQXJyYXkJALUJAgUHb3B0aW9ucwICX18DCQBmAgkAkAMBBQxvcHRpb25zQXJyYXkACgkAAgECH01heCAxMCBvcHRpb25zIGNhbiBiZSBzcGVjaWZpZWQEEW5vZGVzVm90aW5nTnVtS0VZCQEVa2V5Tm9kZXNWb3RpbmdOZXh0TnVtAAQJdm90aW5nTnVtCQEMZ2V0SW50T3JFbHNlAgURbm9kZXNWb3RpbmdOdW1LRVkAAAQMdm90aW5nTnVtU3RyCQCkAwEFCXZvdGluZ051bQoBEHRyYW5zZm9ybU9wdGlvbnMCBWFjY3VtB25leHRPcHQEB29wdERhdGEJALUJAgUHbmV4dE9wdAIBOgQDb3B0CQCRAwIFB29wdERhdGEAAAQGb3B0S0VZCQEXa2V5Tm9kZXNWb3RpbmdPcHRpb25LZXkCBQx2b3RpbmdOdW1TdHIFA29wdAQIb3B0RGVzY3IJAJEDAgUHb3B0RGF0YQABBBBvcHRUb3RhbFZvdGVzS0VZCQEea2V5Tm9kZXNWb3RpbmdPcHRpb25Ub3RhbFZvdGVzAgUMdm90aW5nTnVtU3RyBQNvcHQJAM0IAgkAzQgCBQVhY2N1bQkBC1N0cmluZ0VudHJ5AgUGb3B0S0VZBQhvcHREZXNjcgkBDEludGVnZXJFbnRyeQIFEG9wdFRvdGFsVm90ZXNLRVkAAAkAzQgCCQDNCAIJAM0IAgkAzQgCCgACJGwFDG9wdGlvbnNBcnJheQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQdHJhbnNmb3JtT3B0aW9ucwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkBDEludGVnZXJFbnRyeQIFEW5vZGVzVm90aW5nTnVtS0VZCQBkAgUJdm90aW5nTnVtAAEJAQtTdHJpbmdFbnRyeQIJARJrZXlOb2Rlc1ZvdGluZ0Rlc2MBBQx2b3RpbmdOdW1TdHIFC2Rlc2NyaXB0aW9uCQEMSW50ZWdlckVudHJ5AgkBGWtleU5vZGVzVm90aW5nU3RhcnRIZWlnaHQBBQx2b3RpbmdOdW1TdHIFC3N0YXJ0SGVpZ2h0CQEMSW50ZWdlckVudHJ5AgkBF2tleU5vZGVzVm90aW5nRW5kSGVpZ2h0AQUMdm90aW5nTnVtU3RyBQllbmRIZWlnaHQBaQEKdm90ZUJ5Tm9kZQMObm9kZUFkZHJlc3NTdHIJdm90aW5nTnVtCW9wdGlvbk51bQQMdmFsaWRhdGVOb2RlCQEdcmVhZE5vZGVEYXRhQW5kVmFsaWRhdGVTdGF0dXMCBQ5ub2RlQWRkcmVzc1N0cgIIQVBQUk9WRUQDCQAAAgUMdmFsaWRhdGVOb2RlBQx2YWxpZGF0ZU5vZGUEC25vZGVBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQ5ub2RlQWRkcmVzc1N0cgQPbm9kZUJlbmVmaWNpYXJ5CQEPZ2V0U3RyaW5nT3JGYWlsAgULbm9kZUFkZHJlc3MJARVrZXlCZW5lZmljaWFyeUFkZHJlc3MABA92b3RlckFkZHJlc3NTdHIJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AgUPdm90ZXJBZGRyZXNzU3RyBQ9ub2RlQmVuZWZpY2lhcnkJAAIBAiVPbmx5IE5vZGUncyBiZW5lZmljaWFyeSBjYW4gZG8gdm90aW5nBAtzdGFydEhlaWdodAkBDGdldEludE9yRmFpbAEJARlrZXlOb2Rlc1ZvdGluZ1N0YXJ0SGVpZ2h0AQUJdm90aW5nTnVtBAllbmRIZWlnaHQJAQxnZXRJbnRPckZhaWwBCQEXa2V5Tm9kZXNWb3RpbmdFbmRIZWlnaHQBBQl2b3RpbmdOdW0DCQBmAgULc3RhcnRIZWlnaHQFBmhlaWdodAkAAgECH1ZvdGluZyBoYXMgbm90IGJlZW4gc3RhcnRlZCB5ZXQDCQBmAgUGaGVpZ2h0BQllbmRIZWlnaHQJAAIBAg9Wb3RpbmcgZmluaXNoZWQEDW5vZGVDaG9pY2VLRVkJARhrZXlOb2Rlc1ZvdGluZ05vZGVDaG9pY2UCBQl2b3RpbmdOdW0FDm5vZGVBZGRyZXNzU3RyBApub2RlQ2hvaWNlCQEMZ2V0U3RyT3JFbHNlAwUEdGhpcwUNbm9kZUNob2ljZUtFWQIAAwkBAiE9AgUKbm9kZUNob2ljZQIACQACAQI3Tm9kZSBoYXMgYWxyZWFkeSB2b3RlZC4gSXQgaXMgYWxsb3dlZCB0byB2b3RlIG9ubHkgb25jZQQTb3B0aW9uVG90YWxWb3Rlc0tFWQkBHmtleU5vZGVzVm90aW5nT3B0aW9uVG90YWxWb3RlcwIFCXZvdGluZ051bQUJb3B0aW9uTnVtBBBvcHRpb25Ub3RhbFZvdGVzCQEMZ2V0SW50T3JGYWlsAQUTb3B0aW9uVG90YWxWb3Rlc0tFWQkAzAgCCQEMSW50ZWdlckVudHJ5AgUTb3B0aW9uVG90YWxWb3Rlc0tFWQkAZAIFEG9wdGlvblRvdGFsVm90ZXMAAQkAzAgCCQELU3RyaW5nRW50cnkCBQ1ub2RlQ2hvaWNlS0VZBQlvcHRpb25OdW0FA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgBVFZdj", "chainId": 87, "height": 3638820, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: tyeGHVqBvsGEjbhFt1uvbbGpEBde22TJF4rmBrHLxWp Next: BptRuPzdmjjZB26fZErG8Kwog3Ha7XCpyJxoywxQaBn1 Diff:
OldNewDifferences
1212 let WAVESID = fromBase58String(WAVESIDSTR)
1313
1414 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
15+
16+
17+func getIntOrElse (key,val) = valueOrElse(getInteger(this, key), val)
1518
1619
1720 func getStrOrElse (address,key,defaultVal) = valueOrElse(getString(address, key), defaultVal)
9295
9396
9497 func keyBeneficiaryAddress () = "%s%s__cfg__beneficiaryAddress"
98+
99+
100+func keyNodesVotingNextNum () = "%s%s__nodesVotingCfg__nextVotingNum"
101+
102+
103+func keyNodesVotingOptionKey (votingNum,optionNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, optionNum], SEP)
104+
105+
106+func keyNodesVotingDesc (votingNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, "description"], SEP)
107+
108+
109+func keyNodesVotingStartHeight (votingNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, "votingStartHeight"], SEP)
110+
111+
112+func keyNodesVotingEndHeight (votingNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, "votingEndHeight"], SEP)
113+
114+
115+func keyNodesVotingOptionTotalVotes (votingNum,optionNum) = makeString(["%s%d%s%s__nodesVotingData", votingNum, "optionTotalVotes", optionNum], SEP)
116+
117+
118+func keyNodesVotingNodeChoice (votingNum,nodeAddressStr) = makeString(["%s%d%s%s__nodesVotingData", votingNum, "nodeChoice", nodeAddressStr], SEP)
95119
96120
97121 let IdxControlCfgNeutrinoDapp = 1
416440 }
417441
418442
443+
444+@Callable(i)
445+func initNodesVoting (startHeight,endHeight,options,description) = if ((i.caller != this))
446+ then throw("permissions denied")
447+ else {
448+ let optionsArray = split(options, "__")
449+ if ((size(optionsArray) > 10))
450+ then throw("Max 10 options can be specified")
451+ else {
452+ let nodesVotingNumKEY = keyNodesVotingNextNum()
453+ let votingNum = getIntOrElse(nodesVotingNumKEY, 0)
454+ let votingNumStr = toString(votingNum)
455+ func transformOptions (accum,nextOpt) = {
456+ let optData = split(nextOpt, ":")
457+ let opt = optData[0]
458+ let optKEY = keyNodesVotingOptionKey(votingNumStr, opt)
459+ let optDescr = optData[1]
460+ let optTotalVotesKEY = keyNodesVotingOptionTotalVotes(votingNumStr, opt)
461+ ((accum :+ StringEntry(optKEY, optDescr)) :+ IntegerEntry(optTotalVotesKEY, 0))
462+ }
463+
464+ (((({
465+ let $l = optionsArray
466+ let $s = size($l)
467+ let $acc0 = nil
468+ func $f0_1 ($a,$i) = if (($i >= $s))
469+ then $a
470+ else transformOptions($a, $l[$i])
471+
472+ func $f0_2 ($a,$i) = if (($i >= $s))
473+ then $a
474+ else throw("List size exceeds 10")
475+
476+ $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)
477+ } :+ IntegerEntry(nodesVotingNumKEY, (votingNum + 1))) :+ StringEntry(keyNodesVotingDesc(votingNumStr), description)) :+ IntegerEntry(keyNodesVotingStartHeight(votingNumStr), startHeight)) :+ IntegerEntry(keyNodesVotingEndHeight(votingNumStr), endHeight))
478+ }
479+ }
480+
481+
482+
483+@Callable(i)
484+func voteByNode (nodeAddressStr,votingNum,optionNum) = {
485+ let validateNode = readNodeDataAndValidateStatus(nodeAddressStr, "APPROVED")
486+ if ((validateNode == validateNode))
487+ then {
488+ let nodeAddress = addressFromStringValue(nodeAddressStr)
489+ let nodeBeneficiary = getStringOrFail(nodeAddress, keyBeneficiaryAddress())
490+ let voterAddressStr = toString(i.caller)
491+ if ((voterAddressStr != nodeBeneficiary))
492+ then throw("Only Node's beneficiary can do voting")
493+ else {
494+ let startHeight = getIntOrFail(keyNodesVotingStartHeight(votingNum))
495+ let endHeight = getIntOrFail(keyNodesVotingEndHeight(votingNum))
496+ if ((startHeight > height))
497+ then throw("Voting has not been started yet")
498+ else if ((height > endHeight))
499+ then throw("Voting finished")
500+ else {
501+ let nodeChoiceKEY = keyNodesVotingNodeChoice(votingNum, nodeAddressStr)
502+ let nodeChoice = getStrOrElse(this, nodeChoiceKEY, "")
503+ if ((nodeChoice != ""))
504+ then throw("Node has already voted. It is allowed to vote only once")
505+ else {
506+ let optionTotalVotesKEY = keyNodesVotingOptionTotalVotes(votingNum, optionNum)
507+ let optionTotalVotes = getIntOrFail(optionTotalVotesKEY)
508+[IntegerEntry(optionTotalVotesKEY, (optionTotalVotes + 1)), StringEntry(nodeChoiceKEY, optionNum)]
509+ }
510+ }
511+ }
512+ }
513+ else throw("Strict value is not equal to itself.")
514+ }
515+
516+
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
55
66 let MULT6 = 1000000
77
88 let MULT8 = 100000000
99
1010 let WAVESIDSTR = "WAVES"
1111
1212 let WAVESID = fromBase58String(WAVESIDSTR)
1313
1414 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
15+
16+
17+func getIntOrElse (key,val) = valueOrElse(getInteger(this, key), val)
1518
1619
1720 func getStrOrElse (address,key,defaultVal) = valueOrElse(getString(address, key), defaultVal)
1821
1922
2023 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (("Mandatory this." + key) + " is not defined"))
2124
2225
2326 func getAddressOrFail (key) = valueOrErrorMessage(addressFromString(getStringOrFail(this, key)), (("Fail to convert this." + key) + " value into Address"))
2427
2528
2629 func asAnyList (val) = match val {
2730 case valAnyList: List[Any] =>
2831 valAnyList
2932 case _ =>
3033 throw("fail to cast into List[Any]")
3134 }
3235
3336
3437 func asInt (v) = match v {
3538 case i: Int =>
3639 i
3740 case _ =>
3841 throw("fail to cast into Int")
3942 }
4043
4144
4245 func asByteVecot (v) = match v {
4346 case i: ByteVector =>
4447 i
4548 case _ =>
4649 throw("fail to cast into ByteVector")
4750 }
4851
4952
5053 func validateAddressOrFail (addressStr) = {
5154 let address = valueOrErrorMessage(addressFromString(addressStr), ("fail to convert into address " + addressStr))
5255 if ((0 > wavesBalance(address).available))
5356 then throw()
5457 else addressStr
5558 }
5659
5760
5861 func keyNodeRegistry (address) = ("%s__" + address)
5962
6063
6164 func keyNodeRewardsTotals (address) = ("%s%s__totals__" + address)
6265
6366
6467 func keyApprovedNodeList () = "%s__approvedNodeList"
6568
6669
6770 func keyDepositAmount () = "%s%s__cfg__depositAmount"
6871
6972
7073 func keyNeutrinoAddressStr () = "%s%s__cfg__neutrinoAddress"
7174
7275
7376 func keyMasterNodeAddressStr () = "%s%s__cfg__mainNeutrinoNodeAddress"
7477
7578
7679 func keyProtocolPartX6 () = "%s%s__cfg__protocolPartX6"
7780
7881
7982 func keyBenificaryPartX6 () = "%s%s__cfg__benificaryPartX6"
8083
8184
8285 func keyMinDistributeAmount () = "%s%s__cfg__minDistributeAmount"
8386
8487
8588 func keySwopfiUsdtUsdnPoolAddress () = "%s%s__cfg__swopfiUsdtUsdnPoolAddress"
8689
8790
8891 func keyWxSwapAddress () = "%s%s__cfg__wxSwapAddress"
8992
9093
9194 func keySavingsAddress () = "%s%s__cfg__savingsAddress"
9295
9396
9497 func keyBeneficiaryAddress () = "%s%s__cfg__beneficiaryAddress"
98+
99+
100+func keyNodesVotingNextNum () = "%s%s__nodesVotingCfg__nextVotingNum"
101+
102+
103+func keyNodesVotingOptionKey (votingNum,optionNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, optionNum], SEP)
104+
105+
106+func keyNodesVotingDesc (votingNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, "description"], SEP)
107+
108+
109+func keyNodesVotingStartHeight (votingNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, "votingStartHeight"], SEP)
110+
111+
112+func keyNodesVotingEndHeight (votingNum) = makeString(["%s%d%s__nodesVotingCfg", votingNum, "votingEndHeight"], SEP)
113+
114+
115+func keyNodesVotingOptionTotalVotes (votingNum,optionNum) = makeString(["%s%d%s%s__nodesVotingData", votingNum, "optionTotalVotes", optionNum], SEP)
116+
117+
118+func keyNodesVotingNodeChoice (votingNum,nodeAddressStr) = makeString(["%s%d%s%s__nodesVotingData", votingNum, "nodeChoice", nodeAddressStr], SEP)
95119
96120
97121 let IdxControlCfgNeutrinoDapp = 1
98122
99123 let IdxControlCfgAuctionDapp = 2
100124
101125 let IdxControlCfgRpdDapp = 3
102126
103127 let IdxControlCfgMathDapp = 4
104128
105129 let IdxControlCfgLiquidationDapp = 5
106130
107131 let IdxControlCfgRestDapp = 6
108132
109133 let IdxControlCfgNodeRegistryDapp = 7
110134
111135 let IdxControlCfgNsbtStakingDapp = 8
112136
113137 let IdxControlCfgMediatorDapp = 9
114138
115139 let IdxControlCfgSurfStakingDapp = 10
116140
117141 let IdxControlCfgGnsbtControllerDapp = 11
118142
119143 let IdxControlCfgRestV2Dapp = 12
120144
121145 let IdxControlCfgGovernanceDapp = 13
122146
123147 func keyControlAddress () = "%s%s__config__controlAddress"
124148
125149
126150 func keyControlCfg () = "%s__controlConfig"
127151
128152
129153 func keyUsdnAssetId () = "neutrino_asset_id"
130154
131155
132156 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
133157
134158
135159 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
136160
137161
138162 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
139163
140164 let controlCfg = readControlCfgOrFail(controlContract)
141165
142166 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
143167
144168 let usdnAssetIdStr = getStrOrElse(neutrinoContract, keyUsdnAssetId(), "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p")
145169
146170 let usdnAssetId = fromBase58String(usdnAssetIdStr)
147171
148172 let nRegIdxTxAdd = 1
149173
150174 let nRegIdxHeightAdd = 2
151175
152176 let nRegIdxTimeAdd = 3
153177
154178 let nRegIdxDepoAmt = 4
155179
156180 let nRegIdxDepoAmtLeft = 5
157181
158182 let nRegIdxStatus = 6
159183
160184 let nRegIdxStatusChangeHeight = 7
161185
162186 let nRegIdxStatusChangeTime = 8
163187
164188 func formatDepositAdd (txIdStr,depositAmount,remainingDepositAmount,status) = makeString(["%s%d%d%d%d%s%d%d", txIdStr, toString(lastBlock.height), toString(lastBlock.timestamp), toString(depositAmount), toString(remainingDepositAmount), status, "0", "0"], SEP)
165189
166190
167191 func formatDepositChangeStatus (origS,newStatus) = {
168192 let orig = split(origS, SEP)
169193 makeString(["%s%d%d%d%d%s%d%d", orig[nRegIdxTxAdd], orig[nRegIdxHeightAdd], orig[nRegIdxTimeAdd], orig[nRegIdxDepoAmt], orig[nRegIdxDepoAmtLeft], newStatus, toString(lastBlock.height), toString(lastBlock.timestamp)], SEP)
170194 }
171195
172196
173197 func keyRewardHistory (nodeAddress,txId) = makeString(["%s%s%s", "history", toString(nodeAddress), toBase58String(txId)], SEP)
174198
175199
176200 func dataRewardHistory (wavesAmountTotal,beneficiaryAmt,protocolAmt,protocolAmtPart1,protocolAmtPart2) = makeString(["%d%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(wavesAmountTotal), toString(beneficiaryAmt), toString(protocolAmt), toString(protocolAmtPart1), toString(protocolAmtPart2)], SEP)
177201
178202
179203 func RewardHistoryEntry (nodeAddress,txId,minedAmt,beneficiaryAmt,protocolAmt,protocolAmt1,protocolAmt2) = StringEntry(keyRewardHistory(nodeAddress, txId), dataRewardHistory(minedAmt, beneficiaryAmt, protocolAmt, protocolAmt1, protocolAmt2))
180204
181205
182206 func dataRewardTotals (minedAmt,beneficiaryAmt,protocolAmt,protocolAmtPart1,protocolAmtPart2) = makeString(["%d%d%d%d%d", toString(minedAmt), toString(beneficiaryAmt), toString(protocolAmt), toString(protocolAmtPart1), toString(protocolAmtPart2)], SEP)
183207
184208
185209 func RewardTotalsEntry (miner,minedAmt,beneficiaryAmt,protocolAmt,protocolAmtPart1,protocolAmtPart2) = {
186210 let nodeRewardsTotalsKEY = keyNodeRewardsTotals(toString(miner))
187211 let nodeRewardsArray = split(getStrOrElse(this, nodeRewardsTotalsKEY, dataRewardTotals(0, 0, 0, 0, 0)), SEP)
188212 let newMinedAmt = (parseIntValue(nodeRewardsArray[1]) + minedAmt)
189213 let newBeneficiaryAmt = (parseIntValue(nodeRewardsArray[2]) + beneficiaryAmt)
190214 let newProtocolAmt = (parseIntValue(nodeRewardsArray[3]) + protocolAmt)
191215 let newProtocolAmtPart1 = (parseIntValue(nodeRewardsArray[4]) + protocolAmtPart1)
192216 let newProtocolAmtPart2 = (parseIntValue(nodeRewardsArray[5]) + protocolAmtPart2)
193217 StringEntry(nodeRewardsTotalsKEY, dataRewardTotals(newMinedAmt, newBeneficiaryAmt, newProtocolAmt, newProtocolAmtPart1, newProtocolAmtPart2))
194218 }
195219
196220
197221 func resolveBeneficiaries (minerAddress,beneficiaryFromParam) = {
198222 let beneficiaryFromMinerState = addressFromStringValue(getStringOrFail(minerAddress, keyBeneficiaryAddress()))
199223 if ((scriptHash(minerAddress) == unit))
200224 then beneficiaryFromParam
201225 else beneficiaryFromMinerState
202226 }
203227
204228
205229 func readNodeDataAndValidateStatus (nodeAddr,expectedStatus) = {
206230 let nodeDataOpt = getString(keyNodeRegistry(nodeAddr))
207231 if (!(isDefined(nodeDataOpt)))
208232 then throw(("Unknown Node " + nodeAddr))
209233 else {
210234 let nodeDataStr = value(nodeDataOpt)
211235 let nodeData = split(nodeDataStr, SEP)
212236 let nodeStatus = if ((size(nodeData) >= 9))
213237 then nodeData[nRegIdxStatus]
214238 else "PENDING"
215239 if ((nodeStatus != expectedStatus))
216240 then throw(((((("Node " + nodeAddr) + " status should be ") + expectedStatus) + ", but actually ") + nodeStatus))
217241 else nodeDataStr
218242 }
219243 }
220244
221245
222246 @Callable(i)
223247 func constructorV1 (depositAmount,neutrinoAddressStr,masterNodeAddressStr,protocolPartX6,benificaryPartX6) = if ((i.caller != this))
224248 then throw("permissions denied")
225249 else if ((0 > depositAmount))
226250 then throw("depositAmount less then zero")
227251 else if ((0 > protocolPartX6))
228252 then throw("protocolPartX6 less then zero")
229253 else if ((0 > benificaryPartX6))
230254 then throw("benificaryPartX6 less then zero")
231255 else if (((protocolPartX6 + benificaryPartX6) != MULT6))
232256 then throw("parts sum must be 1")
233257 else [IntegerEntry(keyDepositAmount(), depositAmount), StringEntry(keyNeutrinoAddressStr(), validateAddressOrFail(neutrinoAddressStr)), StringEntry(keyMasterNodeAddressStr(), validateAddressOrFail(masterNodeAddressStr)), IntegerEntry(keyProtocolPartX6(), protocolPartX6), IntegerEntry(keyBenificaryPartX6(), benificaryPartX6)]
234258
235259
236260
237261 @Callable(i)
238262 func constructorV2 (swopfiAddressStr,controlAddressStr,savingsAddressStr) = if ((i.caller != this))
239263 then throw("permissions denied")
240264 else [StringEntry(keySwopfiUsdtUsdnPoolAddress(), validateAddressOrFail(swopfiAddressStr)), StringEntry(keyControlAddress(), validateAddressOrFail(controlAddressStr)), StringEntry(keySavingsAddress(), validateAddressOrFail(savingsAddressStr))]
241265
242266
243267
244268 @Callable(i)
245269 func sumbitApplication () = if ((size(i.payments) != 1))
246270 then throw("exact 1 payment must be attached")
247271 else if ((i.caller != i.originCaller))
248272 then throw("dapp to dapp calls are not allowed")
249273 else {
250274 let pmt = i.payments[0]
251275 let deposit = pmt.amount
252276 let pmtAssetId = valueOrElse(pmt.assetId, WAVESID)
253277 let expectedDepositAmount = getIntOrFail(keyDepositAmount())
254278 let txId = toBase58String(i.transactionId)
255279 let nodeAddress = toString(i.caller)
256280 let nodeRegistryKEY = keyNodeRegistry(nodeAddress)
257281 if ((pmtAssetId != WAVESID))
258282 then throw("only Waves can be used for deposit")
259283 else if ((deposit != expectedDepositAmount))
260284 then throw((("exactly " + toString(expectedDepositAmount)) + " Wavelets are expected"))
261285 else if ((getStrOrElse(this, nodeRegistryKEY, "") != ""))
262286 then throw("your node already registered")
263287 else [StringEntry(nodeRegistryKEY, formatDepositAdd(txId, deposit, deposit, "PENDING"))]
264288 }
265289
266290
267291
268292 @Callable(i)
269293 func distributeMinerReward (beneficiaryAddressStr) = {
270294 let minDistributeAmount = valueOrElse(getInteger(this, keyMinDistributeAmount()), (24 * MULT8))
271295 if ((size(i.payments) != 1))
272296 then throw("exact 1 payment must be attached")
273297 else if ((i.caller != i.originCaller))
274298 then throw("dapp to dapp calls are not allowed")
275299 else {
276300 let pmt = i.payments[0]
277301 let pmtAssetId = valueOrElse(pmt.assetId, WAVESID)
278302 let feeAmt = i.fee
279303 let feeAssetId = valueOrElse(i.feeAssetId, WAVESID)
280304 let callReward = (feeAmt * 3)
281305 let minedAmt = (pmt.amount - callReward)
282306 if ((pmt.amount != minDistributeAmount))
283307 then throw((("attached payment must be exact " + toString(minDistributeAmount)) + " Wavelets"))
284308 else if ((pmtAssetId != WAVESID))
285309 then throw("only Waves can be used in payment")
286310 else if ((feeAssetId != WAVESID))
287311 then throw("only Waves can be used in fees")
288312 else if ((feeAmt != ((5 * MULT8) / 1000)))
289313 then throw("fee amount couldn't exceed 0.005")
290314 else {
291315 let neutrinoAddress = getAddressOrFail(keyNeutrinoAddressStr())
292316 let masterNodeAddress = getAddressOrFail(keyMasterNodeAddressStr())
293317 let minerAddress = i.caller
294318 let beneficiaryFromParam = addressFromStringValue(beneficiaryAddressStr)
295319 let beneficiaryAddress = resolveBeneficiaries(minerAddress, beneficiaryFromParam)
296320 let txRewardReceiver = beneficiaryFromParam
297321 let protocolPart = getIntOrFail(keyProtocolPartX6())
298322 let beneficiaryPart = getIntOrFail(keyBenificaryPartX6())
299323 let beneficiaryAmt = fraction(minedAmt, beneficiaryPart, MULT6)
300324 let protocolAmt = (minedAmt - beneficiaryAmt)
301325 let buyBackAmt = (120 * MULT8)
302326 let savingsAddress = addressFromStringValue(getStrOrElse(this, keySavingsAddress(), "3PC7DBimauyKytx8tXhKo5u2ECb6FsndYKH"))
303327 let savingsAmt = asInt(invoke(savingsAddress, "withdraw", [buyBackAmt], nil))
304328 let wxAssetIdStr = "Atqv59EYzjFGuitKVnMRk6H8FukjoV3ktPorbEys25on"
305329 let wxSwapAddress = addressFromStringValue(getStrOrElse(this, keyWxSwapAddress(), "3P68zNiufsu1viZpu1aY3cdahRRKcvV5N93"))
306330 let swapResult = invoke(wxSwapAddress, "swap", [1, wxAssetIdStr, toString(neutrinoContract)], [AttachedPayment(unit, savingsAmt)])
307331 if ((swapResult == swapResult))
308332 then [ScriptTransfer(beneficiaryAddress, beneficiaryAmt, unit), ScriptTransfer(neutrinoContract, protocolAmt, unit), ScriptTransfer(txRewardReceiver, callReward, unit), RewardHistoryEntry(minerAddress, i.transactionId, minedAmt, beneficiaryAmt, protocolAmt, protocolAmt, 0), RewardTotalsEntry(minerAddress, minedAmt, beneficiaryAmt, protocolAmt, protocolAmt, 0)]
309333 else throw("Strict value is not equal to itself.")
310334 }
311335 }
312336 }
313337
314338
315339
316340 @Callable(i)
317341 func validateAndApproveLeasings (nListS) = {
318342 let nIdxs = [0, 1, 2, 3, 4, 5, 6, 7]
319343 let nList = split(nListS, SEP)
320344 let expectedCount = size(nIdxs)
321345 let neutrinoAddress = getAddressOrFail(keyNeutrinoAddressStr())
322346 if ((i.caller != neutrinoAddress))
323347 then throw("validateAndApproveLeasings not authorized")
324348 else if (((size(nList) % 2) != 0))
325349 then throw("Only even number of nodes is allowed")
326350 else if ((size(nList) != expectedCount))
327351 then throw((("Only " + toString(expectedCount)) + " of nodes' addresses can be passed"))
328352 else {
329353 func forEachNodeChangeStatus (acc,i) = {
330354 let nodeAddr = nList[i]
331355 let nodeDataStr = readNodeDataAndValidateStatus(nodeAddr, "PENDING")
332356 (acc :+ StringEntry(keyNodeRegistry(nodeAddr), formatDepositChangeStatus(nodeDataStr, "APPROVED")))
333357 }
334358
335359 let approvedNodesData = {
336360 let $l = nIdxs
337361 let $s = size($l)
338362 let $acc0 = nil
339363 func $f0_1 ($a,$i) = if (($i >= $s))
340364 then $a
341365 else forEachNodeChangeStatus($a, $l[$i])
342366
343367 func $f0_2 ($a,$i) = if (($i >= $s))
344368 then $a
345369 else throw("List size exceeds 8")
346370
347371 $f0_2($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)
348372 }
349373 $Tuple2(approvedNodesData, nil)
350374 }
351375 }
352376
353377
354378
355379 @Callable(i)
356380 func replaceApprovedNode (oldNodeAddrStr,newNodeAddrStr,groupNum,penaltyAmount) = if ((i.caller != neutrinoContract))
357381 then throw("permissions denied")
358382 else {
359383 let oldDataStr = readNodeDataAndValidateStatus(oldNodeAddrStr, "APPROVED")
360384 let newDataStr = readNodeDataAndValidateStatus(newNodeAddrStr, "PENDING")
361385 let approvedNodeListS = getStringOrFail(this, keyApprovedNodeList())
362386 if (!(contains(approvedNodeListS, oldNodeAddrStr)))
363387 then throw(("approvedNodeList does not contain " + oldNodeAddrStr))
364388 else {
365389 let updatedNodeListS = makeString_2C(split_4C(approvedNodeListS, oldNodeAddrStr), newNodeAddrStr)
366390 let oldNodeAddr = addressFromStringValue(oldNodeAddrStr)
367391 let beneficiaryAddress = resolveBeneficiaries(oldNodeAddr, oldNodeAddr)
368392 let depoAmount = parseIntValue(split(oldDataStr, SEP)[nRegIdxDepoAmt])
369393 let actions = [StringEntry(keyApprovedNodeList(), updatedNodeListS), DeleteEntry(keyNodeRegistry(oldNodeAddrStr)), StringEntry(keyNodeRegistry(newNodeAddrStr), formatDepositChangeStatus(newDataStr, "APPROVED"))]
370394 $Tuple2(if ((depoAmount > penaltyAmount))
371395 then (actions :+ ScriptTransfer(beneficiaryAddress, (depoAmount - penaltyAmount), unit))
372396 else actions, unit)
373397 }
374398 }
375399
376400
377401
378402 @Callable(i)
379403 func returnDeposit (nodeAddressStr) = if ((size(i.payments) != 0))
380404 then throw("No payments allowed")
381405 else {
382406 let callerAddress = i.caller
383407 let nodeRegistryKEY = keyNodeRegistry(nodeAddressStr)
384408 let nodeDataOpt = getString(this, nodeRegistryKEY)
385409 if (!(isDefined(nodeDataOpt)))
386410 then throw(("Address is not applied as neutrino node: " + nodeAddressStr))
387411 else {
388412 let approvedNodeList = getStringOrFail(this, keyApprovedNodeList())
389413 if (contains(approvedNodeList, nodeAddressStr))
390414 then throw("Impossible to return deposit from approved Node, please contact support team")
391415 else {
392416 let nodeData = split(value(nodeDataOpt), SEP)
393417 let status = if ((size(nodeData) >= 9))
394418 then nodeData[nRegIdxStatus]
395419 else "PENDING"
396420 if ((status != "PENDING"))
397421 then throw("Application status is not PENDING!")
398422 else {
399423 let depoAmount = parseIntValue(nodeData[nRegIdxDepoAmt])
400424 let nodeAddress = addressFromStringValue(nodeAddressStr)
401425 let beneficiaryAddress = resolveBeneficiaries(nodeAddress, nodeAddress)
402426 if (!(if (if ((callerAddress == this))
403427 then true
404428 else if ((beneficiaryAddress != nodeAddress))
405429 then (callerAddress == beneficiaryAddress)
406430 else false)
407431 then true
408432 else if ((beneficiaryAddress == nodeAddress))
409433 then (callerAddress == nodeAddress)
410434 else false))
411435 then throw("returnDeposit permissions denied")
412436 else [DeleteEntry(nodeRegistryKEY), ScriptTransfer(beneficiaryAddress, depoAmount, unit)]
413437 }
414438 }
415439 }
416440 }
417441
418442
443+
444+@Callable(i)
445+func initNodesVoting (startHeight,endHeight,options,description) = if ((i.caller != this))
446+ then throw("permissions denied")
447+ else {
448+ let optionsArray = split(options, "__")
449+ if ((size(optionsArray) > 10))
450+ then throw("Max 10 options can be specified")
451+ else {
452+ let nodesVotingNumKEY = keyNodesVotingNextNum()
453+ let votingNum = getIntOrElse(nodesVotingNumKEY, 0)
454+ let votingNumStr = toString(votingNum)
455+ func transformOptions (accum,nextOpt) = {
456+ let optData = split(nextOpt, ":")
457+ let opt = optData[0]
458+ let optKEY = keyNodesVotingOptionKey(votingNumStr, opt)
459+ let optDescr = optData[1]
460+ let optTotalVotesKEY = keyNodesVotingOptionTotalVotes(votingNumStr, opt)
461+ ((accum :+ StringEntry(optKEY, optDescr)) :+ IntegerEntry(optTotalVotesKEY, 0))
462+ }
463+
464+ (((({
465+ let $l = optionsArray
466+ let $s = size($l)
467+ let $acc0 = nil
468+ func $f0_1 ($a,$i) = if (($i >= $s))
469+ then $a
470+ else transformOptions($a, $l[$i])
471+
472+ func $f0_2 ($a,$i) = if (($i >= $s))
473+ then $a
474+ else throw("List size exceeds 10")
475+
476+ $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)
477+ } :+ IntegerEntry(nodesVotingNumKEY, (votingNum + 1))) :+ StringEntry(keyNodesVotingDesc(votingNumStr), description)) :+ IntegerEntry(keyNodesVotingStartHeight(votingNumStr), startHeight)) :+ IntegerEntry(keyNodesVotingEndHeight(votingNumStr), endHeight))
478+ }
479+ }
480+
481+
482+
483+@Callable(i)
484+func voteByNode (nodeAddressStr,votingNum,optionNum) = {
485+ let validateNode = readNodeDataAndValidateStatus(nodeAddressStr, "APPROVED")
486+ if ((validateNode == validateNode))
487+ then {
488+ let nodeAddress = addressFromStringValue(nodeAddressStr)
489+ let nodeBeneficiary = getStringOrFail(nodeAddress, keyBeneficiaryAddress())
490+ let voterAddressStr = toString(i.caller)
491+ if ((voterAddressStr != nodeBeneficiary))
492+ then throw("Only Node's beneficiary can do voting")
493+ else {
494+ let startHeight = getIntOrFail(keyNodesVotingStartHeight(votingNum))
495+ let endHeight = getIntOrFail(keyNodesVotingEndHeight(votingNum))
496+ if ((startHeight > height))
497+ then throw("Voting has not been started yet")
498+ else if ((height > endHeight))
499+ then throw("Voting finished")
500+ else {
501+ let nodeChoiceKEY = keyNodesVotingNodeChoice(votingNum, nodeAddressStr)
502+ let nodeChoice = getStrOrElse(this, nodeChoiceKEY, "")
503+ if ((nodeChoice != ""))
504+ then throw("Node has already voted. It is allowed to vote only once")
505+ else {
506+ let optionTotalVotesKEY = keyNodesVotingOptionTotalVotes(votingNum, optionNum)
507+ let optionTotalVotes = getIntOrFail(optionTotalVotesKEY)
508+[IntegerEntry(optionTotalVotesKEY, (optionTotalVotes + 1)), StringEntry(nodeChoiceKEY, optionNum)]
509+ }
510+ }
511+ }
512+ }
513+ else throw("Strict value is not equal to itself.")
514+ }
515+
516+

github/deemru/w8io/786bc32 
68.51 ms