2022.08.08 15:18 [3240990] smart account 3PJL8Hn8LACaSBWLQ3UVhctA5cTQLBFwBAP > SELF 0.00000000 Waves

{ "type": 13, "id": "CDESBv3CLktXtYjtxxnU3e2t48hkh3EkuK7Jbyhg3aJa", "fee": 3000000, "feeAssetId": null, "timestamp": 1659959780137, "version": 1, "sender": "3PJL8Hn8LACaSBWLQ3UVhctA5cTQLBFwBAP", "senderPublicKey": "6PdA345SW1zresPEKuWiLPsh9Ku14mFDW6cZtpCQrp3E", "proofs": [ "2ii3DBen7VTzRavvfog413AyEZxhPLKVE4LVLwLWSSWtFxgcwhPeK5q42VRp6S7YuB7cbxFPZ63ayDRKoA7z3o8R" ], "script": "base64:BgJACAISCAoGCAgBAQEIEgUKAwEIAhIDCgEBEgMKAQESBAoCCAgSBAoCCAgSAwoBCBIDCgEIEgQKAggBEgMKAQgSAGwAA1NFUAICX18ABlNDQUxFOAAIAAVNVUxUOACAwtcvAA5QT09MV0VJR0hUTVVMVAUFTVVMVDgBBHN0cmYCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQCsAgIJAKwCAgIPbWFuZGF0b3J5IHRoaXMuBQNrZXkCDyBpcyBub3QgZGVmaW5lZAEDaW96AgdhZGRyZXNzA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQdhZGRyZXNzBQNrZXkAAAEDaW9kAwdhZGRyZXNzA2tleQpkZWZhdWx0VmFsCQELdmFsdWVPckVsc2UCCQCaCAIFB2FkZHJlc3MFA2tleQUKZGVmYXVsdFZhbAEDaW9mAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFB2FkZHJlc3MFA2tleQkArAICCQCsAgICD21hbmRhdG9yeSB0aGlzLgUDa2V5Ag8gaXMgbm90IGRlZmluZWQBA2FicwEDdmFsAwkAZgIAAAUDdmFsCQEBLQEFA3ZhbAUDdmFsAQNhYWwBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACCUxpc3RbQW55XQQKdmFsQW55THlzdAUHJG1hdGNoMAUKdmFsQW55THlzdAkAAgECG2ZhaWwgdG8gY2FzdCBpbnRvIExpc3RbQW55XQECYWkBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACA0ludAQGdmFsSW50BQckbWF0Y2gwBQZ2YWxJbnQJAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBG2tleVJlZmVycmFsc0NvbnRyYWN0QWRkcmVzcwAJALkJAgkAzAgCAgQlcyVzCQDMCAICBmNvbmZpZwkAzAgCAhhyZWZlcnJhbHNDb250cmFjdEFkZHJlc3MFA25pbAUDU0VQAB5yZWZlcnJhbHNDb250cmFjdEFkZHJlc3NPckZhaWwJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQRzdHJmAgUEdGhpcwkBG2tleVJlZmVycmFsc0NvbnRyYWN0QWRkcmVzcwAAFmtleVJlZmVycmFsUHJvZ3JhbU5hbWUJALkJAgkAzAgCAgQlcyVzCQDMCAICCHJlZmVycmFsCQDMCAICC3Byb2dyYW1OYW1lBQNuaWwFA1NFUAAacmVmZXJyYWxQcm9ncmFtTmFtZURlZmF1bHQCBnd4bG9jawATcmVmZXJyYWxQcm9ncmFtTmFtZQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBRZrZXlSZWZlcnJhbFByb2dyYW1OYW1lBRpyZWZlcnJhbFByb2dyYW1OYW1lRGVmYXVsdAERa2V5RmFjdG9yeUFkZHJlc3MAAhwlcyVzX19jb25maWdfX2ZhY3RvcnlBZGRyZXNzABhJZHhGYWN0b3J5Q2ZnU3Rha2luZ0RhcHAAAQAZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcAACABRJZHhGYWN0b3J5Q2ZnSWRvRGFwcAADABVJZHhGYWN0b3J5Q2ZnVGVhbURhcHAABAAZSWR4RmFjdG9yeUNmZ0VtaXNzaW9uRGFwcAAFABVJZHhGYWN0b3J5Q2ZnUmVzdERhcHAABgAZSWR4RmFjdG9yeUNmZ1NsaXBwYWdlRGFwcAAHABRJZHhGYWN0b3J5Q2ZnRGFvRGFwcAAIABpJZHhGYWN0b3J5Q2ZnTWFya2V0aW5nRGFwcAAJABpJZHhGYWN0b3J5Q2ZnR3d4UmV3YXJkRGFwcAAKABZJZHhGYWN0b3J5Q2ZnQmlyZHNEYXBwAAsBDWtleUZhY3RvcnlDZmcAAhElc19fZmFjdG9yeUNvbmZpZwEaa2V5RmFjdG9yeUxwMkFzc2V0c01hcHBpbmcBCmxwQXNzZXRTdHIJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUKbHBBc3NldFN0cgkAzAgCAh5tYXBwaW5nc19fbHBBc3NldDJQb29sQ29udHJhY3QFA25pbAUDU0VQARBrZXlGYWN0b3J5THBMaXN0AAIQJXNfX2xwVG9rZW5zTGlzdAEma2V5RmFjdG9yeUxwQXNzZXRUb1Bvb2xDb250cmFjdEFkZHJlc3MBCmxwQXNzZXRTdHIJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgUKbHBBc3NldFN0cgkAzAgCAh5tYXBwaW5nc19fbHBBc3NldDJQb29sQ29udHJhY3QFA25pbAUDU0VQARRrZXlGYWN0b3J5UG9vbFdlaWdodAEPY29udHJhY3RBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAgpwb29sV2VpZ2h0CQDMCAIFD2NvbnRyYWN0QWRkcmVzcwUDbmlsBQNTRVABG2tleUZhY3RvcnlQb29sV2VpZ2h0SGlzdG9yeQILcG9vbEFkZHJlc3MDbnVtCQCsAgIJAKwCAgkArAICAhIlcyVzX19wb29sV2VpZ2h0X18FC3Bvb2xBZGRyZXNzAgJfXwkApAMBBQNudW0BGHJlYWRGYWN0b3J5QWRkcmVzc09yRmFpbAAJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQRzdHJmAgUEdGhpcwkBEWtleUZhY3RvcnlBZGRyZXNzAAEKcmVhZExwTGlzdAAJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCCQEYcmVhZEZhY3RvcnlBZGRyZXNzT3JGYWlsAAkBEGtleUZhY3RvcnlMcExpc3QAAgAFA1NFUAEUcmVhZEZhY3RvcnlDZmdPckZhaWwBB2ZhY3RvcnkJALUJAgkBBHN0cmYCBQdmYWN0b3J5CQENa2V5RmFjdG9yeUNmZwAFA1NFUAEYZ2V0Qm9vc3RpbmdBZGRyZXNzT3JGYWlsAQpmYWN0b3J5Q2ZnCQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFCmZhY3RvcnlDZmcFGUlkeEZhY3RvcnlDZmdCb29zdGluZ0RhcHABGGdldEVtaXNzaW9uQWRkcmVzc09yRmFpbAEKZmFjdG9yeUNmZwkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQpmYWN0b3J5Q2ZnBRlJZHhGYWN0b3J5Q2ZnRW1pc3Npb25EYXBwARdnZXRTdGFraW5nQWRkcmVzc09yRmFpbAEKZmFjdG9yeUNmZwkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQpmYWN0b3J5Q2ZnBRhJZHhGYWN0b3J5Q2ZnU3Rha2luZ0RhcHABGWdldEd3eFJld2FyZEFkZHJlc3NPckZhaWwBCmZhY3RvcnlDZmcJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUKZmFjdG9yeUNmZwUaSWR4RmFjdG9yeUNmZ0d3eFJld2FyZERhcHABE2tleU1hbmFnZXJQdWJsaWNLZXkAAhQlc19fbWFuYWdlclB1YmxpY0tleQEaa2V5UGVuZGluZ01hbmFnZXJQdWJsaWNLZXkAAhslc19fcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkBHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudAACGyVzJXNfX3JhdGVQZXJCbG9ja19fY3VycmVudAEha2V5RW1pc3Npb25SYXRlUGVyQmxvY2tNYXhDdXJyZW50AAIeJXMlc19fcmF0ZVBlckJsb2NrTWF4X19jdXJyZW50ARVrZXlFbWlzc2lvblN0YXJ0QmxvY2sAAholcyVzX19lbWlzc2lvbl9fc3RhcnRCbG9jawEba2V5RW1pc3Npb25EdXJhdGlvbkluQmxvY2tzAAIYJXMlc19fZW1pc3Npb25fX2R1cmF0aW9uARNrZXlFbWlzc2lvbkVuZEJsb2NrAAIYJXMlc19fZW1pc3Npb25fX2VuZEJsb2NrAQ1rZXlOZXh0UGVyaW9kAAIOJXNfX25leHRQZXJpb2QBH2tleUd3eFJld2FyZEVtaXNzaW9uU3RhcnRIZWlnaHQAAiglcyVzX19nd3hSZXdhcmRFbWlzc2lvblBhcnRfX3N0YXJ0SGVpZ2h0AA1JZHhDZmdBc3NldElkAAEAE0lkeENmZ01pbkxvY2tBbW91bnQAAgAVSWR4Q2ZnTWluTG9ja0R1cmF0aW9uAAMAFUlkeENmZ01heExvY2tEdXJhdGlvbgAEABJJZHhDZmdNYXRoQ29udHJhY3QABQEJa2V5Q29uZmlnAAIKJXNfX2NvbmZpZwEVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAkAtQkCCQEEc3RyZgIFBHRoaXMJAQlrZXlDb25maWcABQNTRVAADG1hdGhDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCCQEVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAUSSWR4Q2ZnTWF0aENvbnRyYWN0AQ1mb3JtYXRDb25maWdTBQdhc3NldElkDW1pbkxvY2tBbW91bnQPbWluTG9ja0R1cmF0aW9uD21heExvY2tEdXJhdGlvbgxtYXRoQ29udHJhY3QJALkJAgkAzAgCAgglcyVkJWQlZAkAzAgCBQdhc3NldElkCQDMCAIFDW1pbkxvY2tBbW91bnQJAMwIAgUPbWluTG9ja0R1cmF0aW9uCQDMCAIFD21heExvY2tEdXJhdGlvbgkAzAgCBQxtYXRoQ29udHJhY3QFA25pbAUDU0VQAQxmb3JtYXRDb25maWcFB2Fzc2V0SWQNbWluTG9ja0Ftb3VudA9taW5Mb2NrRHVyYXRpb24PbWF4TG9ja0R1cmF0aW9uDG1hdGhDb250cmFjdAkBDWZvcm1hdENvbmZpZ1MFBQdhc3NldElkCQCkAwEFDW1pbkxvY2tBbW91bnQJAKQDAQUPbWluTG9ja0R1cmF0aW9uCQCkAwEFD21heExvY2tEdXJhdGlvbgUMbWF0aENvbnRyYWN0ARZtYW5hZ2VyUHVibGljS2V5T3JVbml0AAQHJG1hdGNoMAkAoggBCQETa2V5TWFuYWdlclB1YmxpY0tleQADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQDZBAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAR1wZW5kaW5nTWFuYWdlclB1YmxpY0tleU9yVW5pdAAEByRtYXRjaDAJAKIIAQkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJANkEAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IBC211c3RNYW5hZ2VyAQFpBAJwZAkAAgECEVBlcm1pc3Npb24gZGVuaWVkBAckbWF0Y2gwCQEWbWFuYWdlclB1YmxpY0tleU9yVW5pdAADCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCcGsFByRtYXRjaDADCQAAAggFAWkPY2FsbGVyUHVibGljS2V5BQJwawYFAnBkAwkAAQIFByRtYXRjaDACBFVuaXQDCQAAAggFAWkGY2FsbGVyBQR0aGlzBgUCcGQJAAIBAgtNYXRjaCBlcnJvcgAOSWR4TG9ja1VzZXJOdW0AAQANSWR4TG9ja0Ftb3VudAACAAxJZHhMb2NrU3RhcnQAAwAPSWR4TG9ja0R1cmF0aW9uAAQADUlkeExvY2tQYXJhbUsABQANSWR4TG9ja1BhcmFtQgAGARNrZXlMb2NrUGFyYW1zUmVjb3JkAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICCiVzJXNfX2xvY2sJAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARpyZWFkTG9ja1BhcmFtc1JlY29yZE9yRmFpbAELdXNlckFkZHJlc3MJALUJAgkBBHN0cmYCBQR0aGlzCQETa2V5TG9ja1BhcmFtc1JlY29yZAEFC3VzZXJBZGRyZXNzBQNTRVABF2Zvcm1hdExvY2tQYXJhbXNSZWNvcmRTCAd1c2VyTnVtBmFtb3VudAVzdGFydAhkdXJhdGlvbgZwYXJhbUsGcGFyYW1CEGxhc3RVcGRUaW1lc3RhbXAJZ3d4QW1vdW50CQC5CQIJAMwIAgIQJWQlZCVkJWQlZCVkJWQlZAkAzAgCBQd1c2VyTnVtCQDMCAIFBmFtb3VudAkAzAgCBQVzdGFydAkAzAgCBQhkdXJhdGlvbgkAzAgCBQZwYXJhbUsJAMwIAgUGcGFyYW1CCQDMCAIFEGxhc3RVcGRUaW1lc3RhbXAJAMwIAgUJZ3d4QW1vdW50BQNuaWwFA1NFUAEWZm9ybWF0TG9ja1BhcmFtc1JlY29yZAcHdXNlck51bQZhbW91bnQFc3RhcnQIZHVyYXRpb24GcGFyYW1LBnBhcmFtQglnd3hBbW91bnQJARdmb3JtYXRMb2NrUGFyYW1zUmVjb3JkUwgFB3VzZXJOdW0JAKQDAQUGYW1vdW50CQCkAwEFBXN0YXJ0CQCkAwEFCGR1cmF0aW9uCQCkAwEFBnBhcmFtSwkApAMBBQZwYXJhbUIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAKQDAQUJZ3d4QW1vdW50AQ5rZXlOZXh0VXNlck51bQACDyVzX19uZXh0VXNlck51bQESa2V5VXNlcjJOdW1NYXBwaW5nAQt1c2VyQWRkcmVzcwkAuQkCCQDMCAICGSVzJXMlc19fbWFwcGluZ19fdXNlcjJudW0JAMwIAgULdXNlckFkZHJlc3MFA25pbAUDU0VQARJrZXlOdW0yVXNlck1hcHBpbmcBA251bQkAuQkCCQDMCAICGSVzJXMlc19fbWFwcGluZ19fbnVtMnVzZXIJAMwIAgUDbnVtBQNuaWwFA1NFUAEWa2V5TG9ja1BhcmFtVXNlckFtb3VudAEHdXNlck51bQkAuQkCCQDMCAICFiVzJWQlc19fcGFyYW1CeVVzZXJOdW0JAMwIAgUHdXNlck51bQkAzAgCAgZhbW91bnQFA25pbAUDU0VQARZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAQd1c2VyTnVtCQC5CQIJAMwIAgIWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkAzAgCBQd1c2VyTnVtCQDMCAICBXN0YXJ0BQNuaWwFA1NFUAEUa2V5TG9ja1BhcmFtRHVyYXRpb24BB3VzZXJOdW0JALkJAgkAzAgCAhYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQDMCAIFB3VzZXJOdW0JAMwIAgIIZHVyYXRpb24FA25pbAUDU0VQAQ1rZXlMb2NrUGFyYW1LAQd1c2VyTnVtCQC5CQIJAMwIAgIWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkAzAgCBQd1c2VyTnVtCQDMCAICAWsFA25pbAUDU0VQAQ1rZXlMb2NrUGFyYW1CAQd1c2VyTnVtCQC5CQIJAMwIAgIWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkAzAgCBQd1c2VyTnVtCQDMCAICAWIFA25pbAUDU0VQARVrZXlMb2NrUGFyYW1CeVBlcmlvZEsCB3VzZXJOdW0GcGVyaW9kCQC5CQIJAMwIAgIXJXMlZCVzJWRfX3BhcmFtQnlQZXJpb2QJAMwIAgUHdXNlck51bQkAzAgCAgFrCQDMCAIFBnBlcmlvZAUDbmlsBQNTRVABFWtleUxvY2tQYXJhbUJ5UGVyaW9kQgIHdXNlck51bQZwZXJpb2QJALkJAgkAzAgCAhclcyVkJXMlZF9fcGFyYW1CeVBlcmlvZAkAzAgCBQd1c2VyTnVtCQDMCAICAWIJAMwIAgUGcGVyaW9kBQNuaWwFA1NFUAEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAh4lcyVzX19zdGF0c19fYWN0aXZlVG90YWxMb2NrZWQBIGtleVN0YXRzTG9ja3NEdXJhdGlvblN1bUluQmxvY2tzAAIlJXMlc19fc3RhdHNfX2xvY2tzRHVyYXRpb25TdW1JbkJsb2NrcwESa2V5U3RhdHNMb2Nrc0NvdW50AAIXJXMlc19fc3RhdHNfX2xvY2tzQ291bnQBEmtleVN0YXRzVXNlcnNDb3VudAACHSVzJXNfX3N0YXRzX19hY3RpdmVVc2Vyc0NvdW50ASBrZXlVc2VyQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTAEHdXNlck51bQkAuQkCCQDMCAICHiVzJWRfX3VzZXJCb29zdEVtaXNzaW9uTGFzdEludAkAzAgCBQd1c2VyTnVtBQNuaWwFA1NFUAEia2V5VXNlckxwQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTAIHdXNlck51bQlscEFzc2V0SWQJALkJAgkAzAgCAh4lcyVkX191c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnQJAMwIAgUHdXNlck51bQkAzAgCBQlscEFzc2V0SWQFA25pbAUDU0VQARdrZXlVc2VyTWF4Qm9vc3RJTlRFR1JBTAEHdXNlck51bQkAuQkCCQDMCAICESVzJWRfX21heEJvb3N0SW50CQDMCAIFB3VzZXJOdW0FA25pbAUDU0VQARhrZXlUb3RhbE1heEJvb3N0SU5URUdSQUwAAhglcyVzX19tYXhCb29zdEludF9fdG90YWwBIWtleVVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbAEHdXNlck51bQkAuQkCCQDMCAICJCVzJWRfX3VzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbAkAzAgCBQd1c2VyTnVtBQNuaWwFA1NFUAETa2V5VXNlckJvb3N0Q2xhaW1lZAEHdXNlck51bQkAuQkCCQDMCAICFiVzJWRfX3VzZXJCb29zdENsYWltZWQJAMwIAgUHdXNlck51bQUDbmlsBQNTRVABEWtleVRvdGFsQ2FjaGVkR3d4AAIWJXMlc19fZ3d4Q2FjaGVkX190b3RhbAAPZmFjdG9yeUNvbnRyYWN0CQEYcmVhZEZhY3RvcnlBZGRyZXNzT3JGYWlsAAAKZmFjdG9yeUNmZwkBFHJlYWRGYWN0b3J5Q2ZnT3JGYWlsAQUPZmFjdG9yeUNvbnRyYWN0ABBlbWlzc2lvbkNvbnRyYWN0CQEYZ2V0RW1pc3Npb25BZGRyZXNzT3JGYWlsAQUKZmFjdG9yeUNmZwAPc3Rha2luZ0NvbnRyYWN0CQEXZ2V0U3Rha2luZ0FkZHJlc3NPckZhaWwBBQpmYWN0b3J5Q2ZnABFnd3hSZXdhcmRDb250cmFjdAkBGWdldEd3eFJld2FyZEFkZHJlc3NPckZhaWwBBQpmYWN0b3J5Q2ZnAQxIaXN0b3J5RW50cnkIBHR5cGUEdXNlcgZhbW91bnQJbG9ja1N0YXJ0CGR1cmF0aW9uAWsBYgFpBApoaXN0b3J5S0VZCQC5CQIJAMwIAgIRJXMlcyVzJXNfX2hpc3RvcnkJAMwIAgUEdHlwZQkAzAgCBQR1c2VyCQDMCAIJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAUDbmlsBQNTRVAEC2hpc3RvcnlEQVRBCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUGYW1vdW50CQDMCAIJAKQDAQUJbG9ja1N0YXJ0CQDMCAIJAKQDAQUIZHVyYXRpb24JAMwIAgkApAMBBQFrCQDMCAIJAKQDAQUBYgUDbmlsBQNTRVAJAQtTdHJpbmdFbnRyeQIFCmhpc3RvcnlLRVkFC2hpc3RvcnlEQVRBAQpTdGF0c0VudHJ5BA50b3RhbExvY2tlZEluYwtkdXJhdGlvbkluYwxsb2NrQ291bnRJbmMNdXNlcnNDb3VudEluYwQbbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzS0VZCQEga2V5U3RhdHNMb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3MABA1sb2Nrc0NvdW50S0VZCQESa2V5U3RhdHNMb2Nrc0NvdW50AAQNdXNlcnNDb3VudEtFWQkBEmtleVN0YXRzVXNlcnNDb3VudAAEDnRvdGFsQW1vdW50S0VZCQEXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQABBhsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3MJAQNpb3oCBQR0aGlzBRtsb2Nrc0R1cmF0aW9uU3VtSW5CbG9ja3NLRVkECmxvY2tzQ291bnQJAQNpb3oCBQR0aGlzBQ1sb2Nrc0NvdW50S0VZBAp1c2Vyc0NvdW50CQEDaW96AgUEdGhpcwUNdXNlcnNDb3VudEtFWQQLdG90YWxBbW91bnQJAQNpb3oCBQR0aGlzBQ50b3RhbEFtb3VudEtFWQkAzAgCCQEMSW50ZWdlckVudHJ5AgUbbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzS0VZCQBkAgUYbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzBQtkdXJhdGlvbkluYwkAzAgCCQEMSW50ZWdlckVudHJ5AgUNbG9ja3NDb3VudEtFWQkAZAIFCmxvY2tzQ291bnQFDGxvY2tDb3VudEluYwkAzAgCCQEMSW50ZWdlckVudHJ5AgUNdXNlcnNDb3VudEtFWQkAZAIFCnVzZXJzQ291bnQFDXVzZXJzQ291bnRJbmMJAMwIAgkBDEludGVnZXJFbnRyeQIFDnRvdGFsQW1vdW50S0VZCQBkAgULdG90YWxBbW91bnQFDnRvdGFsTG9ja2VkSW5jBQNuaWwBDWNhbGNHd3hBbW91bnQDBGtSYXcEYlJhdwFoBAVTQ0FMRQDoBwkAaQIJAGQCCQBoAgUEa1JhdwUBaAUEYlJhdwUFU0NBTEUBD0xvY2tQYXJhbXNFbnRyeQgLdXNlckFkZHJlc3MHdXNlck51bQZhbW91bnQFc3RhcnQIZHVyYXRpb24BawFiBnBlcmlvZAQNdXNlckFtb3VudEtFWQkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBBQd1c2VyTnVtBA1zdGFydEJsb2NrS0VZCQEWa2V5TG9ja1BhcmFtU3RhcnRCbG9jawEFB3VzZXJOdW0EC2R1cmF0aW9uS0VZCQEUa2V5TG9ja1BhcmFtRHVyYXRpb24BBQd1c2VyTnVtBARrS0VZCQENa2V5TG9ja1BhcmFtSwEFB3VzZXJOdW0EBGJLRVkJAQ1rZXlMb2NrUGFyYW1CAQUHdXNlck51bQQMa0J5UGVyaW9kS0VZCQEVa2V5TG9ja1BhcmFtQnlQZXJpb2RLAgUHdXNlck51bQUGcGVyaW9kBAxiQnlQZXJpb2RLRVkJARVrZXlMb2NrUGFyYW1CeVBlcmlvZEICBQd1c2VyTnVtBQZwZXJpb2QECWd3eEFtb3VudAkBDWNhbGNHd3hBbW91bnQDBQFrBQFiBQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIFDXVzZXJBbW91bnRLRVkFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUNc3RhcnRCbG9ja0tFWQUFc3RhcnQJAMwIAgkBDEludGVnZXJFbnRyeQIFC2R1cmF0aW9uS0VZBQhkdXJhdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgUEa0tFWQUBawkAzAgCCQEMSW50ZWdlckVudHJ5AgUEYktFWQUBYgkAzAgCCQEMSW50ZWdlckVudHJ5AgUMa0J5UGVyaW9kS0VZBQFrCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQxiQnlQZXJpb2RLRVkFAWIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleUxvY2tQYXJhbXNSZWNvcmQBBQt1c2VyQWRkcmVzcwkBFmZvcm1hdExvY2tQYXJhbXNSZWNvcmQHBQd1c2VyTnVtBQZhbW91bnQFBXN0YXJ0BQhkdXJhdGlvbgUBawUBYgUJZ3d4QW1vdW50BQNuaWwBImV4dHJhY3RPcHRpb25hbFBheW1lbnRBbW91bnRPckZhaWwCAWkPZXhwZWN0ZWRBc3NldElkAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECG29ubHkgb25lIHBheW1lbnQgaXMgYWxsb3dlZAMJAAACCQCQAwEIBQFpCHBheW1lbnRzAAAAAAQDcG10CQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQFD2V4cGVjdGVkQXNzZXRJZAkAAgECG2ludmFsaWQgYXNzZXQgaWQgaW4gcGF5bWVudAgFA3BtdAZhbW91bnQBGWNhbGNVc2VyR3d4QW1vdW50QXRIZWlnaHQCC3VzZXJBZGRyZXNzDHRhcmdldEhlaWdodAQFRU1QVFkCBWVtcHR5BBJ1c2VyMk51bU1hcHBpbmdLRVkJARJrZXlVc2VyMk51bU1hcHBpbmcBBQt1c2VyQWRkcmVzcwQHdXNlck51bQkBC3ZhbHVlT3JFbHNlAgkAoggBBRJ1c2VyMk51bU1hcHBpbmdLRVkFBUVNUFRZBAFrCQELdmFsdWVPckVsc2UCCQCfCAEJAQ1rZXlMb2NrUGFyYW1LAQUHdXNlck51bQAABAFiCQELdmFsdWVPckVsc2UCCQCfCAEJAQ1rZXlMb2NrUGFyYW1CAQUHdXNlck51bQAABA1nd3hBbW91bnRDYWxjCQENY2FsY0d3eEFtb3VudAMFAWsFAWIFDHRhcmdldEhlaWdodAQJZ3d4QW1vdW50AwkAZgIAAAUNZ3d4QW1vdW50Q2FsYwAABQ1nd3hBbW91bnRDYWxjBQlnd3hBbW91bnQBFGNhbGNDdXJyZW50R3d4QW1vdW50AQt1c2VyQWRkcmVzcwkBGWNhbGNVc2VyR3d4QW1vdW50QXRIZWlnaHQCBQt1c2VyQWRkcmVzcwUGaGVpZ2h0ARRpbnRlcm5hbENsYWltV3hCb29zdAMMbHBBc3NldElkU3RyDnVzZXJBZGRyZXNzU3RyCHJlYWRPbmx5BAVFTVBUWQIFRU1QVFkEEXVzZXJSZWNvcmRPckVtcHR5CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJARNrZXlMb2NrUGFyYW1zUmVjb3JkAQUOdXNlckFkZHJlc3NTdHIFBUVNUFRZAwkAAAIFEXVzZXJSZWNvcmRPckVtcHR5BQVFTVBUWQkAlQoDAAAFA25pbAIVdXNlclJlY29yZDo6aXM6OmVtcHR5BA91c2VyUmVjb3JkQXJyYXkJALUJAgURdXNlclJlY29yZE9yRW1wdHkFA1NFUAQKdXNlck51bVN0cgkAkQMCBQ91c2VyUmVjb3JkQXJyYXkFDklkeExvY2tVc2VyTnVtBBxnd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0CQELdmFsdWVPckVsc2UCCQCaCAIFEWd3eFJld2FyZENvbnRyYWN0CQEfa2V5R3d4UmV3YXJkRW1pc3Npb25TdGFydEhlaWdodAAAAAQIRU1QVFlTVFICBWVtcHR5BA0kdDAxMzk1ODE0NTI2AwkBAiE9AgUMbHBBc3NldElkU3RyBQhFTVBUWVNUUgQOcG9vbEFkZHJlc3NTdHIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ9mYWN0b3J5Q29udHJhY3QJARprZXlGYWN0b3J5THAyQXNzZXRzTWFwcGluZwEFDGxwQXNzZXRJZFN0cgkArAICAhV1bnN1cHBvcnRlZCBscCBhc3NldCAFDGxwQXNzZXRJZFN0cgQDcHcxCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ9mYWN0b3J5Q29udHJhY3QJARRrZXlGYWN0b3J5UG9vbFdlaWdodAEFDnBvb2xBZGRyZXNzU3RyBANwdzAJAQt2YWx1ZU9yRWxzZQIJAJoIAgUPZmFjdG9yeUNvbnRyYWN0CQEba2V5RmFjdG9yeVBvb2xXZWlnaHRIaXN0b3J5AgUOcG9vbEFkZHJlc3NTdHIAAAUDcHcxCQCUCgIFA3B3MAUDcHcxAwUIcmVhZE9ubHkJAJQKAgAAAAAJAAIBCQCsAgICKG5vdCByZWFkb25seSBtb2RlOiB1bnN1cHBvcnRlZCBscCBhc3NldCAFDGxwQXNzZXRJZFN0cgQLcG9vbFdlaWdodDAIBQ0kdDAxMzk1ODE0NTI2Al8xBAtwb29sV2VpZ2h0MQgFDSR0MDEzOTU4MTQ1MjYCXzIEEnd4RW1pc3Npb25QZXJCbG9jawkBA2lvZgIFEGVtaXNzaW9uQ29udHJhY3QJAR5rZXlFbWlzc2lvblJhdGVQZXJCbG9ja0N1cnJlbnQABA1lbWlzc2lvblN0YXJ0CQEDaW9mAgUQZW1pc3Npb25Db250cmFjdAkBFWtleUVtaXNzaW9uU3RhcnRCbG9jawAEC2VtaXNzaW9uRW5kCQEDaW9mAgUQZW1pc3Npb25Db250cmFjdAkBE2tleUVtaXNzaW9uRW5kQmxvY2sABAFoAwkAZgIFBmhlaWdodAULZW1pc3Npb25FbmQFC2VtaXNzaW9uRW5kBQZoZWlnaHQEAmRoCQCWAwEJAMwIAgkAZQIFAWgFDWVtaXNzaW9uU3RhcnQJAMwIAgAABQNuaWwEInVzZXJMcEJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkJASJrZXlVc2VyTHBCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMAgUKdXNlck51bVN0cgUMbHBBc3NldElkU3RyBCB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQkBIGtleVVzZXJCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMAQUKdXNlck51bVN0cgQddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUidXNlckxwQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQkBA2lvegIFBHRoaXMFIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZBBVib29zdEVtaXNzaW9uSW50ZWdyYWwJAGkCCQBoAgkAaAIFEnd4RW1pc3Npb25QZXJCbG9jawUCZGgAAgADBBl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsCQBlAgUVYm9vc3RFbWlzc2lvbkludGVncmFsBR11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbAQDdWRoCQBrAwUZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAADCQBoAgACBRJ3eEVtaXNzaW9uUGVyQmxvY2sEBnVMYXN0SAkAZQIFAWgFA3VkaAQEdWRoMAkAlgMBCQDMCAIJAGUCBRxnd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0BQZ1TGFzdEgJAMwIAgAABQNuaWwEBHVkaDEJAGUCCQBlAgUBaAUGdUxhc3RIBQR1ZGgwAwMDCQBmAgAABQZ1TGFzdEgGCQBmAgAABQR1ZGgxBgkAZwIJAQNhYnMBCQBlAgkAZAIFBHVkaDAFBHVkaDEFA3VkaAABCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhZpbnZhbGlkIHVkaCBjYWxjOiB1ZGg9CQCkAwEFA3VkaAIIIHVMYXN0SD0JAKQDAQUGdUxhc3RIAgYgdWRoMD0JAKQDAQUEdWRoMAIGIHVkaDE9CQCkAwEFBHVkaDEDCQBmAgAABRl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsCQACAQISd3JvbmcgY2FsY3VsYXRpb25zBBd1c2VyTWF4Qm9vc3RJbnRlZ3JhbEtFWQkBF2tleVVzZXJNYXhCb29zdElOVEVHUkFMAQUKdXNlck51bVN0cgQYdG90YWxNYXhCb29zdEludGVncmFsS0VZCQEYa2V5VG90YWxNYXhCb29zdElOVEVHUkFMAAQPdXNlck1heEJvb3N0SW50CQEDaW96AgUEdGhpcwUXdXNlck1heEJvb3N0SW50ZWdyYWxLRVkEEHRvdGFsTWF4Qm9vc3RJbnQJAQNpb3oCBQR0aGlzBRh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkEEXRvdGFsQ2FjaGVkR3d4S0VZCQERa2V5VG90YWxDYWNoZWRHd3gABA50b3RhbENhY2hlZEd3eAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBRF0b3RhbENhY2hlZEd3eEtFWQAABAt1c2VyQ3Vyckd3eAkBFGNhbGNDdXJyZW50R3d4QW1vdW50AQUOdXNlckFkZHJlc3NTdHIEIXVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbEtFWQkBIWtleVVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbAEFCnVzZXJOdW1TdHIEHnVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbAkBA2lvegIFBHRoaXMFIXVzZXJCb29zdEF2YWxhaWJsZVRvQ2xhaW1Ub3RhbEtFWQQadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDADCQAAAgUDdWRoAAAAAAkAawMFGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwFBHVkaDAFA3VkaAQadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDEDCQAAAgUDdWRoAAAAAAkAawMFGXVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwFBHVkaDEFA3VkaAQecG9vbFVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwwCQBrAwUadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDAFC3Bvb2xXZWlnaHQwBQ5QT09MV0VJR0hUTVVMVAQecG9vbFVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwxCQBrAwUadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDEFC3Bvb2xXZWlnaHQxBQ5QT09MV0VJR0hUTVVMVAQidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MAMJAAACBQ50b3RhbENhY2hlZEd3eAAAAAAJAGsDBR5wb29sVXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDAFC3VzZXJDdXJyR3d4BQ50b3RhbENhY2hlZEd3eAQidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MQMJAAACBQ50b3RhbENhY2hlZEd3eAAAAAAJAGsDBR5wb29sVXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDEFC3VzZXJDdXJyR3d4BQ50b3RhbENhY2hlZEd3eAQhdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3CQBkAgUidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MAUidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MQQTdXNlckJvb3N0Q2xhaW1lZEtFWQkBE2tleVVzZXJCb29zdENsYWltZWQBBQp1c2VyTnVtU3RyBBB1c2VyQm9vc3RDbGFpbWVkCQEDaW96AgUEdGhpcwUTdXNlckJvb3N0Q2xhaW1lZEtFWQQSdXNlckJvb3N0QXZhaWxhYmxlCQBlAgUhdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3BRB1c2VyQm9vc3RDbGFpbWVkBAlkYXRhU3RhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIFInVzZXJMcEJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkFFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAUDbmlsBAVkZWJ1ZwkAuQkCCQDMCAIJAKQDAQUddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwJAMwIAgkApAMBBRl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsCQDMCAIJAKQDAQUQdXNlckJvb3N0Q2xhaW1lZAkAzAgCCQCkAwEFEnVzZXJCb29zdEF2YWlsYWJsZQkAzAgCCQCkAwEFC3Bvb2xXZWlnaHQwCQDMCAIJAKQDAQULcG9vbFdlaWdodDEJAMwIAgkApAMBBQFoCQDMCAIJAKQDAQUDdWRoCQDMCAIJAKQDAQUGdUxhc3RICQDMCAIJAKQDAQUEdWRoMAkAzAgCCQCkAwEFBHVkaDEJAMwIAgkApAMBBQt1c2VyQ3Vyckd3eAkAzAgCCQCkAwEFDnRvdGFsQ2FjaGVkR3d4BQNuaWwCAToJAJUKAwUhdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3BQlkYXRhU3RhdGUFBWRlYnVnAQtsb2NrQWN0aW9ucwIBaQhkdXJhdGlvbgQIY2ZnQXJyYXkJARVyZWFkQ29uZmlnQXJyYXlPckZhaWwABAphc3NldElkU3RyCQCRAwIFCGNmZ0FycmF5BQ1JZHhDZmdBc3NldElkBAdhc3NldElkCQDZBAEFCmFzc2V0SWRTdHIEDW1pbkxvY2tBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQUTSWR4Q2ZnTWluTG9ja0Ftb3VudAQPbWluTG9ja0R1cmF0aW9uCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFFUlkeENmZ01pbkxvY2tEdXJhdGlvbgQPbWF4TG9ja0R1cmF0aW9uCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIY2ZnQXJyYXkFFUlkeENmZ01heExvY2tEdXJhdGlvbgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECNGludmFsaWQgcGF5bWVudCAtIGV4YWN0IG9uZSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAABAlwbXRBbW91bnQIBQNwbXQGYW1vdW50AwkBAiE9AgUHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkCQACAQkArAICCQCsAgICHmludmFsaWQgYXNzZXQgaXMgaW4gcGF5bWVudCAtIAUKYXNzZXRJZFN0cgIMIGlzIGV4cGVjdGVkBA5uZXh0VXNlck51bUtFWQkBDmtleU5leHRVc2VyTnVtAAQOdXNlckFkZHJlc3NTdHIJAKUIAQgFAWkGY2FsbGVyBA51c2VySXNFeGlzdGluZwkBCWlzRGVmaW5lZAEJAKIIAQkBEmtleVVzZXIyTnVtTWFwcGluZwEFDnVzZXJBZGRyZXNzU3RyBAp1c2VyTnVtU3RyAwUOdXNlcklzRXhpc3RpbmcJAQV2YWx1ZQEJAKIIAQkBEmtleVVzZXIyTnVtTWFwcGluZwEFDnVzZXJBZGRyZXNzU3RyCQCkAwEJAQNpb2YCBQR0aGlzBQ5uZXh0VXNlck51bUtFWQQHdXNlck51bQkBDXBhcnNlSW50VmFsdWUBBQp1c2VyTnVtU3RyBAlsb2NrU3RhcnQFBmhlaWdodAQNc3RhcnRCbG9ja0tFWQkBFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sBBQp1c2VyTnVtU3RyBAtkdXJhdGlvbktFWQkBFGtleUxvY2tQYXJhbUR1cmF0aW9uAQUKdXNlck51bVN0cgQNdXNlckFtb3VudEtFWQkBFmtleUxvY2tQYXJhbVVzZXJBbW91bnQBBQp1c2VyTnVtU3RyAwkAZgIFDW1pbkxvY2tBbW91bnQFCXBtdEFtb3VudAkAAgEJAKwCAgIiYW1vdW50IGlzIGxlc3MgdGhlbiBtaW5Mb2NrQW1vdW50PQkApAMBBQ1taW5Mb2NrQW1vdW50AwkAZgIFD21pbkxvY2tEdXJhdGlvbgUIZHVyYXRpb24JAAIBCQCsAgICLXBhc3NlZCBkdXJhdGlvbiBpcyBsZXNzIHRoZW4gbWluTG9ja0R1cmF0aW9uPQkApAMBBQ9taW5Mb2NrRHVyYXRpb24DCQBmAgUIZHVyYXRpb24FD21heExvY2tEdXJhdGlvbgkAAgEJAKwCAgIwcGFzc2VkIGR1cmF0aW9uIGlzIGdyZWF0ZXIgdGhlbiBtYXhMb2NrRHVyYXRpb249CQCkAwEFD21heExvY2tEdXJhdGlvbgMDBQ51c2VySXNFeGlzdGluZwkAZwIJAGQCCQEDaW9mAgUEdGhpcwUNc3RhcnRCbG9ja0tFWQkBA2lvZgIFBHRoaXMFC2R1cmF0aW9uS0VZBQlsb2NrU3RhcnQHCQACAQI2dGhlcmUgaXMgYW4gYWN0aXZlIGxvY2sgLSBjb25zaWRlciB0byB1c2UgaW5jcmVhc2VMb2NrAwkAZgIJAQNpb3oCBQR0aGlzBQ11c2VyQW1vdW50S0VZAAAJAAIBCQCsAgICNHRoZXJlIGFyZSBsb2NrZWQgV1hzIC0gY29uc2lkZXIgdG8gdXNlIGluY3JlYXNlTG9jayAFDXVzZXJBbW91bnRLRVkEB2NvZWZmWDgJAGsDBQhkdXJhdGlvbgUFTVVMVDgFD21heExvY2tEdXJhdGlvbgQOZ1d4QW1vdW50U3RhcnQJAGsDBQlwbXRBbW91bnQFB2NvZWZmWDgFBU1VTFQ4BBNnV3hQYXJhbXNSZXN1bHRMaXN0CQEDYWFsAQkA/AcEBQxtYXRoQ29udHJhY3QCFWNhbGNHd3hQYXJhbXNSRUFET05MWQkAzAgCBQ5nV3hBbW91bnRTdGFydAkAzAgCBQlsb2NrU3RhcnQJAMwIAgUIZHVyYXRpb24FA25pbAUDbmlsBAFrCQECYWkBCQCRAwIFE2dXeFBhcmFtc1Jlc3VsdExpc3QAAAQBYgkBAmFpAQkAkQMCBRNnV3hQYXJhbXNSZXN1bHRMaXN0AAEEBnBlcmlvZAkApAMBCQECYWkBCQCRAwIFE2dXeFBhcmFtc1Jlc3VsdExpc3QAAgQSd3hFbWlzc2lvblBlckJsb2NrCQEDaW9mAgUQZW1pc3Npb25Db250cmFjdAkBHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudAAEDWVtaXNzaW9uU3RhcnQJAQNpb2YCBRBlbWlzc2lvbkNvbnRyYWN0CQEVa2V5RW1pc3Npb25TdGFydEJsb2NrAAQLZW1pc3Npb25FbmQJAQNpb2YCBRBlbWlzc2lvbkNvbnRyYWN0CQETa2V5RW1pc3Npb25FbmRCbG9jawAEAWgDCQBmAgUGaGVpZ2h0BQtlbWlzc2lvbkVuZAULZW1pc3Npb25FbmQFBmhlaWdodAQCZGgJAJYDAQkAzAgCCQBlAgUBaAUNZW1pc3Npb25TdGFydAkAzAgCAAAFA25pbAQgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkJASBrZXlVc2VyQm9vc3RFbWlzc2lvbkxhc3RJTlRFR1JBTAEFCnVzZXJOdW1TdHIEFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAaQIJAGgCCQBoAgUSd3hFbWlzc2lvblBlckJsb2NrBQJkaAACAAMEF3VzZXJNYXhCb29zdEludGVncmFsS0VZCQEXa2V5VXNlck1heEJvb3N0SU5URUdSQUwBBQp1c2VyTnVtU3RyBBh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkJARhrZXlUb3RhbE1heEJvb3N0SU5URUdSQUwABA91c2VyTWF4Qm9vc3RJbnQJAGkCCQBoAgUOZ1d4QW1vdW50U3RhcnQFCGR1cmF0aW9uAAIEEHRvdGFsTWF4Qm9vc3RJbnQJAQNpb3oCBQR0aGlzBRh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkEEXRvdGFsQ2FjaGVkR3d4S0VZCQERa2V5VG90YWxDYWNoZWRHd3gABA50b3RhbENhY2hlZEd3eAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBRF0b3RhbENhY2hlZEd3eEtFWQAABANhcnIDBQ51c2VySXNFeGlzdGluZwUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5uZXh0VXNlck51bUtFWQkAZAIFB3VzZXJOdW0AAQkAzAgCCQELU3RyaW5nRW50cnkCCQESa2V5VXNlcjJOdW1NYXBwaW5nAQUOdXNlckFkZHJlc3NTdHIFCnVzZXJOdW1TdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEmtleU51bTJVc2VyTWFwcGluZwEFCnVzZXJOdW1TdHIFDnVzZXJBZGRyZXNzU3RyBQNuaWwJAJQKAgkAzggCCQDNCAIJAM4IAgkAzggCBQNhcnIJAQ9Mb2NrUGFyYW1zRW50cnkIBQ51c2VyQWRkcmVzc1N0cgUKdXNlck51bVN0cgUJcG10QW1vdW50BQlsb2NrU3RhcnQFCGR1cmF0aW9uBQFrBQFiBQZwZXJpb2QJAQpTdGF0c0VudHJ5BAUJcG10QW1vdW50BQhkdXJhdGlvbgABAwUOdXNlcklzRXhpc3RpbmcAAAABCQEMSGlzdG9yeUVudHJ5CAIEbG9jawUOdXNlckFkZHJlc3NTdHIFCXBtdEFtb3VudAUJbG9ja1N0YXJ0BQhkdXJhdGlvbgUBawUBYgUBaQkAzAgCCQEMSW50ZWdlckVudHJ5AgUgdXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkFFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAzAgCCQEMSW50ZWdlckVudHJ5AgURdG90YWxDYWNoZWRHd3hLRVkJAGQCBQ50b3RhbENhY2hlZEd3eAUOZ1d4QW1vdW50U3RhcnQFA25pbAUOZ1d4QW1vdW50U3RhcnQLAWkBC2NvbnN0cnVjdG9yBhFmYWN0b3J5QWRkcmVzc1N0cg5sb2NrQXNzZXRJZFN0cg1taW5Mb2NrQW1vdW50C21pbkR1cmF0aW9uC21heER1cmF0aW9uDG1hdGhDb250cmFjdAQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5rZXlOZXh0VXNlck51bQAAAAkAzAgCCQELU3RyaW5nRW50cnkCCQEJa2V5Q29uZmlnAAkBDGZvcm1hdENvbmZpZwUFDmxvY2tBc3NldElkU3RyBQ1taW5Mb2NrQW1vdW50BQttaW5EdXJhdGlvbgULbWF4RHVyYXRpb24FDG1hdGhDb250cmFjdAkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5RmFjdG9yeUFkZHJlc3MABRFmYWN0b3J5QWRkcmVzc1N0cgUDbmlsCQEKU3RhdHNFbnRyeQQAAAAAAAAAAAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQdsb2NrUmVmAwhkdXJhdGlvbg9yZWZlcnJlckFkZHJlc3MJc2lnbmF0dXJlBA0kdDAyMjk2NjIzMDMxCQELbG9ja0FjdGlvbnMCBQFpBQhkdXJhdGlvbgQRbG9ja0FjdGlvbnNSZXN1bHQIBQ0kdDAyMjk2NjIzMDMxAl8xBA5nV3hBbW91bnRTdGFydAgFDSR0MDIyOTY2MjMwMzECXzIED3JlZmVycmFsQWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBnJlZkludgMDCQAAAgUPcmVmZXJyZXJBZGRyZXNzAgAGCQAAAgUJc2lnbmF0dXJlAQAFBHVuaXQJAPwHBAUecmVmZXJyYWxzQ29udHJhY3RBZGRyZXNzT3JGYWlsAgpjcmVhdGVQYWlyCQDMCAIFE3JlZmVycmFsUHJvZ3JhbU5hbWUJAMwIAgUPcmVmZXJyZXJBZGRyZXNzCQDMCAIFD3JlZmVycmFsQWRkcmVzcwkAzAgCBQlzaWduYXR1cmUFA25pbAUDbmlsAwkAAAIFBnJlZkludgUGcmVmSW52BBF1cGRhdGVSZWZBY3Rpdml0eQkA/AcEBQxtYXRoQ29udHJhY3QCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUBaQZjYWxsZXIJAMwIAgUOZ1d4QW1vdW50U3RhcnQFA25pbAUDbmlsAwkAAAIFEXVwZGF0ZVJlZkFjdGl2aXR5BRF1cGRhdGVSZWZBY3Rpdml0eQkAlAoCBRFsb2NrQWN0aW9uc1Jlc3VsdAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQRsb2NrAQhkdXJhdGlvbgQNJHQwMjM0ODkyMzU1NAkBC2xvY2tBY3Rpb25zAgUBaQUIZHVyYXRpb24EEWxvY2tBY3Rpb25zUmVzdWx0CAUNJHQwMjM0ODkyMzU1NAJfMQQOZ1d4QW1vdW50U3RhcnQIBQ0kdDAyMzQ4OTIzNTU0Al8yBBF1cGRhdGVSZWZBY3Rpdml0eQkA/AcEBQxtYXRoQ29udHJhY3QCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUBaQZjYWxsZXIJAMwIAgUOZ1d4QW1vdW50U3RhcnQFA25pbAUDbmlsAwkAAAIFEXVwZGF0ZVJlZkFjdGl2aXR5BRF1cGRhdGVSZWZBY3Rpdml0eQkAlAoCBRFsb2NrQWN0aW9uc1Jlc3VsdAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxpbmNyZWFzZUxvY2sBDWRlbHRhRHVyYXRpb24ECGNmZ0FycmF5CQEVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAQKYXNzZXRJZFN0cgkAkQMCBQhjZmdBcnJheQUNSWR4Q2ZnQXNzZXRJZAQHYXNzZXRJZAkA2QQBBQphc3NldElkU3RyBA9taW5Mb2NrRHVyYXRpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQUVSWR4Q2ZnTWluTG9ja0R1cmF0aW9uBA9tYXhMb2NrRHVyYXRpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhjZmdBcnJheQUVSWR4Q2ZnTWF4TG9ja0R1cmF0aW9uBAlwbXRBbW91bnQJASJleHRyYWN0T3B0aW9uYWxQYXltZW50QW1vdW50T3JGYWlsAgUBaQUHYXNzZXRJZAQOdXNlckFkZHJlc3NTdHIJAKUIAQgFAWkGY2FsbGVyBA91c2VyUmVjb3JkQXJyYXkJARpyZWFkTG9ja1BhcmFtc1JlY29yZE9yRmFpbAEFDnVzZXJBZGRyZXNzU3RyBAp1c2VyTnVtU3RyCQCRAwIFD3VzZXJSZWNvcmRBcnJheQUOSWR4TG9ja1VzZXJOdW0ECnVzZXJBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ91c2VyUmVjb3JkQXJyYXkFDUlkeExvY2tBbW91bnQECWxvY2tTdGFydAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFD3VzZXJSZWNvcmRBcnJheQUMSWR4TG9ja1N0YXJ0BAxsb2NrRHVyYXRpb24JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ91c2VyUmVjb3JkQXJyYXkFD0lkeExvY2tEdXJhdGlvbgQHbG9ja0VuZAkAZAIFCWxvY2tTdGFydAUMbG9ja0R1cmF0aW9uBBFyZW1haW5pbmdEdXJhdGlvbgkAlgMBCQDMCAIJAGUCBQdsb2NrRW5kBQZoZWlnaHQJAMwIAgAABQNuaWwEDXVzZXJBbW91bnROZXcJAGQCBQp1c2VyQW1vdW50BQlwbXRBbW91bnQED2xvY2tEdXJhdGlvbk5ldwkAZAIFEXJlbWFpbmluZ0R1cmF0aW9uBQ1kZWx0YUR1cmF0aW9uAwkAZgIAAAUNZGVsdGFEdXJhdGlvbgkAAgECGmR1cmF0aW9uIGlzIGxlc3MgdGhlbiB6ZXJvAwkAZgIFD21pbkxvY2tEdXJhdGlvbgUPbG9ja0R1cmF0aW9uTmV3CQACAQkArAICAi1sb2NrRHVyYXRpb25OZXcgaXMgbGVzcyB0aGVuIG1pbkxvY2tEdXJhdGlvbj0JAKQDAQUPbWluTG9ja0R1cmF0aW9uAwkAZgIFD2xvY2tEdXJhdGlvbk5ldwUPbWF4TG9ja0R1cmF0aW9uCQACAQkArAICAkRkZWx0YUR1cmF0aW9uICsgZXhpc3RlZExvY2tEdXJhdGlvbiBpcyBncmVhdGVyIHRoZW4gbWF4TG9ja0R1cmF0aW9uPQkApAMBBQ9tYXhMb2NrRHVyYXRpb24EB2NvZWZmWDgJAGsDBQ9sb2NrRHVyYXRpb25OZXcFBU1VTFQ4BQ9tYXhMb2NrRHVyYXRpb24EDmdXeEFtb3VudFN0YXJ0CQBrAwUNdXNlckFtb3VudE5ldwUHY29lZmZYOAUFTVVMVDgEEXVwZGF0ZVJlZkFjdGl2aXR5CQD8BwQFDG1hdGhDb250cmFjdAIWdXBkYXRlUmVmZXJyYWxBY3Rpdml0eQkAzAgCCQClCAEIBQFpBmNhbGxlcgkAzAgCBQ5nV3hBbW91bnRTdGFydAUDbmlsBQNuaWwDCQAAAgURdXBkYXRlUmVmQWN0aXZpdHkFEXVwZGF0ZVJlZkFjdGl2aXR5BAxsb2NrU3RhcnROZXcFBmhlaWdodAQTZ1d4UGFyYW1zUmVzdWx0TGlzdAkBA2FhbAEJAPwHBAUMbWF0aENvbnRyYWN0AhVjYWxjR3d4UGFyYW1zUkVBRE9OTFkJAMwIAgUOZ1d4QW1vdW50U3RhcnQJAMwIAgUMbG9ja1N0YXJ0TmV3CQDMCAIFD2xvY2tEdXJhdGlvbk5ldwUDbmlsBQNuaWwEAWsJAQJhaQEJAJEDAgUTZ1d4UGFyYW1zUmVzdWx0TGlzdAAABAFiCQECYWkBCQCRAwIFE2dXeFBhcmFtc1Jlc3VsdExpc3QAAQQGcGVyaW9kCQCkAwEJAQJhaQEJAJEDAgUTZ1d4UGFyYW1zUmVzdWx0TGlzdAACBBJ3eEVtaXNzaW9uUGVyQmxvY2sJAQNpb2YCBRBlbWlzc2lvbkNvbnRyYWN0CQEea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50AAQNZW1pc3Npb25TdGFydAkBA2lvZgIFEGVtaXNzaW9uQ29udHJhY3QJARVrZXlFbWlzc2lvblN0YXJ0QmxvY2sABAtlbWlzc2lvbkVuZAkBA2lvZgIFEGVtaXNzaW9uQ29udHJhY3QJARNrZXlFbWlzc2lvbkVuZEJsb2NrAAQBaAMJAGYCBQZoZWlnaHQFC2VtaXNzaW9uRW5kBQtlbWlzc2lvbkVuZAUGaGVpZ2h0BAJkaAkAlgMBCQDMCAIJAGUCBQFoBQ1lbWlzc2lvblN0YXJ0CQDMCAIAAAUDbmlsBCB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQkBIGtleVVzZXJCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMAQUKdXNlck51bVN0cgQddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwJAQNpb3oCBQR0aGlzBSB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWQQVYm9vc3RFbWlzc2lvbkludGVncmFsCQBpAgkAaAIJAGgCBRJ3eEVtaXNzaW9uUGVyQmxvY2sFAmRoAAIAAwQZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbAkAZQIFFWJvb3N0RW1pc3Npb25JbnRlZ3JhbAUddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwDCQBmAgAABRl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsCQACAQISd3JvbmcgY2FsY3VsYXRpb25zBBd1c2VyTWF4Qm9vc3RJbnRlZ3JhbEtFWQkBF2tleVVzZXJNYXhCb29zdElOVEVHUkFMAQUKdXNlck51bVN0cgQYdG90YWxNYXhCb29zdEludGVncmFsS0VZCQEYa2V5VG90YWxNYXhCb29zdElOVEVHUkFMAAQPdXNlck1heEJvb3N0SW50CQEDaW96AgUEdGhpcwUXdXNlck1heEJvb3N0SW50ZWdyYWxLRVkEEHRvdGFsTWF4Qm9vc3RJbnQJAQNpb3oCBQR0aGlzBRh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkEC2N1cnJVc2VyR3d4CQEUY2FsY0N1cnJlbnRHd3hBbW91bnQBBQ51c2VyQWRkcmVzc1N0cgQHZ3d4RGlmZgkAZQIFDmdXeEFtb3VudFN0YXJ0BQtjdXJyVXNlckd3eAMJAGYCAAAFB2d3eERpZmYJAAIBCQCsAgICGGd3eERpZmYgaXMgbGVzcyB0aGVuIDA6IAkApAMBBQdnd3hEaWZmBBF0b3RhbENhY2hlZEd3eEtFWQkBEWtleVRvdGFsQ2FjaGVkR3d4AAQOdG90YWxDYWNoZWRHd3gJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwURdG90YWxDYWNoZWRHd3hLRVkAAAQhdXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsS0VZCQEha2V5VXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsAQUKdXNlck51bVN0cgQedXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQEDaW96AgUEdGhpcwUhdXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsS0VZBCF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXcJAGsDBRl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsBQtjdXJyVXNlckd3eAUOdG90YWxDYWNoZWRHd3gEEnVzZXJNYXhCb29zdEludE5ldwkAaQIJAGgCBQ5nV3hBbW91bnRTdGFydAUPbG9ja0R1cmF0aW9uTmV3AAIEGHJlbWFpbmluZ1VzZXJNYXhCb29zdEludAkAaQIJAGgCBQtjdXJyVXNlckd3eAURcmVtYWluaW5nRHVyYXRpb24AAgQTdXNlck1heEJvb3N0SW50RGlmZgkAZQIFEnVzZXJNYXhCb29zdEludE5ldwUYcmVtYWluaW5nVXNlck1heEJvb3N0SW50CQDOCAIJAM0IAgkAzggCCQEPTG9ja1BhcmFtc0VudHJ5CAUOdXNlckFkZHJlc3NTdHIFCnVzZXJOdW1TdHIFDXVzZXJBbW91bnROZXcFDGxvY2tTdGFydE5ldwUPbG9ja0R1cmF0aW9uTmV3BQFrBQFiBQZwZXJpb2QJAQpTdGF0c0VudHJ5BAUJcG10QW1vdW50BQ1kZWx0YUR1cmF0aW9uAAAAAAkBDEhpc3RvcnlFbnRyeQgCBGxvY2sFDnVzZXJBZGRyZXNzU3RyBQlwbXRBbW91bnQFCWxvY2tTdGFydAUPbG9ja0R1cmF0aW9uTmV3BQFrBQFiBQFpCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRF0b3RhbENhY2hlZEd3eEtFWQkAZAIFDnRvdGFsQ2FjaGVkR3d4BQdnd3hEaWZmBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMY2xhaW1XeEJvb3N0AgxscEFzc2V0SWRTdHIOdXNlckFkZHJlc3NTdHIDCQECIT0CBQ9zdGFraW5nQ29udHJhY3QIBQFpBmNhbGxlcgkAAgECEnBlcm1pc3Npb25zIGRlbmllZAQNJHQwMjg1MzMyODYzNQkBFGludGVybmFsQ2xhaW1XeEJvb3N0AwUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgcEEnVzZXJCb29zdEF2YWlsYWJsZQgFDSR0MDI4NTMzMjg2MzUCXzEECWRhdGFTdGF0ZQgFDSR0MDI4NTMzMjg2MzUCXzIEBWRlYnVnCAUNJHQwMjg1MzMyODYzNQJfMwkAlAoCBQlkYXRhU3RhdGUJAMwIAgUSdXNlckJvb3N0QXZhaWxhYmxlBQNuaWwBaQEUY2xhaW1XeEJvb3N0UkVBRE9OTFkCDGxwQXNzZXRJZFN0cg51c2VyQWRkcmVzc1N0cgQNJHQwMjg3NjcyODg2OAkBFGludGVybmFsQ2xhaW1XeEJvb3N0AwUMbHBBc3NldElkU3RyBQ51c2VyQWRkcmVzc1N0cgYEEnVzZXJCb29zdEF2YWlsYWJsZQgFDSR0MDI4NzY3Mjg4NjgCXzEECWRhdGFTdGF0ZQgFDSR0MDI4NzY3Mjg4NjgCXzIEBWRlYnVnCAUNJHQwMjg3NjcyODg2OAJfMwkAlAoCBQNuaWwJAMwIAgUSdXNlckJvb3N0QXZhaWxhYmxlCQDMCAIFBWRlYnVnBQNuaWwBaQEGdW5sb2NrAQt1c2VyQWRkcmVzcwQPdXNlclJlY29yZEFycmF5CQEacmVhZExvY2tQYXJhbXNSZWNvcmRPckZhaWwBBQt1c2VyQWRkcmVzcwQKdXNlck51bVN0cgkAkQMCBQ91c2VyUmVjb3JkQXJyYXkFDklkeExvY2tVc2VyTnVtBAp1c2VyQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUPdXNlclJlY29yZEFycmF5BQ1JZHhMb2NrQW1vdW50BAlsb2NrU3RhcnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ91c2VyUmVjb3JkQXJyYXkFDElkeExvY2tTdGFydAQMbG9ja0R1cmF0aW9uCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUPdXNlclJlY29yZEFycmF5BQ9JZHhMb2NrRHVyYXRpb24EB2xvY2tFbmQJAGQCBQlsb2NrU3RhcnQFDGxvY2tEdXJhdGlvbgQIY2ZnQXJyYXkJARVyZWFkQ29uZmlnQXJyYXlPckZhaWwABAdhc3NldElkCQDZBAEJAJEDAgUIY2ZnQXJyYXkFDUlkeENmZ0Fzc2V0SWQDCQBnAgUHbG9ja0VuZAUGaGVpZ2h0CQACAQkArAICCQCsAgICBXdhaXQgCQCkAwEFB2xvY2tFbmQCCiB0byB1bmxvY2sDCQBnAgAABQp1c2VyQW1vdW50CQACAQIRbm90aGluZyB0byB1bmxvY2sEBnBlcmlvZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQxtYXRoQ29udHJhY3QJAQ1rZXlOZXh0UGVyaW9kAAAACQDNCAIJAM0IAgkAzggCCQEPTG9ja1BhcmFtc0VudHJ5CAULdXNlckFkZHJlc3MFCnVzZXJOdW1TdHIAAAUJbG9ja1N0YXJ0BQxsb2NrRHVyYXRpb24AAAAACQCkAwEFBnBlcmlvZAkBClN0YXRzRW50cnkECQEBLQEFCnVzZXJBbW91bnQAAAAAAP///////////wEJAQxIaXN0b3J5RW50cnkIAgZ1bmxvY2sFC3VzZXJBZGRyZXNzBQp1c2VyQW1vdW50BQlsb2NrU3RhcnQFDGxvY2tEdXJhdGlvbgAAAAAFAWkJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFC3VzZXJBZGRyZXNzBQp1c2VyQW1vdW50BQdhc3NldElkAWkBE2d3eFVzZXJJbmZvUkVBRE9OTFkBC3VzZXJBZGRyZXNzBAlnd3hBbW91bnQJARRjYWxjQ3VycmVudEd3eEFtb3VudAEFC3VzZXJBZGRyZXNzCQCUCgIFA25pbAkAzAgCBQlnd3hBbW91bnQFA25pbAFpASBnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHRSRUFET05MWQILdXNlckFkZHJlc3MMdGFyZ2V0SGVpZ2h0BAlnd3hBbW91bnQJARljYWxjVXNlckd3eEFtb3VudEF0SGVpZ2h0AgULdXNlckFkZHJlc3MFDHRhcmdldEhlaWdodAkAlAoCBQNuaWwFCWd3eEFtb3VudAFpAQpzZXRNYW5hZ2VyARdwZW5kaW5nTWFuYWdlclB1YmxpY0tleQQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBBVjaGVja01hbmFnZXJQdWJsaWNLZXkJANkEAQUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkDCQAAAgUVY2hlY2tNYW5hZ2VyUHVibGljS2V5BRVjaGVja01hbmFnZXJQdWJsaWNLZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5jb25maXJtTWFuYWdlcgAEAnBtCQEdcGVuZGluZ01hbmFnZXJQdWJsaWNLZXlPclVuaXQABAVoYXNQTQMJAQlpc0RlZmluZWQBBQJwbQYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUFaGFzUE0FBWhhc1BNBAdjaGVja1BNAwkAAAIIBQFpD2NhbGxlclB1YmxpY0tleQkBBXZhbHVlAQUCcG0GCQACAQIbWW91IGFyZSBub3QgcGVuZGluZyBtYW5hZ2VyAwkAAAIFB2NoZWNrUE0FB2NoZWNrUE0JAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleU1hbmFnZXJQdWJsaWNLZXkACQDYBAEJAQV2YWx1ZQEFAnBtCQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAED3RhcmdldFB1YmxpY0tleQQHJG1hdGNoMAkBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwBQJwawMJAAECBQckbWF0Y2gwAgRVbml0CAUCdHgPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAFD3RhcmdldFB1YmxpY0tleZhTj1U=", "chainId": 87, "height": 3240990, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 218JccVxYAg3euRNNULaNrUnU1DwhQFagcsiiedsg1yt Next: 97RfoaU2E85yx3oek7mJLcFpXBvpML66G4f9JrZFLYTg Diff:
OldNewDifferences
4141 throw("fail to cast into Int")
4242 }
4343
44+
45+func keyReferralsContractAddress () = makeString(["%s%s", "config", "referralsContractAddress"], SEP)
46+
47+
48+let referralsContractAddressOrFail = addressFromStringValue(strf(this, keyReferralsContractAddress()))
49+
50+let keyReferralProgramName = makeString(["%s%s", "referral", "programName"], SEP)
51+
52+let referralProgramNameDefault = "wxlock"
53+
54+let referralProgramName = valueOrElse(getString(this, keyReferralProgramName), referralProgramNameDefault)
4455
4556 func keyFactoryAddress () = "%s%s__config__factoryAddress"
4657
148159
149160 func readConfigArrayOrFail () = split(strf(this, keyConfig()), SEP)
150161
162+
163+let mathContract = addressFromStringValue(readConfigArrayOrFail()[IdxCfgMathContract])
151164
152165 func formatConfigS (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = makeString(["%s%d%d%d", assetId, minLockAmount, minLockDuration, maxLockDuration, mathContract], SEP)
153166
367380 let userNumStr = userRecordArray[IdxLockUserNum]
368381 let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
369382 let EMPTYSTR = "empty"
370- let $t01316713735 = if ((lpAssetIdStr != EMPTYSTR))
383+ let $t01395814526 = if ((lpAssetIdStr != EMPTYSTR))
371384 then {
372385 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
373386 let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
377390 else if (readOnly)
378391 then $Tuple2(0, 0)
379392 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
380- let poolWeight0 = $t01316713735._1
381- let poolWeight1 = $t01316713735._2
393+ let poolWeight0 = $t01395814526._1
394+ let poolWeight1 = $t01395814526._2
382395 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
383396 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
384397 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
439452 }
440453
441454
442-@Callable(i)
443-func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
444- let checkCaller = mustManager(i)
445- if ((checkCaller == checkCaller))
446- then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
447- else throw("Strict value is not equal to itself.")
448- }
449-
450-
451-
452-@Callable(i)
453-func lock (duration) = {
455+func lockActions (i,duration) = {
454456 let cfgArray = readConfigArrayOrFail()
455457 let assetIdStr = cfgArray[IdxCfgAssetId]
456458 let assetId = fromBase58String(assetIdStr)
457459 let minLockAmount = parseIntValue(cfgArray[IdxCfgMinLockAmount])
458460 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
459461 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
460- let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
461462 if ((size(i.payments) != 1))
462463 then throw("invalid payment - exact one payment must be attached")
463464 else {
514515 let arr = if (userIsExisting)
515516 then nil
516517 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
517- ((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
518+ $Tuple2(((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
518519 then 0
519- else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gWxAmountStart))])
520+ else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gWxAmountStart))]), gWxAmountStart)
520521 }
521522 }
522523 }
524+ }
525+
526+
527+@Callable(i)
528+func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
529+ let checkCaller = mustManager(i)
530+ if ((checkCaller == checkCaller))
531+ then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
532+ else throw("Strict value is not equal to itself.")
533+ }
534+
535+
536+
537+@Callable(i)
538+func lockRef (duration,referrerAddress,signature) = {
539+ let $t02296623031 = lockActions(i, duration)
540+ let lockActionsResult = $t02296623031._1
541+ let gWxAmountStart = $t02296623031._2
542+ let referralAddress = toString(i.caller)
543+ let refInv = if (if ((referrerAddress == ""))
544+ then true
545+ else (signature == base58''))
546+ then unit
547+ else invoke(referralsContractAddressOrFail, "createPair", [referralProgramName, referrerAddress, referralAddress, signature], nil)
548+ if ((refInv == refInv))
549+ then {
550+ let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
551+ if ((updateRefActivity == updateRefActivity))
552+ then $Tuple2(lockActionsResult, unit)
553+ else throw("Strict value is not equal to itself.")
554+ }
555+ else throw("Strict value is not equal to itself.")
556+ }
557+
558+
559+
560+@Callable(i)
561+func lock (duration) = {
562+ let $t02348923554 = lockActions(i, duration)
563+ let lockActionsResult = $t02348923554._1
564+ let gWxAmountStart = $t02348923554._2
565+ let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
566+ if ((updateRefActivity == updateRefActivity))
567+ then $Tuple2(lockActionsResult, unit)
568+ else throw("Strict value is not equal to itself.")
523569 }
524570
525571
531577 let assetId = fromBase58String(assetIdStr)
532578 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
533579 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
534- let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
535580 let pmtAmount = extractOptionalPaymentAmountOrFail(i, assetId)
536581 let userAddressStr = toString(i.caller)
537582 let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
552597 else {
553598 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
554599 let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
555- let lockStartNew = height
556- let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
557- let k = ai(gWxParamsResultList[0])
558- let b = ai(gWxParamsResultList[1])
559- let period = toString(ai(gWxParamsResultList[2]))
560- let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
561- let emissionStart = iof(emissionContract, keyEmissionStartBlock())
562- let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
563- let h = if ((height > emissionEnd))
564- then emissionEnd
565- else height
566- let dh = max([(h - emissionStart), 0])
567- let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
568- let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
569- let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
570- let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
571- if ((0 > userBoostEmissionIntegral))
572- then throw("wrong calculations")
573- else {
574- let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
575- let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
576- let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
577- let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
578- let currUserGwx = calcCurrentGwxAmount(userAddressStr)
579- let gwxDiff = (gWxAmountStart - currUserGwx)
580- if ((0 > gwxDiff))
581- then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
600+ let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
601+ if ((updateRefActivity == updateRefActivity))
602+ then {
603+ let lockStartNew = height
604+ let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
605+ let k = ai(gWxParamsResultList[0])
606+ let b = ai(gWxParamsResultList[1])
607+ let period = toString(ai(gWxParamsResultList[2]))
608+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
609+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
610+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
611+ let h = if ((height > emissionEnd))
612+ then emissionEnd
613+ else height
614+ let dh = max([(h - emissionStart), 0])
615+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
616+ let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
617+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
618+ let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
619+ if ((0 > userBoostEmissionIntegral))
620+ then throw("wrong calculations")
582621 else {
583- let totalCachedGwxKEY = keyTotalCachedGwx()
584- let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
585- let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
586- let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
587- let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwx)
588- let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
589- let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
590- let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
591- (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStartNew, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gwxDiff))])
622+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
623+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
624+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
625+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
626+ let currUserGwx = calcCurrentGwxAmount(userAddressStr)
627+ let gwxDiff = (gWxAmountStart - currUserGwx)
628+ if ((0 > gwxDiff))
629+ then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
630+ else {
631+ let totalCachedGwxKEY = keyTotalCachedGwx()
632+ let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
633+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
634+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
635+ let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwx)
636+ let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
637+ let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
638+ let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
639+ (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStartNew, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gwxDiff))])
640+ }
592641 }
593642 }
643+ else throw("Strict value is not equal to itself.")
594644 }
595645 }
596646
600650 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
601651 then throw("permissions denied")
602652 else {
603- let $t02692227024 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
604- let userBoostAvailable = $t02692227024._1
605- let dataState = $t02692227024._2
606- let debug = $t02692227024._3
653+ let $t02853328635 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
654+ let userBoostAvailable = $t02853328635._1
655+ let dataState = $t02853328635._2
656+ let debug = $t02853328635._3
607657 $Tuple2(dataState, [userBoostAvailable])
608658 }
609659
611661
612662 @Callable(i)
613663 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
614- let $t02715627257 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
615- let userBoostAvailable = $t02715627257._1
616- let dataState = $t02715627257._2
617- let debug = $t02715627257._3
664+ let $t02876728868 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
665+ let userBoostAvailable = $t02876728868._1
666+ let dataState = $t02876728868._2
667+ let debug = $t02876728868._3
618668 $Tuple2(nil, [userBoostAvailable, debug])
619669 }
620670
630680 let lockEnd = (lockStart + lockDuration)
631681 let cfgArray = readConfigArrayOrFail()
632682 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
633- let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
634683 if ((lockEnd >= height))
635684 then throw((("wait " + toString(lockEnd)) + " to unlock"))
636685 else if ((0 >= userAmount))
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
55
66 let SCALE8 = 8
77
88 let MULT8 = 100000000
99
1010 let POOLWEIGHTMULT = MULT8
1111
1212 func strf (address,key) = valueOrErrorMessage(getString(address, key), (("mandatory this." + key) + " is not defined"))
1313
1414
1515 func ioz (address,key) = valueOrElse(getInteger(address, key), 0)
1616
1717
1818 func iod (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
1919
2020
2121 func iof (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
2222
2323
2424 func abs (val) = if ((0 > val))
2525 then -(val)
2626 else val
2727
2828
2929 func aal (val) = match val {
3030 case valAnyLyst: List[Any] =>
3131 valAnyLyst
3232 case _ =>
3333 throw("fail to cast into List[Any]")
3434 }
3535
3636
3737 func ai (val) = match val {
3838 case valInt: Int =>
3939 valInt
4040 case _ =>
4141 throw("fail to cast into Int")
4242 }
4343
44+
45+func keyReferralsContractAddress () = makeString(["%s%s", "config", "referralsContractAddress"], SEP)
46+
47+
48+let referralsContractAddressOrFail = addressFromStringValue(strf(this, keyReferralsContractAddress()))
49+
50+let keyReferralProgramName = makeString(["%s%s", "referral", "programName"], SEP)
51+
52+let referralProgramNameDefault = "wxlock"
53+
54+let referralProgramName = valueOrElse(getString(this, keyReferralProgramName), referralProgramNameDefault)
4455
4556 func keyFactoryAddress () = "%s%s__config__factoryAddress"
4657
4758
4859 let IdxFactoryCfgStakingDapp = 1
4960
5061 let IdxFactoryCfgBoostingDapp = 2
5162
5263 let IdxFactoryCfgIdoDapp = 3
5364
5465 let IdxFactoryCfgTeamDapp = 4
5566
5667 let IdxFactoryCfgEmissionDapp = 5
5768
5869 let IdxFactoryCfgRestDapp = 6
5970
6071 let IdxFactoryCfgSlippageDapp = 7
6172
6273 let IdxFactoryCfgDaoDapp = 8
6374
6475 let IdxFactoryCfgMarketingDapp = 9
6576
6677 let IdxFactoryCfgGwxRewardDapp = 10
6778
6879 let IdxFactoryCfgBirdsDapp = 11
6980
7081 func keyFactoryCfg () = "%s__factoryConfig"
7182
7283
7384 func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
7485
7586
7687 func keyFactoryLpList () = "%s__lpTokensList"
7788
7889
7990 func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
8091
8192
8293 func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
8394
8495
8596 func keyFactoryPoolWeightHistory (poolAddress,num) = ((("%s%s__poolWeight__" + poolAddress) + "__") + toString(num))
8697
8798
8899 func readFactoryAddressOrFail () = addressFromStringValue(strf(this, keyFactoryAddress()))
89100
90101
91102 func readLpList () = split(valueOrElse(getString(readFactoryAddressOrFail(), keyFactoryLpList()), ""), SEP)
92103
93104
94105 func readFactoryCfgOrFail (factory) = split(strf(factory, keyFactoryCfg()), SEP)
95106
96107
97108 func getBoostingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgBoostingDapp])
98109
99110
100111 func getEmissionAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgEmissionDapp])
101112
102113
103114 func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
104115
105116
106117 func getGwxRewardAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgGwxRewardDapp])
107118
108119
109120 func keyManagerPublicKey () = "%s__managerPublicKey"
110121
111122
112123 func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
113124
114125
115126 func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
116127
117128
118129 func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
119130
120131
121132 func keyEmissionStartBlock () = "%s%s__emission__startBlock"
122133
123134
124135 func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
125136
126137
127138 func keyEmissionEndBlock () = "%s%s__emission__endBlock"
128139
129140
130141 func keyNextPeriod () = "%s__nextPeriod"
131142
132143
133144 func keyGwxRewardEmissionStartHeight () = "%s%s__gwxRewardEmissionPart__startHeight"
134145
135146
136147 let IdxCfgAssetId = 1
137148
138149 let IdxCfgMinLockAmount = 2
139150
140151 let IdxCfgMinLockDuration = 3
141152
142153 let IdxCfgMaxLockDuration = 4
143154
144155 let IdxCfgMathContract = 5
145156
146157 func keyConfig () = "%s__config"
147158
148159
149160 func readConfigArrayOrFail () = split(strf(this, keyConfig()), SEP)
150161
162+
163+let mathContract = addressFromStringValue(readConfigArrayOrFail()[IdxCfgMathContract])
151164
152165 func formatConfigS (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = makeString(["%s%d%d%d", assetId, minLockAmount, minLockDuration, maxLockDuration, mathContract], SEP)
153166
154167
155168 func formatConfig (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = formatConfigS(assetId, toString(minLockAmount), toString(minLockDuration), toString(maxLockDuration), mathContract)
156169
157170
158171 func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
159172 case s: String =>
160173 fromBase58String(s)
161174 case _: Unit =>
162175 unit
163176 case _ =>
164177 throw("Match error")
165178 }
166179
167180
168181 func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
169182 case s: String =>
170183 fromBase58String(s)
171184 case _: Unit =>
172185 unit
173186 case _ =>
174187 throw("Match error")
175188 }
176189
177190
178191 func mustManager (i) = {
179192 let pd = throw("Permission denied")
180193 match managerPublicKeyOrUnit() {
181194 case pk: ByteVector =>
182195 if ((i.callerPublicKey == pk))
183196 then true
184197 else pd
185198 case _: Unit =>
186199 if ((i.caller == this))
187200 then true
188201 else pd
189202 case _ =>
190203 throw("Match error")
191204 }
192205 }
193206
194207
195208 let IdxLockUserNum = 1
196209
197210 let IdxLockAmount = 2
198211
199212 let IdxLockStart = 3
200213
201214 let IdxLockDuration = 4
202215
203216 let IdxLockParamK = 5
204217
205218 let IdxLockParamB = 6
206219
207220 func keyLockParamsRecord (userAddress) = makeString(["%s%s__lock", userAddress], SEP)
208221
209222
210223 func readLockParamsRecordOrFail (userAddress) = split(strf(this, keyLockParamsRecord(userAddress)), SEP)
211224
212225
213226 func formatLockParamsRecordS (userNum,amount,start,duration,paramK,paramB,lastUpdTimestamp,gwxAmount) = makeString(["%d%d%d%d%d%d%d%d", userNum, amount, start, duration, paramK, paramB, lastUpdTimestamp, gwxAmount], SEP)
214227
215228
216229 func formatLockParamsRecord (userNum,amount,start,duration,paramK,paramB,gwxAmount) = formatLockParamsRecordS(userNum, toString(amount), toString(start), toString(duration), toString(paramK), toString(paramB), toString(lastBlock.timestamp), toString(gwxAmount))
217230
218231
219232 func keyNextUserNum () = "%s__nextUserNum"
220233
221234
222235 func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
223236
224237
225238 func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
226239
227240
228241 func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
229242
230243
231244 func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
232245
233246
234247 func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
235248
236249
237250 func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
238251
239252
240253 func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
241254
242255
243256 func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
244257
245258
246259 func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
247260
248261
249262 func keyLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
250263
251264
252265 func keyStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
253266
254267
255268 func keyStatsLocksCount () = "%s%s__stats__locksCount"
256269
257270
258271 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
259272
260273
261274 func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
262275
263276
264277 func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastInt", userNum, lpAssetId], SEP)
265278
266279
267280 func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
268281
269282
270283 func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
271284
272285
273286 func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
274287
275288
276289 func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
277290
278291
279292 func keyTotalCachedGwx () = "%s%s__gwxCached__total"
280293
281294
282295 let factoryContract = readFactoryAddressOrFail()
283296
284297 let factoryCfg = readFactoryCfgOrFail(factoryContract)
285298
286299 let emissionContract = getEmissionAddressOrFail(factoryCfg)
287300
288301 let stakingContract = getStakingAddressOrFail(factoryCfg)
289302
290303 let gwxRewardContract = getGwxRewardAddressOrFail(factoryCfg)
291304
292305 func HistoryEntry (type,user,amount,lockStart,duration,k,b,i) = {
293306 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
294307 let historyDATA = makeString(["%d%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(amount), toString(lockStart), toString(duration), toString(k), toString(b)], SEP)
295308 StringEntry(historyKEY, historyDATA)
296309 }
297310
298311
299312 func StatsEntry (totalLockedInc,durationInc,lockCountInc,usersCountInc) = {
300313 let locksDurationSumInBlocksKEY = keyStatsLocksDurationSumInBlocks()
301314 let locksCountKEY = keyStatsLocksCount()
302315 let usersCountKEY = keyStatsUsersCount()
303316 let totalAmountKEY = keyLockParamTotalAmount()
304317 let locksDurationSumInBlocks = ioz(this, locksDurationSumInBlocksKEY)
305318 let locksCount = ioz(this, locksCountKEY)
306319 let usersCount = ioz(this, usersCountKEY)
307320 let totalAmount = ioz(this, totalAmountKEY)
308321 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
309322 }
310323
311324
312325 func calcGwxAmount (kRaw,bRaw,h) = {
313326 let SCALE = 1000
314327 (((kRaw * h) + bRaw) / SCALE)
315328 }
316329
317330
318331 func LockParamsEntry (userAddress,userNum,amount,start,duration,k,b,period) = {
319332 let userAmountKEY = keyLockParamUserAmount(userNum)
320333 let startBlockKEY = keyLockParamStartBlock(userNum)
321334 let durationKEY = keyLockParamDuration(userNum)
322335 let kKEY = keyLockParamK(userNum)
323336 let bKEY = keyLockParamB(userNum)
324337 let kByPeriodKEY = keyLockParamByPeriodK(userNum, period)
325338 let bByPeriodKEY = keyLockParamByPeriodB(userNum, period)
326339 let gwxAmount = calcGwxAmount(k, b, height)
327340 [IntegerEntry(userAmountKEY, amount), IntegerEntry(startBlockKEY, start), IntegerEntry(durationKEY, duration), IntegerEntry(kKEY, k), IntegerEntry(bKEY, b), IntegerEntry(kByPeriodKEY, k), IntegerEntry(bByPeriodKEY, b), StringEntry(keyLockParamsRecord(userAddress), formatLockParamsRecord(userNum, amount, start, duration, k, b, gwxAmount))]
328341 }
329342
330343
331344 func extractOptionalPaymentAmountOrFail (i,expectedAssetId) = if ((size(i.payments) > 1))
332345 then throw("only one payment is allowed")
333346 else if ((size(i.payments) == 0))
334347 then 0
335348 else {
336349 let pmt = i.payments[0]
337350 if ((value(pmt.assetId) != expectedAssetId))
338351 then throw("invalid asset id in payment")
339352 else pmt.amount
340353 }
341354
342355
343356 func calcUserGwxAmountAtHeight (userAddress,targetHeight) = {
344357 let EMPTY = "empty"
345358 let user2NumMappingKEY = keyUser2NumMapping(userAddress)
346359 let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
347360 let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
348361 let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
349362 let gwxAmountCalc = calcGwxAmount(k, b, targetHeight)
350363 let gwxAmount = if ((0 > gwxAmountCalc))
351364 then 0
352365 else gwxAmountCalc
353366 gwxAmount
354367 }
355368
356369
357370 func calcCurrentGwxAmount (userAddress) = calcUserGwxAmountAtHeight(userAddress, height)
358371
359372
360373 func internalClaimWxBoost (lpAssetIdStr,userAddressStr,readOnly) = {
361374 let EMPTY = "EMPTY"
362375 let userRecordOrEmpty = valueOrElse(getString(this, keyLockParamsRecord(userAddressStr)), EMPTY)
363376 if ((userRecordOrEmpty == EMPTY))
364377 then $Tuple3(0, nil, "userRecord::is::empty")
365378 else {
366379 let userRecordArray = split(userRecordOrEmpty, SEP)
367380 let userNumStr = userRecordArray[IdxLockUserNum]
368381 let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
369382 let EMPTYSTR = "empty"
370- let $t01316713735 = if ((lpAssetIdStr != EMPTYSTR))
383+ let $t01395814526 = if ((lpAssetIdStr != EMPTYSTR))
371384 then {
372385 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
373386 let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
374387 let pw0 = valueOrElse(getInteger(factoryContract, keyFactoryPoolWeightHistory(poolAddressStr, 0)), pw1)
375388 $Tuple2(pw0, pw1)
376389 }
377390 else if (readOnly)
378391 then $Tuple2(0, 0)
379392 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
380- let poolWeight0 = $t01316713735._1
381- let poolWeight1 = $t01316713735._2
393+ let poolWeight0 = $t01395814526._1
394+ let poolWeight1 = $t01395814526._2
382395 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
383396 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
384397 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
385398 let h = if ((height > emissionEnd))
386399 then emissionEnd
387400 else height
388401 let dh = max([(h - emissionStart), 0])
389402 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNumStr, lpAssetIdStr)
390403 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
391404 let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), ioz(this, userBoostEmissionLastIntegralKEY))
392405 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
393406 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
394407 let udh = fraction(userBoostEmissionIntegral, 3, (2 * wxEmissionPerBlock))
395408 let uLastH = (h - udh)
396409 let udh0 = max([(gwxRewardEmissionStartHeight - uLastH), 0])
397410 let udh1 = ((h - uLastH) - udh0)
398411 if (if (if ((0 > uLastH))
399412 then true
400413 else (0 > udh1))
401414 then true
402415 else (abs(((udh0 + udh1) - udh)) >= 1))
403416 then throw(((((((("invalid udh calc: udh=" + toString(udh)) + " uLastH=") + toString(uLastH)) + " udh0=") + toString(udh0)) + " udh1=") + toString(udh1)))
404417 else if ((0 > userBoostEmissionIntegral))
405418 then throw("wrong calculations")
406419 else {
407420 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
408421 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
409422 let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
410423 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
411424 let totalCachedGwxKEY = keyTotalCachedGwx()
412425 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
413426 let userCurrGwx = calcCurrentGwxAmount(userAddressStr)
414427 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
415428 let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
416429 let userBoostEmissionIntegral0 = if ((udh == 0))
417430 then 0
418431 else fraction(userBoostEmissionIntegral, udh0, udh)
419432 let userBoostEmissionIntegral1 = if ((udh == 0))
420433 then 0
421434 else fraction(userBoostEmissionIntegral, udh1, udh)
422435 let poolUserBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral0, poolWeight0, POOLWEIGHTMULT)
423436 let poolUserBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral1, poolWeight1, POOLWEIGHTMULT)
424437 let userBoostAvaliableToClaimTotalNew0 = if ((totalCachedGwx == 0))
425438 then 0
426439 else fraction(poolUserBoostEmissionIntegral0, userCurrGwx, totalCachedGwx)
427440 let userBoostAvaliableToClaimTotalNew1 = if ((totalCachedGwx == 0))
428441 then 0
429442 else fraction(poolUserBoostEmissionIntegral1, userCurrGwx, totalCachedGwx)
430443 let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotalNew0 + userBoostAvaliableToClaimTotalNew1)
431444 let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
432445 let userBoostClaimed = ioz(this, userBoostClaimedKEY)
433446 let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
434447 let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
435448 let debug = makeString([toString(userBoostEmissionLastIntegral), toString(userBoostEmissionIntegral), toString(userBoostClaimed), toString(userBoostAvailable), toString(poolWeight0), toString(poolWeight1), toString(h), toString(udh), toString(uLastH), toString(udh0), toString(udh1), toString(userCurrGwx), toString(totalCachedGwx)], ":")
436449 $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
437450 }
438451 }
439452 }
440453
441454
442-@Callable(i)
443-func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
444- let checkCaller = mustManager(i)
445- if ((checkCaller == checkCaller))
446- then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
447- else throw("Strict value is not equal to itself.")
448- }
449-
450-
451-
452-@Callable(i)
453-func lock (duration) = {
455+func lockActions (i,duration) = {
454456 let cfgArray = readConfigArrayOrFail()
455457 let assetIdStr = cfgArray[IdxCfgAssetId]
456458 let assetId = fromBase58String(assetIdStr)
457459 let minLockAmount = parseIntValue(cfgArray[IdxCfgMinLockAmount])
458460 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
459461 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
460- let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
461462 if ((size(i.payments) != 1))
462463 then throw("invalid payment - exact one payment must be attached")
463464 else {
464465 let pmt = i.payments[0]
465466 let pmtAmount = pmt.amount
466467 if ((assetId != value(pmt.assetId)))
467468 then throw((("invalid asset is in payment - " + assetIdStr) + " is expected"))
468469 else {
469470 let nextUserNumKEY = keyNextUserNum()
470471 let userAddressStr = toString(i.caller)
471472 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
472473 let userNumStr = if (userIsExisting)
473474 then value(getString(keyUser2NumMapping(userAddressStr)))
474475 else toString(iof(this, nextUserNumKEY))
475476 let userNum = parseIntValue(userNumStr)
476477 let lockStart = height
477478 let startBlockKEY = keyLockParamStartBlock(userNumStr)
478479 let durationKEY = keyLockParamDuration(userNumStr)
479480 let userAmountKEY = keyLockParamUserAmount(userNumStr)
480481 if ((minLockAmount > pmtAmount))
481482 then throw(("amount is less then minLockAmount=" + toString(minLockAmount)))
482483 else if ((minLockDuration > duration))
483484 then throw(("passed duration is less then minLockDuration=" + toString(minLockDuration)))
484485 else if ((duration > maxLockDuration))
485486 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
486487 else if (if (userIsExisting)
487488 then ((iof(this, startBlockKEY) + iof(this, durationKEY)) >= lockStart)
488489 else false)
489490 then throw("there is an active lock - consider to use increaseLock")
490491 else if ((ioz(this, userAmountKEY) > 0))
491492 then throw(("there are locked WXs - consider to use increaseLock " + userAmountKEY))
492493 else {
493494 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
494495 let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
495496 let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
496497 let k = ai(gWxParamsResultList[0])
497498 let b = ai(gWxParamsResultList[1])
498499 let period = toString(ai(gWxParamsResultList[2]))
499500 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
500501 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
501502 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
502503 let h = if ((height > emissionEnd))
503504 then emissionEnd
504505 else height
505506 let dh = max([(h - emissionStart), 0])
506507 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
507508 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
508509 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
509510 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
510511 let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
511512 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
512513 let totalCachedGwxKEY = keyTotalCachedGwx()
513514 let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
514515 let arr = if (userIsExisting)
515516 then nil
516517 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
517- ((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
518+ $Tuple2(((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
518519 then 0
519- else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gWxAmountStart))])
520+ else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gWxAmountStart))]), gWxAmountStart)
520521 }
521522 }
522523 }
524+ }
525+
526+
527+@Callable(i)
528+func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
529+ let checkCaller = mustManager(i)
530+ if ((checkCaller == checkCaller))
531+ then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
532+ else throw("Strict value is not equal to itself.")
533+ }
534+
535+
536+
537+@Callable(i)
538+func lockRef (duration,referrerAddress,signature) = {
539+ let $t02296623031 = lockActions(i, duration)
540+ let lockActionsResult = $t02296623031._1
541+ let gWxAmountStart = $t02296623031._2
542+ let referralAddress = toString(i.caller)
543+ let refInv = if (if ((referrerAddress == ""))
544+ then true
545+ else (signature == base58''))
546+ then unit
547+ else invoke(referralsContractAddressOrFail, "createPair", [referralProgramName, referrerAddress, referralAddress, signature], nil)
548+ if ((refInv == refInv))
549+ then {
550+ let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
551+ if ((updateRefActivity == updateRefActivity))
552+ then $Tuple2(lockActionsResult, unit)
553+ else throw("Strict value is not equal to itself.")
554+ }
555+ else throw("Strict value is not equal to itself.")
556+ }
557+
558+
559+
560+@Callable(i)
561+func lock (duration) = {
562+ let $t02348923554 = lockActions(i, duration)
563+ let lockActionsResult = $t02348923554._1
564+ let gWxAmountStart = $t02348923554._2
565+ let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
566+ if ((updateRefActivity == updateRefActivity))
567+ then $Tuple2(lockActionsResult, unit)
568+ else throw("Strict value is not equal to itself.")
523569 }
524570
525571
526572
527573 @Callable(i)
528574 func increaseLock (deltaDuration) = {
529575 let cfgArray = readConfigArrayOrFail()
530576 let assetIdStr = cfgArray[IdxCfgAssetId]
531577 let assetId = fromBase58String(assetIdStr)
532578 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
533579 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
534- let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
535580 let pmtAmount = extractOptionalPaymentAmountOrFail(i, assetId)
536581 let userAddressStr = toString(i.caller)
537582 let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
538583 let userNumStr = userRecordArray[IdxLockUserNum]
539584 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
540585 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
541586 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
542587 let lockEnd = (lockStart + lockDuration)
543588 let remainingDuration = max([(lockEnd - height), 0])
544589 let userAmountNew = (userAmount + pmtAmount)
545590 let lockDurationNew = (remainingDuration + deltaDuration)
546591 if ((0 > deltaDuration))
547592 then throw("duration is less then zero")
548593 else if ((minLockDuration > lockDurationNew))
549594 then throw(("lockDurationNew is less then minLockDuration=" + toString(minLockDuration)))
550595 else if ((lockDurationNew > maxLockDuration))
551596 then throw(("deltaDuration + existedLockDuration is greater then maxLockDuration=" + toString(maxLockDuration)))
552597 else {
553598 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
554599 let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
555- let lockStartNew = height
556- let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
557- let k = ai(gWxParamsResultList[0])
558- let b = ai(gWxParamsResultList[1])
559- let period = toString(ai(gWxParamsResultList[2]))
560- let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
561- let emissionStart = iof(emissionContract, keyEmissionStartBlock())
562- let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
563- let h = if ((height > emissionEnd))
564- then emissionEnd
565- else height
566- let dh = max([(h - emissionStart), 0])
567- let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
568- let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
569- let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
570- let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
571- if ((0 > userBoostEmissionIntegral))
572- then throw("wrong calculations")
573- else {
574- let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
575- let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
576- let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
577- let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
578- let currUserGwx = calcCurrentGwxAmount(userAddressStr)
579- let gwxDiff = (gWxAmountStart - currUserGwx)
580- if ((0 > gwxDiff))
581- then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
600+ let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
601+ if ((updateRefActivity == updateRefActivity))
602+ then {
603+ let lockStartNew = height
604+ let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
605+ let k = ai(gWxParamsResultList[0])
606+ let b = ai(gWxParamsResultList[1])
607+ let period = toString(ai(gWxParamsResultList[2]))
608+ let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
609+ let emissionStart = iof(emissionContract, keyEmissionStartBlock())
610+ let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
611+ let h = if ((height > emissionEnd))
612+ then emissionEnd
613+ else height
614+ let dh = max([(h - emissionStart), 0])
615+ let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
616+ let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
617+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
618+ let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
619+ if ((0 > userBoostEmissionIntegral))
620+ then throw("wrong calculations")
582621 else {
583- let totalCachedGwxKEY = keyTotalCachedGwx()
584- let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
585- let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
586- let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
587- let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwx)
588- let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
589- let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
590- let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
591- (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStartNew, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gwxDiff))])
622+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
623+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
624+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
625+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
626+ let currUserGwx = calcCurrentGwxAmount(userAddressStr)
627+ let gwxDiff = (gWxAmountStart - currUserGwx)
628+ if ((0 > gwxDiff))
629+ then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
630+ else {
631+ let totalCachedGwxKEY = keyTotalCachedGwx()
632+ let totalCachedGwx = valueOrElse(getInteger(this, totalCachedGwxKEY), 0)
633+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
634+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
635+ let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwx)
636+ let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
637+ let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
638+ let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
639+ (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStartNew, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(totalCachedGwxKEY, (totalCachedGwx + gwxDiff))])
640+ }
592641 }
593642 }
643+ else throw("Strict value is not equal to itself.")
594644 }
595645 }
596646
597647
598648
599649 @Callable(i)
600650 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
601651 then throw("permissions denied")
602652 else {
603- let $t02692227024 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
604- let userBoostAvailable = $t02692227024._1
605- let dataState = $t02692227024._2
606- let debug = $t02692227024._3
653+ let $t02853328635 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
654+ let userBoostAvailable = $t02853328635._1
655+ let dataState = $t02853328635._2
656+ let debug = $t02853328635._3
607657 $Tuple2(dataState, [userBoostAvailable])
608658 }
609659
610660
611661
612662 @Callable(i)
613663 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
614- let $t02715627257 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
615- let userBoostAvailable = $t02715627257._1
616- let dataState = $t02715627257._2
617- let debug = $t02715627257._3
664+ let $t02876728868 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
665+ let userBoostAvailable = $t02876728868._1
666+ let dataState = $t02876728868._2
667+ let debug = $t02876728868._3
618668 $Tuple2(nil, [userBoostAvailable, debug])
619669 }
620670
621671
622672
623673 @Callable(i)
624674 func unlock (userAddress) = {
625675 let userRecordArray = readLockParamsRecordOrFail(userAddress)
626676 let userNumStr = userRecordArray[IdxLockUserNum]
627677 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
628678 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
629679 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
630680 let lockEnd = (lockStart + lockDuration)
631681 let cfgArray = readConfigArrayOrFail()
632682 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
633- let mathContract = addressFromStringValue(cfgArray[IdxCfgMathContract])
634683 if ((lockEnd >= height))
635684 then throw((("wait " + toString(lockEnd)) + " to unlock"))
636685 else if ((0 >= userAmount))
637686 then throw("nothing to unlock")
638687 else {
639688 let period = valueOrElse(getInteger(mathContract, keyNextPeriod()), 0)
640689 (((LockParamsEntry(userAddress, userNumStr, 0, lockStart, lockDuration, 0, 0, toString(period)) ++ StatsEntry(-(userAmount), 0, 0, -1)) :+ HistoryEntry("unlock", userAddress, userAmount, lockStart, lockDuration, 0, 0, i)) :+ ScriptTransfer(addressFromStringValue(userAddress), userAmount, assetId))
641690 }
642691 }
643692
644693
645694
646695 @Callable(i)
647696 func gwxUserInfoREADONLY (userAddress) = {
648697 let gwxAmount = calcCurrentGwxAmount(userAddress)
649698 $Tuple2(nil, [gwxAmount])
650699 }
651700
652701
653702
654703 @Callable(i)
655704 func getUserGwxAmountAtHeightREADONLY (userAddress,targetHeight) = {
656705 let gwxAmount = calcUserGwxAmountAtHeight(userAddress, targetHeight)
657706 $Tuple2(nil, gwxAmount)
658707 }
659708
660709
661710
662711 @Callable(i)
663712 func setManager (pendingManagerPublicKey) = {
664713 let checkCaller = mustManager(i)
665714 if ((checkCaller == checkCaller))
666715 then {
667716 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
668717 if ((checkManagerPublicKey == checkManagerPublicKey))
669718 then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
670719 else throw("Strict value is not equal to itself.")
671720 }
672721 else throw("Strict value is not equal to itself.")
673722 }
674723
675724
676725
677726 @Callable(i)
678727 func confirmManager () = {
679728 let pm = pendingManagerPublicKeyOrUnit()
680729 let hasPM = if (isDefined(pm))
681730 then true
682731 else throw("No pending manager")
683732 if ((hasPM == hasPM))
684733 then {
685734 let checkPM = if ((i.callerPublicKey == value(pm)))
686735 then true
687736 else throw("You are not pending manager")
688737 if ((checkPM == checkPM))
689738 then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
690739 else throw("Strict value is not equal to itself.")
691740 }
692741 else throw("Strict value is not equal to itself.")
693742 }
694743
695744
696745 @Verifier(tx)
697746 func verify () = {
698747 let targetPublicKey = match managerPublicKeyOrUnit() {
699748 case pk: ByteVector =>
700749 pk
701750 case _: Unit =>
702751 tx.senderPublicKey
703752 case _ =>
704753 throw("Match error")
705754 }
706755 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
707756 }
708757

github/deemru/w8io/786bc32 
95.17 ms