tx · 8Ataf1rnQc15scJLhso5qbXxkC587Ti3XnHjjTzaDVxJ

3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy:  -0.02300000 Waves

2023.01.10 13:06 [2398704] smart account 3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy > SELF 0.00000000 Waves

{ "type": 13, "id": "8Ataf1rnQc15scJLhso5qbXxkC587Ti3XnHjjTzaDVxJ", "fee": 2300000, "feeAssetId": null, "timestamp": 1673345278724, "version": 1, "sender": "3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy", "senderPublicKey": "9W33iCCNfmFxUbiC6XZcH5x7f6xfwC7Jb3BoExT5q2PV", "proofs": [ "441wCQJ6sGMK7Cnuh6ixpSudL5xdeEoFWf6YR19iZ2EnpuqAWQjFp4DjvHi8Et7Nrr1Bbhs4DdeRR1wpP9YpNQha" ], "script": "base64:BgKQJggCEggKBggIAQEBCBIFCgMBCAISAwoBARIDCgEBEgQKAggIEgQKAggIEgMKAQgSAwoBCBIDCgEIEgQKAggBEgASAwoBCBIAIgNTRVAiBlNDQUxFOCIFTVVMVDgiDlBPT0xXRUlHSFRNVUxUIgRzdHJmIgdhZGRyZXNzIgNrZXkiA2lveiIDaW9kIgpkZWZhdWx0VmFsIgNpb2YiA2FicyIDdmFsIgNhYWwiByRtYXRjaDAiCnZhbEFueUx5c3QiAmFpIgZ2YWxJbnQiG2tleVJlZmVycmFsc0NvbnRyYWN0QWRkcmVzcyIecmVmZXJyYWxzQ29udHJhY3RBZGRyZXNzT3JGYWlsIhZrZXlSZWZlcnJhbFByb2dyYW1OYW1lIhpyZWZlcnJhbFByb2dyYW1OYW1lRGVmYXVsdCITcmVmZXJyYWxQcm9ncmFtTmFtZSIRa2V5RmFjdG9yeUFkZHJlc3MiGElkeEZhY3RvcnlDZmdTdGFraW5nRGFwcCIZSWR4RmFjdG9yeUNmZ0Jvb3N0aW5nRGFwcCIUSWR4RmFjdG9yeUNmZ0lkb0RhcHAiFUlkeEZhY3RvcnlDZmdUZWFtRGFwcCIZSWR4RmFjdG9yeUNmZ0VtaXNzaW9uRGFwcCIVSWR4RmFjdG9yeUNmZ1Jlc3REYXBwIhlJZHhGYWN0b3J5Q2ZnU2xpcHBhZ2VEYXBwIhRJZHhGYWN0b3J5Q2ZnRGFvRGFwcCIaSWR4RmFjdG9yeUNmZ01hcmtldGluZ0RhcHAiGklkeEZhY3RvcnlDZmdHd3hSZXdhcmREYXBwIhZJZHhGYWN0b3J5Q2ZnQmlyZHNEYXBwIg1rZXlGYWN0b3J5Q2ZnIhprZXlGYWN0b3J5THAyQXNzZXRzTWFwcGluZyIKbHBBc3NldFN0ciIQa2V5RmFjdG9yeUxwTGlzdCIma2V5RmFjdG9yeUxwQXNzZXRUb1Bvb2xDb250cmFjdEFkZHJlc3MiFGtleUZhY3RvcnlQb29sV2VpZ2h0Ig9jb250cmFjdEFkZHJlc3MiG2tleUZhY3RvcnlQb29sV2VpZ2h0SGlzdG9yeSILcG9vbEFkZHJlc3MiA251bSIYcmVhZEZhY3RvcnlBZGRyZXNzT3JGYWlsIgpyZWFkTHBMaXN0IhRyZWFkRmFjdG9yeUNmZ09yRmFpbCIHZmFjdG9yeSIYZ2V0Qm9vc3RpbmdBZGRyZXNzT3JGYWlsIgpmYWN0b3J5Q2ZnIhhnZXRFbWlzc2lvbkFkZHJlc3NPckZhaWwiF2dldFN0YWtpbmdBZGRyZXNzT3JGYWlsIhlnZXRHd3hSZXdhcmRBZGRyZXNzT3JGYWlsIhNrZXlNYW5hZ2VyUHVibGljS2V5IhprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleSIea2V5RW1pc3Npb25SYXRlUGVyQmxvY2tDdXJyZW50IiFrZXlFbWlzc2lvblJhdGVQZXJCbG9ja01heEN1cnJlbnQiFWtleUVtaXNzaW9uU3RhcnRCbG9jayIba2V5RW1pc3Npb25EdXJhdGlvbkluQmxvY2tzIhNrZXlFbWlzc2lvbkVuZEJsb2NrIg1rZXlOZXh0UGVyaW9kIh9rZXlHd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0Ig1JZHhDZmdBc3NldElkIhNJZHhDZmdNaW5Mb2NrQW1vdW50IhVJZHhDZmdNaW5Mb2NrRHVyYXRpb24iFUlkeENmZ01heExvY2tEdXJhdGlvbiISSWR4Q2ZnTWF0aENvbnRyYWN0IglrZXlDb25maWciFXJlYWRDb25maWdBcnJheU9yRmFpbCIMbWF0aENvbnRyYWN0Ig1mb3JtYXRDb25maWdTIgdhc3NldElkIg1taW5Mb2NrQW1vdW50Ig9taW5Mb2NrRHVyYXRpb24iD21heExvY2tEdXJhdGlvbiIMZm9ybWF0Q29uZmlnIhZtYW5hZ2VyUHVibGljS2V5T3JVbml0IgFzIh1wZW5kaW5nTWFuYWdlclB1YmxpY0tleU9yVW5pdCILbXVzdE1hbmFnZXIiAWkiAnBkIgJwayIOSWR4TG9ja1VzZXJOdW0iDUlkeExvY2tBbW91bnQiDElkeExvY2tTdGFydCIPSWR4TG9ja0R1cmF0aW9uIg1JZHhMb2NrUGFyYW1LIg1JZHhMb2NrUGFyYW1CIhNrZXlMb2NrUGFyYW1zUmVjb3JkIgt1c2VyQWRkcmVzcyIacmVhZExvY2tQYXJhbXNSZWNvcmRPckZhaWwiF2Zvcm1hdExvY2tQYXJhbXNSZWNvcmRTIgd1c2VyTnVtIgZhbW91bnQiBXN0YXJ0IghkdXJhdGlvbiIGcGFyYW1LIgZwYXJhbUIiEGxhc3RVcGRUaW1lc3RhbXAiCWd3eEFtb3VudCIWZm9ybWF0TG9ja1BhcmFtc1JlY29yZCIOa2V5TmV4dFVzZXJOdW0iEmtleVVzZXIyTnVtTWFwcGluZyISa2V5TnVtMlVzZXJNYXBwaW5nIhZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50IhZrZXlMb2NrUGFyYW1TdGFydEJsb2NrIhRrZXlMb2NrUGFyYW1EdXJhdGlvbiINa2V5TG9ja1BhcmFtSyINa2V5TG9ja1BhcmFtQiIVa2V5TG9ja1BhcmFtQnlQZXJpb2RLIgZwZXJpb2QiFWtleUxvY2tQYXJhbUJ5UGVyaW9kQiIXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQiIGtleVN0YXRzTG9ja3NEdXJhdGlvblN1bUluQmxvY2tzIhJrZXlTdGF0c0xvY2tzQ291bnQiEmtleVN0YXRzVXNlcnNDb3VudCIga2V5VXNlckJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwiImtleVVzZXJMcEJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwiCWxwQXNzZXRJZCIXa2V5VXNlck1heEJvb3N0SU5URUdSQUwiGGtleVRvdGFsTWF4Qm9vc3RJTlRFR1JBTCIha2V5VXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsIhNrZXlVc2VyQm9vc3RDbGFpbWVkIhFrZXlUb3RhbENhY2hlZEd3eCIba2V5VG90YWxDYWNoZWRHd3hDb3JyZWN0aXZlIg9mYWN0b3J5Q29udHJhY3QiEGVtaXNzaW9uQ29udHJhY3QiD3N0YWtpbmdDb250cmFjdCIRZ3d4UmV3YXJkQ29udHJhY3QiEWdldFRvdGFsQ2FjaGVkR3d4Igdjb3JyZWN0IhlrZXlWb3RpbmdFbWlzc2lvbkNvbnRyYWN0IhZ2b3RpbmdFbWlzc2lvbkNvbnRyYWN0IhFrZXlDdXJyZW50RXBvY2hVaSIOY3VycmVudEVwb2NoVWkiDmtleVRhcmdldEVwb2NoIhF0YXJnZXRFcG9jaE9wdGlvbiIRdG90YWxDYWNoZWRHd3hSYXciFWlzQ29ycmVjdGlvbkFjdGl2YXRlZCIKY29ycmVjdGl2ZSIMSGlzdG9yeUVudHJ5IgR0eXBlIgR1c2VyIglsb2NrU3RhcnQiAWsiAWIiCmhpc3RvcnlLRVkiC2hpc3RvcnlEQVRBIgpTdGF0c0VudHJ5Ig50b3RhbExvY2tlZEluYyILZHVyYXRpb25JbmMiDGxvY2tDb3VudEluYyINdXNlcnNDb3VudEluYyIbbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzS0VZIg1sb2Nrc0NvdW50S0VZIg11c2Vyc0NvdW50S0VZIg50b3RhbEFtb3VudEtFWSIYbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzIgpsb2Nrc0NvdW50Igp1c2Vyc0NvdW50Igt0b3RhbEFtb3VudCINY2FsY0d3eEFtb3VudCIEa1JhdyIEYlJhdyIBaCIFU0NBTEUiD0xvY2tQYXJhbXNFbnRyeSINdXNlckFtb3VudEtFWSINc3RhcnRCbG9ja0tFWSILZHVyYXRpb25LRVkiBGtLRVkiBGJLRVkiDGtCeVBlcmlvZEtFWSIMYkJ5UGVyaW9kS0VZIiJleHRyYWN0T3B0aW9uYWxQYXltZW50QW1vdW50T3JGYWlsIg9leHBlY3RlZEFzc2V0SWQiA3BtdCIZY2FsY1VzZXJHd3hBbW91bnRBdEhlaWdodCIMdGFyZ2V0SGVpZ2h0IgVFTVBUWSISdXNlcjJOdW1NYXBwaW5nS0VZIg1nd3hBbW91bnRDYWxjIhRjYWxjQ3VycmVudEd3eEFtb3VudCIUaW50ZXJuYWxDbGFpbVd4Qm9vc3QiDGxwQXNzZXRJZFN0ciIOdXNlckFkZHJlc3NTdHIiCHJlYWRPbmx5IhF1c2VyUmVjb3JkT3JFbXB0eSIPdXNlclJlY29yZEFycmF5Igp1c2VyTnVtU3RyIhxnd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0IghFTVBUWVNUUiINJHQwMTQ5NjUxNTUzMyIOcG9vbEFkZHJlc3NTdHIiA3B3MSIDcHcwIgtwb29sV2VpZ2h0MCILcG9vbFdlaWdodDEiEnd4RW1pc3Npb25QZXJCbG9jayINZW1pc3Npb25TdGFydCILZW1pc3Npb25FbmQiAmRoIiJ1c2VyTHBCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZIiB1c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbEtFWSIddXNlckJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWwiFWJvb3N0RW1pc3Npb25JbnRlZ3JhbCIZdXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbCIDdWRoIgZ1TGFzdEgiBHVkaDAiBHVkaDEiF3VzZXJNYXhCb29zdEludGVncmFsS0VZIhh0b3RhbE1heEJvb3N0SW50ZWdyYWxLRVkiD3VzZXJNYXhCb29zdEludCIQdG90YWxNYXhCb29zdEludCIXdG90YWxDYWNoZWRHd3hDb3JyZWN0ZWQiC3VzZXJDdXJyR3d4IiF1c2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWxLRVkiHnVzZXJCb29zdEF2YWxpYWJsZVRvQ2xhaW1Ub3RhbCIadXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDAiGnVzZXJCb29zdEVtaXNzaW9uSW50ZWdyYWwxIh5wb29sVXNlckJvb3N0RW1pc3Npb25JbnRlZ3JhbDAiHnBvb2xVc2VyQm9vc3RFbWlzc2lvbkludGVncmFsMSIidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MCIidXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3MSIhdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsTmV3IhN1c2VyQm9vc3RDbGFpbWVkS0VZIhB1c2VyQm9vc3RDbGFpbWVkIhJ1c2VyQm9vc3RBdmFpbGFibGUiCWRhdGFTdGF0ZSIFZGVidWciC2xvY2tBY3Rpb25zIghjZmdBcnJheSIKYXNzZXRJZFN0ciIJcG10QW1vdW50Ig5uZXh0VXNlck51bUtFWSIOdXNlcklzRXhpc3RpbmciB2NvZWZmWDgiDmdXeEFtb3VudFN0YXJ0IhNnV3hQYXJhbXNSZXN1bHRMaXN0IgNhcnIiEWZhY3RvcnlBZGRyZXNzU3RyIg5sb2NrQXNzZXRJZFN0ciILbWluRHVyYXRpb24iC21heER1cmF0aW9uIgtjaGVja0NhbGxlciIPcmVmZXJyZXJBZGRyZXNzIglzaWduYXR1cmUiDSR0MDIzODkyMjM5NTciEWxvY2tBY3Rpb25zUmVzdWx0Ig9yZWZlcnJhbEFkZHJlc3MiBnJlZkludiIRdXBkYXRlUmVmQWN0aXZpdHkiDSR0MDI0NDE1MjQ0ODAiDWRlbHRhRHVyYXRpb24iCnVzZXJBbW91bnQiDGxvY2tEdXJhdGlvbiIHbG9ja0VuZCIRcmVtYWluaW5nRHVyYXRpb24iDXVzZXJBbW91bnROZXciD2xvY2tEdXJhdGlvbk5ldyIMbG9ja1N0YXJ0TmV3IgtjdXJyVXNlckd3eCIHZ3d4RGlmZiISdXNlck1heEJvb3N0SW50TmV3IhhyZW1haW5pbmdVc2VyTWF4Qm9vc3RJbnQiE3VzZXJNYXhCb29zdEludERpZmYiDSR0MDI5NDYxMjk1NjMiDSR0MDI5Njk1Mjk3OTYiEHVzZXJSZWNvcmRPcHRpb24iEG1heERlbHRhRHVyYXRpb24iF3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5IhVjaGVja01hbmFnZXJQdWJsaWNLZXkiAnBtIgVoYXNQTSIHY2hlY2tQTSICdHgiBnZlcmlmeSIPdGFyZ2V0UHVibGljS2V5bgABYQICX18AAWIACAABYwCAwtcvAAFkBQFjAQFlAgFmAWcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQFmBQFnCQCsAgIJAKwCAgIPbWFuZGF0b3J5IHRoaXMuBQFnAg8gaXMgbm90IGRlZmluZWQBAWgCAWYBZwkBC3ZhbHVlT3JFbHNlAgkAmggCBQFmBQFnAAABAWkDAWYBZwFqCQELdmFsdWVPckVsc2UCCQCaCAIFAWYFAWcFAWoBAWsCAWYBZwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFAWYFAWcJAKwCAgkArAICAg9tYW5kYXRvcnkgdGhpcy4FAWcCDyBpcyBub3QgZGVmaW5lZAEBbAEBbQMJAGYCAAAFAW0JAQEtAQUBbQUBbQEBbgEBbQQBbwUBbQMJAAECBQFvAglMaXN0W0FueV0EAXAFAW8FAXAJAAIBAhtmYWlsIHRvIGNhc3QgaW50byBMaXN0W0FueV0BAXEBAW0EAW8FAW0DCQABAgUBbwIDSW50BAFyBQFvBQFyCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQFzAAkAuQkCCQDMCAICBCVzJXMJAMwIAgIGY29uZmlnCQDMCAICGHJlZmVycmFsc0NvbnRyYWN0QWRkcmVzcwUDbmlsBQFhAAF0CQERQGV4dHJOYXRpdmUoMTA2MikBCQEBZQIFBHRoaXMJAQFzAAABdQkAuQkCCQDMCAICBCVzJXMJAMwIAgIIcmVmZXJyYWwJAMwIAgILcHJvZ3JhbU5hbWUFA25pbAUBYQABdgIGd3hsb2NrAAF3CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAXUFAXYBAXgAAhwlcyVzX19jb25maWdfX2ZhY3RvcnlBZGRyZXNzAAF5AAEAAXoAAgABQQADAAFCAAQAAUMABQABRAAGAAFFAAcAAUYACAABRwAJAAFIAAoAAUkACwEBSgACESVzX19mYWN0b3J5Q29uZmlnAQFLAQFMCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAIFAUwJAMwIAgIebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQNuaWwFAWEBAU0AAhAlc19fbHBUb2tlbnNMaXN0AQFOAQFMCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAIFAUwJAMwIAgIebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQNuaWwFAWEBAU8BAVAJALkJAgkAzAgCAgQlcyVzCQDMCAICCnBvb2xXZWlnaHQJAMwIAgUBUAUDbmlsBQFhAQFRAgFSAVMJAKwCAgkArAICCQCsAgICEiVzJXNfX3Bvb2xXZWlnaHRfXwUBUgICX18JAKQDAQUBUwEBVAAJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQFlAgUEdGhpcwkBAXgAAQFVAAkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIJAQFUAAkBAU0AAgAFAWEBAVYBAVcJALUJAgkBAWUCBQFXCQEBSgAFAWEBAVgBAVkJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUBWQUBegEBWgEBWQkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQFZBQFDAQJhYQEBWQkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQFZBQF5AQJhYgEBWQkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQFZBQFIAQJhYwACFCVzX19tYW5hZ2VyUHVibGljS2V5AQJhZAACGyVzX19wZW5kaW5nTWFuYWdlclB1YmxpY0tleQECYWUAAhslcyVzX19yYXRlUGVyQmxvY2tfX2N1cnJlbnQBAmFmAAIeJXMlc19fcmF0ZVBlckJsb2NrTWF4X19jdXJyZW50AQJhZwACGiVzJXNfX2VtaXNzaW9uX19zdGFydEJsb2NrAQJhaAACGCVzJXNfX2VtaXNzaW9uX19kdXJhdGlvbgECYWkAAhglcyVzX19lbWlzc2lvbl9fZW5kQmxvY2sBAmFqAAIOJXNfX25leHRQZXJpb2QBAmFrAAIoJXMlc19fZ3d4UmV3YXJkRW1pc3Npb25QYXJ0X19zdGFydEhlaWdodAACYWwAAQACYW0AAgACYW4AAwACYW8ABAACYXAABQECYXEAAgolc19fY29uZmlnAQJhcgAJALUJAgkBAWUCBQR0aGlzCQECYXEABQFhAAJhcwkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCCQECYXIABQJhcAECYXQFAmF1AmF2AmF3AmF4AmFzCQC5CQIJAMwIAgIIJXMlZCVkJWQJAMwIAgUCYXUJAMwIAgUCYXYJAMwIAgUCYXcJAMwIAgUCYXgJAMwIAgUCYXMFA25pbAUBYQECYXkFAmF1AmF2AmF3AmF4AmFzCQECYXQFBQJhdQkApAMBBQJhdgkApAMBBQJhdwkApAMBBQJheAUCYXMBAmF6AAQBbwkAoggBCQECYWMAAwkAAQIFAW8CBlN0cmluZwQCYUEFAW8JANkEAQUCYUEDCQABAgUBbwIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJhQgAEAW8JAKIIAQkBAmFkAAMJAAECBQFvAgZTdHJpbmcEAmFBBQFvCQDZBAEFAmFBAwkAAQIFAW8CBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgECYUMBAmFEBAJhRQkAAgECEVBlcm1pc3Npb24gZGVuaWVkBAFvCQECYXoAAwkAAQIFAW8CCkJ5dGVWZWN0b3IEAmFGBQFvAwkAAAIIBQJhRA9jYWxsZXJQdWJsaWNLZXkFAmFGBgUCYUUDCQABAgUBbwIEVW5pdAMJAAACCAUCYUQGY2FsbGVyBQR0aGlzBgUCYUUJAAIBAgtNYXRjaCBlcnJvcgACYUcAAQACYUgAAgACYUkAAwACYUoABAACYUsABQACYUwABgECYU0BAmFOCQC5CQIJAMwIAgIKJXMlc19fbG9jawkAzAgCBQJhTgUDbmlsBQFhAQJhTwECYU4JALUJAgkBAWUCBQR0aGlzCQECYU0BBQJhTgUBYQECYVAIAmFRAmFSAmFTAmFUAmFVAmFWAmFXAmFYCQC5CQIJAMwIAgIQJWQlZCVkJWQlZCVkJWQlZAkAzAgCBQJhUQkAzAgCBQJhUgkAzAgCBQJhUwkAzAgCBQJhVAkAzAgCBQJhVQkAzAgCBQJhVgkAzAgCBQJhVwkAzAgCBQJhWAUDbmlsBQFhAQJhWQcCYVECYVICYVMCYVQCYVUCYVYCYVgJAQJhUAgFAmFRCQCkAwEFAmFSCQCkAwEFAmFTCQCkAwEFAmFUCQCkAwEFAmFVCQCkAwEFAmFWCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQCkAwEFAmFYAQJhWgACDyVzX19uZXh0VXNlck51bQECYmEBAmFOCQC5CQIJAMwIAgIZJXMlcyVzX19tYXBwaW5nX191c2VyMm51bQkAzAgCBQJhTgUDbmlsBQFhAQJiYgEBUwkAuQkCCQDMCAICGSVzJXMlc19fbWFwcGluZ19fbnVtMnVzZXIJAMwIAgUBUwUDbmlsBQFhAQJiYwECYVEJALkJAgkAzAgCAhYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQDMCAIFAmFRCQDMCAICBmFtb3VudAUDbmlsBQFhAQJiZAECYVEJALkJAgkAzAgCAhYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQDMCAIFAmFRCQDMCAICBXN0YXJ0BQNuaWwFAWEBAmJlAQJhUQkAuQkCCQDMCAICFiVzJWQlc19fcGFyYW1CeVVzZXJOdW0JAMwIAgUCYVEJAMwIAgIIZHVyYXRpb24FA25pbAUBYQECYmYBAmFRCQC5CQIJAMwIAgIWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkAzAgCBQJhUQkAzAgCAgFrBQNuaWwFAWEBAmJnAQJhUQkAuQkCCQDMCAICFiVzJWQlc19fcGFyYW1CeVVzZXJOdW0JAMwIAgUCYVEJAMwIAgIBYgUDbmlsBQFhAQJiaAICYVECYmkJALkJAgkAzAgCAhclcyVkJXMlZF9fcGFyYW1CeVBlcmlvZAkAzAgCBQJhUQkAzAgCAgFrCQDMCAIFAmJpBQNuaWwFAWEBAmJqAgJhUQJiaQkAuQkCCQDMCAICFyVzJWQlcyVkX19wYXJhbUJ5UGVyaW9kCQDMCAIFAmFRCQDMCAICAWIJAMwIAgUCYmkFA25pbAUBYQECYmsAAh4lcyVzX19zdGF0c19fYWN0aXZlVG90YWxMb2NrZWQBAmJsAAIlJXMlc19fc3RhdHNfX2xvY2tzRHVyYXRpb25TdW1JbkJsb2NrcwECYm0AAhclcyVzX19zdGF0c19fbG9ja3NDb3VudAECYm4AAh0lcyVzX19zdGF0c19fYWN0aXZlVXNlcnNDb3VudAECYm8BAmFRCQC5CQIJAMwIAgIeJXMlZF9fdXNlckJvb3N0RW1pc3Npb25MYXN0SW50CQDMCAIFAmFRBQNuaWwFAWEBAmJwAgJhUQJicQkAuQkCCQDMCAICHiVzJWRfX3VzZXJCb29zdEVtaXNzaW9uTGFzdEludAkAzAgCBQJhUQkAzAgCBQJicQUDbmlsBQFhAQJicgECYVEJALkJAgkAzAgCAhElcyVkX19tYXhCb29zdEludAkAzAgCBQJhUQUDbmlsBQFhAQJicwACGCVzJXNfX21heEJvb3N0SW50X190b3RhbAECYnQBAmFRCQC5CQIJAMwIAgIkJXMlZF9fdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQDMCAIFAmFRBQNuaWwFAWEBAmJ1AQJhUQkAuQkCCQDMCAICFiVzJWRfX3VzZXJCb29zdENsYWltZWQJAMwIAgUCYVEFA25pbAUBYQECYnYAAhYlcyVzX19nd3hDYWNoZWRfX3RvdGFsAQJidwACHCVzX19nd3hDYWNoZWRUb3RhbENvcnJlY3RpdmUAAmJ4CQEBVAAAAVkJAQFWAQUCYngAAmJ5CQEBWgEFAVkAAmJ6CQECYWEBBQFZAAJiQQkBAmFiAQUBWQECYkIBAmJDBAJiRAkAuQkCCQDMCAICAiVzCQDMCAICFnZvdGluZ0VtaXNzaW9uQ29udHJhY3QFA25pbAUBYQQCYkUJARFAZXh0ck5hdGl2ZSgxMDYyKQEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFAmJ4BQJiRAQCYkYJALkJAgkAzAgCAgIlcwkAzAgCAg5jdXJyZW50RXBvY2hVaQUDbmlsBQFhBAJiRwkBEUBleHRyTmF0aXZlKDEwNTApAgUCYkUFAmJGBAJiSAkAuQkCCQDMCAICBCVzJXMJAMwIAgIpdG90YWxDYWNoZWRHd3hDb3JyZWN0aW9uX19hY3RpdmF0aW9uRXBvY2gFA25pbAUBYQQCYkkJAJoIAgUEdGhpcwUCYkgEAmJKCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJidgAAAAQCYksDCQEJaXNEZWZpbmVkAQUCYkkJAGcCBQJiRwkBBXZhbHVlAQUCYkkHBAJiTAMDBQJiSwUCYkMHCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQJidwAAAAAACQCWAwEJAMwIAgAACQDMCAIJAGQCBQJiSgUCYkwFA25pbAECYk0IAmJOAmJPAmFSAmJQAmFUAmJRAmJSAmFEBAJiUwkAuQkCCQDMCAICESVzJXMlcyVzX19oaXN0b3J5CQDMCAIFAmJOCQDMCAIFAmJPCQDMCAIJANgEAQgFAmFEDXRyYW5zYWN0aW9uSWQFA25pbAUBYQQCYlQJALkJAgkAzAgCAg4lZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sGaGVpZ2h0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApAMBBQJhUgkAzAgCCQCkAwEFAmJQCQDMCAIJAKQDAQUCYVQJAMwIAgkApAMBBQJiUQkAzAgCCQCkAwEFAmJSBQNuaWwFAWEJAQtTdHJpbmdFbnRyeQIFAmJTBQJiVAECYlUEAmJWAmJXAmJYAmJZBAJiWgkBAmJsAAQCY2EJAQJibQAEAmNiCQECYm4ABAJjYwkBAmJrAAQCY2QJAQFoAgUEdGhpcwUCYloEAmNlCQEBaAIFBHRoaXMFAmNhBAJjZgkBAWgCBQR0aGlzBQJjYgQCY2cJAQFoAgUEdGhpcwUCY2MJAMwIAgkBDEludGVnZXJFbnRyeQIFAmJaCQBkAgUCY2QFAmJXCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjYQkAZAIFAmNlBQJiWAkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY2IJAGQCBQJjZgUCYlkJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNjCQBkAgUCY2cFAmJWBQNuaWwBAmNoAwJjaQJjagJjawQCY2wA6AcJAGkCCQBkAgkAaAIFAmNpBQJjawUCY2oFAmNsAQJjbQgCYU4CYVECYVICYVMCYVQCYlECYlICYmkEAmNuCQECYmMBBQJhUQQCY28JAQJiZAEFAmFRBAJjcAkBAmJlAQUCYVEEAmNxCQECYmYBBQJhUQQCY3IJAQJiZwEFAmFRBAJjcwkBAmJoAgUCYVEFAmJpBAJjdAkBAmJqAgUCYVEFAmJpBAJhWAkBAmNoAwUCYlEFAmJSBQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNuBQJhUgkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY28FAmFTCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjcAUCYVQJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNxBQJiUQkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY3IFAmJSCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjcwUCYlEJAMwIAgkBDEludGVnZXJFbnRyeQIFAmN0BQJiUgkAzAgCCQELU3RyaW5nRW50cnkCCQECYU0BBQJhTgkBAmFZBwUCYVEFAmFSBQJhUwUCYVQFAmJRBQJiUgUCYVgFA25pbAECY3UCAmFEAmN2AwkAZgIJAJADAQgFAmFECHBheW1lbnRzAAEJAAIBAhtvbmx5IG9uZSBwYXltZW50IGlzIGFsbG93ZWQDCQAAAgkAkAMBCAUCYUQIcGF5bWVudHMAAAAABAJjdwkAkQMCCAUCYUQIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQJjdwdhc3NldElkBQJjdgkAAgECG2ludmFsaWQgYXNzZXQgaWQgaW4gcGF5bWVudAgFAmN3BmFtb3VudAECY3gCAmFOAmN5BAJjegIFZW1wdHkEAmNBCQECYmEBBQJhTgQCYVEJAQt2YWx1ZU9yRWxzZQIJAKIIAQUCY0EFAmN6BAJiUQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYmYBBQJhUQAABAJiUgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYmcBBQJhUQAABAJjQgkBAmNoAwUCYlEFAmJSBQJjeQQCYVgDCQBmAgAABQJjQgAABQJjQgUCYVgBAmNDAQJhTgkBAmN4AgUCYU4FBmhlaWdodAECY0QDAmNFAmNGAmNHBAJjegIFRU1QVFkEAmNICQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJAQJhTQEFAmNGBQJjegMJAAACBQJjSAUCY3oJAJUKAwAABQNuaWwCFXVzZXJSZWNvcmQ6OmlzOjplbXB0eQQCY0kJALUJAgUCY0gFAWEEAmNKCQCRAwIFAmNJBQJhRwQCY0sJAQt2YWx1ZU9yRWxzZQIJAJoIAgUCYkEJAQJhawAAAAQCY0wCBWVtcHR5BAJjTQMJAQIhPQIFAmNFBQJjTAQCY04JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQJieAkBAUsBBQJjRQkArAICAhV1bnN1cHBvcnRlZCBscCBhc3NldCAFAmNFBAJjTwkBEUBleHRyTmF0aXZlKDEwNTApAgUCYngJAQFPAQUCY04EAmNQCQELdmFsdWVPckVsc2UCCQCaCAIFAmJ4CQEBUQIFAmNOAAAFAmNPCQCUCgIFAmNQBQJjTwMFAmNHCQCUCgIAAAAACQACAQkArAICAihub3QgcmVhZG9ubHkgbW9kZTogdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQJjRQQCY1EIBQJjTQJfMQQCY1IIBQJjTQJfMgQCY1MJAQFrAgUCYnkJAQJhZQAEAmNUCQEBawIFAmJ5CQECYWcABAJjVQkBAWsCBQJieQkBAmFpAAQCY2sDCQBmAgUGaGVpZ2h0BQJjVQUCY1UFBmhlaWdodAQCY1YJAJYDAQkAzAgCCQBlAgUCY2sFAmNUCQDMCAIAAAUDbmlsBAJjVwkBAmJwAgUCY0oFAmNFBAJjWAkBAmJvAQUCY0oEAmNZCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAmNXCQEBaAIFBHRoaXMFAmNYBAJjWgkAaQIJAGgCCQBoAgUCY1MFAmNWAAIAAwQCZGEJAGUCBQJjWgUCY1kEAmRiCQBrAwUCZGEAAwkAaAIAAgUCY1MEAmRjCQBlAgUCY2sFAmRiBAJkZAkAlgMBCQDMCAIJAGUCBQJjSwUCZGMJAMwIAgAABQNuaWwEAmRlCQBlAgkAZQIFAmNrBQJkYwUCZGQDAwMJAGYCAAAFAmRjBgkAZgIAAAUCZGUGCQBnAgkBAWwBCQBlAgkAZAIFAmRkBQJkZQUCZGIAAQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIWaW52YWxpZCB1ZGggY2FsYzogdWRoPQkApAMBBQJkYgIIIHVMYXN0SD0JAKQDAQUCZGMCBiB1ZGgwPQkApAMBBQJkZAIGIHVkaDE9CQCkAwEFAmRlAwkAZgIAAAUCZGEJAAIBAhJ3cm9uZyBjYWxjdWxhdGlvbnMEAmRmCQECYnIBBQJjSgQCZGcJAQJicwAEAmRoCQEBaAIFBHRoaXMFAmRmBAJkaQkBAWgCBQR0aGlzBQJkZwQCZGoJAQJiQgEGBAJkawkBAmNDAQUCY0YEAmRsCQECYnQBBQJjSgQCZG0JAQFoAgUEdGhpcwUCZGwEAmRuAwkAAAIFAmRiAAAAAAkAawMFAmRhBQJkZAUCZGIEAmRvAwkAAAIFAmRiAAAAAAkAawMFAmRhBQJkZQUCZGIEAmRwCQBrAwUCZG4FAmNRBQFkBAJkcQkAawMFAmRvBQJjUgUBZAQCZHIDCQAAAgUCZGoAAAAACQBrAwUCZHAFAmRrBQJkagQCZHMDCQAAAgUCZGoAAAAACQBrAwUCZHEFAmRrBQJkagQCZHQJAGQCBQJkcgUCZHMEAmR1CQECYnUBBQJjSgQCZHYJAQFoAgUEdGhpcwUCZHUEAmR3CQBlAgUCZHQFAmR2BAJkeAkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY1cFAmNaBQNuaWwEAmR5CQC5CQIJAMwIAgkApAMBBQJjWQkAzAgCCQCkAwEFAmRhCQDMCAIJAKQDAQUCZHYJAMwIAgkApAMBBQJkdwkAzAgCCQCkAwEFAmNRCQDMCAIJAKQDAQUCY1IJAMwIAgkApAMBBQJjawkAzAgCCQCkAwEFAmRiCQDMCAIJAKQDAQUCZGMJAMwIAgkApAMBBQJkZAkAzAgCCQCkAwEFAmRlCQDMCAIJAKQDAQUCZGsJAMwIAgkApAMBBQJkagUDbmlsAgE6CQCVCgMFAmR0BQJkeAUCZHkBAmR6AgJhRAJhVAQCZEEJAQJhcgAEAmRCCQCRAwIFAmRBBQJhbAQCYXUJANkEAQUCZEIEAmF2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZEEFAmFtBAJhdwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRBBQJhbgQCYXgJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkQQUCYW8DCQECIT0CCQCQAwEIBQJhRAhwYXltZW50cwABCQACAQI0aW52YWxpZCBwYXltZW50IC0gZXhhY3Qgb25lIHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQCY3cJAJEDAggFAmFECHBheW1lbnRzAAAEAmRDCAUCY3cGYW1vdW50AwkBAiE9AgUCYXUJAQV2YWx1ZQEIBQJjdwdhc3NldElkCQACAQkArAICCQCsAgICHmludmFsaWQgYXNzZXQgaXMgaW4gcGF5bWVudCAtIAUCZEICDCBpcyBleHBlY3RlZAQCZEQJAQJhWgAEAmNGCQClCAEIBQJhRAZjYWxsZXIEAmRFCQEJaXNEZWZpbmVkAQkAoggBCQECYmEBBQJjRgQCY0oDBQJkRQkBBXZhbHVlAQkAoggBCQECYmEBBQJjRgkApAMBCQEBawIFBHRoaXMFAmREBAJhUQkBDXBhcnNlSW50VmFsdWUBBQJjSgQCYlAFBmhlaWdodAQCY28JAQJiZAEFAmNKBAJjcAkBAmJlAQUCY0oEAmNuCQECYmMBBQJjSgMJAGYCBQJhdgUCZEMJAAIBCQCsAgICImFtb3VudCBpcyBsZXNzIHRoZW4gbWluTG9ja0Ftb3VudD0JAKQDAQUCYXYDCQBmAgUCYXcFAmFUCQACAQkArAICAi1wYXNzZWQgZHVyYXRpb24gaXMgbGVzcyB0aGVuIG1pbkxvY2tEdXJhdGlvbj0JAKQDAQUCYXcDCQBmAgUCYVQFAmF4CQACAQkArAICAjBwYXNzZWQgZHVyYXRpb24gaXMgZ3JlYXRlciB0aGVuIG1heExvY2tEdXJhdGlvbj0JAKQDAQUCYXgDAwUCZEUJAGcCCQBkAgkBAWsCBQR0aGlzBQJjbwkBAWsCBQR0aGlzBQJjcAUCYlAHCQACAQI2dGhlcmUgaXMgYW4gYWN0aXZlIGxvY2sgLSBjb25zaWRlciB0byB1c2UgaW5jcmVhc2VMb2NrAwkAZgIJAQFoAgUEdGhpcwUCY24AAAkAAgEJAKwCAgI0dGhlcmUgYXJlIGxvY2tlZCBXWHMgLSBjb25zaWRlciB0byB1c2UgaW5jcmVhc2VMb2NrIAUCY24EAmRGCQBrAwUCYVQFAWMFAmF4BAJkRwkAawMFAmRDBQJkRgUBYwQCZEgJAQFuAQkA/AcEBQJhcwIVY2FsY0d3eFBhcmFtc1JFQURPTkxZCQDMCAIFAmRHCQDMCAIFAmJQCQDMCAIFAmFUBQNuaWwFA25pbAQCYlEJAQFxAQkAkQMCBQJkSAAABAJiUgkBAXEBCQCRAwIFAmRIAAEEAmJpCQCkAwEJAQFxAQkAkQMCBQJkSAACBAJjUwkBAWsCBQJieQkBAmFlAAQCY1QJAQFrAgUCYnkJAQJhZwAEAmNVCQEBawIFAmJ5CQECYWkABAJjawMJAGYCBQZoZWlnaHQFAmNVBQJjVQUGaGVpZ2h0BAJjVgkAlgMBCQDMCAIJAGUCBQJjawUCY1QJAMwIAgAABQNuaWwEAmNYCQECYm8BBQJjSgQCY1oJAGkCCQBoAgkAaAIFAmNTBQJjVgACAAMEAmRmCQECYnIBBQJjSgQCZGcJAQJicwAEAmRoCQBpAgkAaAIFAmRHBQJhVAACBAJkaQkBAWgCBQR0aGlzBQJkZwQCYkoJAQJiQgEHBAJkSQMFAmRFBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIFAmRECQBkAgUCYVEAAQkAzAgCCQELU3RyaW5nRW50cnkCCQECYmEBBQJjRgUCY0oJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmJiAQUCY0oFAmNGBQNuaWwJAJQKAgkAzggCCQDNCAIJAM4IAgkAzggCBQJkSQkBAmNtCAUCY0YFAmNKBQJkQwUCYlAFAmFUBQJiUQUCYlIFAmJpCQECYlUEBQJkQwUCYVQAAQMFAmRFAAAAAQkBAmJNCAIEbG9jawUCY0YFAmRDBQJiUAUCYVQFAmJRBQJiUgUCYUQJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNYBQJjWgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmJ2AAkAZAIFAmJKBQJkRwUDbmlsBQJkRw0CYUQBC2NvbnN0cnVjdG9yBgJkSgJkSwJhdgJkTAJkTQJhcwQCZE4JAQJhQwEFAmFEAwkAAAIFAmROBQJkTgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYVoAAAAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFxAAkBAmF5BQUCZEsFAmF2BQJkTAUCZE0FAmFzCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQF4AAUCZEoFA25pbAkBAmJVBAAAAAAAAAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFEAQdsb2NrUmVmAwJhVAJkTwJkUAQCZFEJAQJkegIFAmFEBQJhVAQCZFIIBQJkUQJfMQQCZEcIBQJkUQJfMgQCZFMJAKUIAQgFAmFEBmNhbGxlcgQCZFQDAwkAAAIFAmRPAgAGCQAAAgUCZFABAAUEdW5pdAkA/AcEBQF0AgpjcmVhdGVQYWlyCQDMCAIFAXcJAMwIAgUCZE8JAMwIAgUCZFMJAMwIAgUCZFAFA25pbAUDbmlsAwkAAAIFAmRUBQJkVAQCZFUJAPwHBAUCYXMCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUCYUQGY2FsbGVyCQDMCAIFAmRHBQNuaWwFA25pbAMJAAACBQJkVQUCZFUJAJQKAgUCZFIFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYUQBBGxvY2sBAmFUBAJkVgkBAmR6AgUCYUQFAmFUBAJkUggFAmRWAl8xBAJkRwgFAmRWAl8yBAJkVQkA/AcEBQJhcwIWdXBkYXRlUmVmZXJyYWxBY3Rpdml0eQkAzAgCCQClCAEIBQJhRAZjYWxsZXIJAMwIAgUCZEcFA25pbAUDbmlsAwkAAAIFAmRVBQJkVQkAlAoCBQJkUgUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhRAEMaW5jcmVhc2VMb2NrAQJkVwQCZEEJAQJhcgAEAmRCCQCRAwIFAmRBBQJhbAQCYXUJANkEAQUCZEIEAmF3CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZEEFAmFuBAJheAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRBBQJhbwQCZEMJAQJjdQIFAmFEBQJhdQQCY0YJAKUIAQgFAmFEBmNhbGxlcgQCY0kJAQJhTwEFAmNGBAJjSgkAkQMCBQJjSQUCYUcEAmRYCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY0kFAmFIBAJiUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmNJBQJhSQQCZFkJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjSQUCYUoEAmRaCQBkAgUCYlAFAmRZBAJlYQkAlgMBCQDMCAIJAGUCBQJkWgUGaGVpZ2h0CQDMCAIAAAUDbmlsBAJlYgkAZAIFAmRYBQJkQwQCZWMJAGQCBQJlYQUCZFcDCQBmAgAABQJkVwkAAgECGmR1cmF0aW9uIGlzIGxlc3MgdGhlbiB6ZXJvAwkAZgIFAmF3BQJlYwkAAgEJAKwCAgItbG9ja0R1cmF0aW9uTmV3IGlzIGxlc3MgdGhlbiBtaW5Mb2NrRHVyYXRpb249CQCkAwEFAmF3AwkAZgIFAmVjBQJheAkAAgEJAKwCAgJEZGVsdGFEdXJhdGlvbiArIGV4aXN0ZWRMb2NrRHVyYXRpb24gaXMgZ3JlYXRlciB0aGVuIG1heExvY2tEdXJhdGlvbj0JAKQDAQUCYXgEAmRGCQBrAwUCZWMFAWMFAmF4BAJkRwkAawMFAmViBQJkRgUBYwQCZFUJAPwHBAUCYXMCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUCYUQGY2FsbGVyCQDMCAIFAmRHBQNuaWwFA25pbAMJAAACBQJkVQUCZFUEAmVkBQZoZWlnaHQEAmRICQEBbgEJAPwHBAUCYXMCFWNhbGNHd3hQYXJhbXNSRUFET05MWQkAzAgCBQJkRwkAzAgCBQJlZAkAzAgCBQJlYwUDbmlsBQNuaWwEAmJRCQEBcQEJAJEDAgUCZEgAAAQCYlIJAQFxAQkAkQMCBQJkSAABBAJiaQkApAMBCQEBcQEJAJEDAgUCZEgAAgQCY1MJAQFrAgUCYnkJAQJhZQAEAmNUCQEBawIFAmJ5CQECYWcABAJjVQkBAWsCBQJieQkBAmFpAAQCY2sDCQBmAgUGaGVpZ2h0BQJjVQUCY1UFBmhlaWdodAQCY1YJAJYDAQkAzAgCCQBlAgUCY2sFAmNUCQDMCAIAAAUDbmlsBAJjWAkBAmJvAQUCY0oEAmNZCQEBaAIFBHRoaXMFAmNYBAJjWgkAaQIJAGgCCQBoAgUCY1MFAmNWAAIAAwQCZGEJAGUCBQJjWgUCY1kDCQBmAgAABQJkYQkAAgECEndyb25nIGNhbGN1bGF0aW9ucwQCZGYJAQJicgEFAmNKBAJkZwkBAmJzAAQCZGgJAQFoAgUEdGhpcwUCZGYEAmRpCQEBaAIFBHRoaXMFAmRnBAJlZQkBAmNDAQUCY0YEAmVmCQBlAgUCZEcFAmVlAwkAZgIAAAUCZWYJAAIBCQCsAgICGGd3eERpZmYgaXMgbGVzcyB0aGVuIDA6IAkApAMBBQJlZgQCYkoJAQJiQgEHBAJkagkBAmJCAQYEAmRsCQECYnQBBQJjSgQCZG0JAQFoAgUEdGhpcwUCZGwEAmR0CQBrAwUCZGEFAmVlBQJkagQCZWcJAGkCCQBoAgUCZEcFAmVjAAIEAmVoCQBpAgkAaAIFAmVlBQJlYQACBAJlaQkAZQIFAmVnBQJlaAkAzggCCQDNCAIJAM4IAgkBAmNtCAUCY0YFAmNKBQJlYgUCZWQFAmVjBQJiUQUCYlIFAmJpCQECYlUEBQJkQwUCZFcAAAAACQECYk0IAgRsb2NrBQJjRgUCZEMFAmJQBQJlYwUCYlEFAmJSBQJhRAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmJ2AAkAZAIFAmJKBQJlZgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFEAQxjbGFpbVd4Qm9vc3QCAmNFAmNGAwkBAiE9AgUCYnoIBQJhRAZjYWxsZXIJAAIBAhJwZXJtaXNzaW9ucyBkZW5pZWQEAmVqCQECY0QDBQJjRQUCY0YHBAJkdwgFAmVqAl8xBAJkeAgFAmVqAl8yBAJkeQgFAmVqAl8zCQCUCgIFAmR4CQDMCAIFAmR3BQNuaWwCYUQBFGNsYWltV3hCb29zdFJFQURPTkxZAgJjRQJjRgQCZWsJAQJjRAMFAmNFBQJjRgYEAmR3CAUCZWsCXzEEAmR4CAUCZWsCXzIEAmR5CAUCZWsCXzMJAJQKAgUDbmlsCQDMCAIFAmR3CQDMCAIFAmR5BQNuaWwCYUQBBnVubG9jawECYU4EAmNJCQECYU8BBQJhTgQCY0oJAJEDAgUCY0kFAmFHBAJkWAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmNJBQJhSAQCYlAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjSQUCYUkEAmRZCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY0kFAmFKBAJkWgkAZAIFAmJQBQJkWQQCZEEJAQJhcgAEAmF1CQDZBAEJAJEDAgUCZEEFAmFsAwkAZwIFAmRaBQZoZWlnaHQJAAIBCQCsAgIJAKwCAgIFd2FpdCAJAKQDAQUCZFoCCiB0byB1bmxvY2sDCQBnAgAABQJkWAkAAgECEW5vdGhpbmcgdG8gdW5sb2NrBAJiaQkBC3ZhbHVlT3JFbHNlAgkAmggCBQJhcwkBAmFqAAAACQDNCAIJAM0IAgkAzggCCQECY20IBQJhTgUCY0oAAAUCYlAFAmRZAAAAAAkApAMBBQJiaQkBAmJVBAkBAS0BBQJkWAAAAAAA////////////AQkBAmJNCAIGdW5sb2NrBQJhTgUCZFgFAmJQBQJkWQAAAAAFAmFECQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQJhTgUCZFgFAmF1AmFEARNnd3hVc2VySW5mb1JFQURPTkxZAQJhTgQCYVgJAQJjQwEFAmFOCQCUCgIFA25pbAkAzAgCBQJhWAUDbmlsAmFEARd1c2VyTWF4RHVyYXRpb25SRUFET05MWQECY0YEAmRBCQECYXIABAJheAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRBBQJhbwQCZWwJAJ0IAgUEdGhpcwkBAmFNAQUCY0YDCQAAAgUCZWwFBHVuaXQJAJQKAgUDbmlsCQCUCgICBGxvY2sFAmF4BAJjSQkAtQkCCQEFdmFsdWUBBQJlbAUBYQQCYlAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjSQUCYUkEAmRZCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY0kFAmFKBAJkWgkAZAIFAmJQBQJkWQQCZWEJAJYDAQkAzAgCCQBlAgUCZFoFBmhlaWdodAkAzAgCAAAFA25pbAQCZW0JAGUCBQJheAUCZWEJAJQKAgUDbmlsCQCUCgICDGluY3JlYXNlTG9jawUCZW0CYUQBIGdldFVzZXJHd3hBbW91bnRBdEhlaWdodFJFQURPTkxZAgJhTgJjeQQCYVgJAQJjeAIFAmFOBQJjeQkAlAoCBQNuaWwFAmFYAmFEARlnZXRUb3RhbENhY2hlZEd3eFJFQURPTkxZAAkAlAoCBQNuaWwJAQJiQgEGAmFEAQpzZXRNYW5hZ2VyAQJlbgQCZE4JAQJhQwEFAmFEAwkAAAIFAmROBQJkTgQCZW8JANkEAQUCZW4DCQAAAgUCZW8FAmVvCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhZAAFAmVuBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYUQBDmNvbmZpcm1NYW5hZ2VyAAQCZXAJAQJhQgAEAmVxAwkBCWlzRGVmaW5lZAEFAmVwBgkAAgECEk5vIHBlbmRpbmcgbWFuYWdlcgMJAAACBQJlcQUCZXEEAmVyAwkAAAIIBQJhRA9jYWxsZXJQdWJsaWNLZXkJAQV2YWx1ZQEFAmVwBgkAAgECG1lvdSBhcmUgbm90IHBlbmRpbmcgbWFuYWdlcgMJAAACBQJlcgUCZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFjAAkA2AQBCQEFdmFsdWUBBQJlcAkAzAgCCQELRGVsZXRlRW50cnkBCQECYWQABQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmVzAQJldAAEAmV1BAFvCQECYXoAAwkAAQIFAW8CCkJ5dGVWZWN0b3IEAmFGBQFvBQJhRgMJAAECBQFvAgRVbml0CAUCZXMPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IJAPQDAwgFAmVzCWJvZHlCeXRlcwkAkQMCCAUCZXMGcHJvb2ZzAAAFAmV1oPQWCg==", "chainId": 84, "height": 2398704, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3Dok8wiZB6Hfb7Jq8HaJuJhAxMwFtNkHe1uZesBsPGsr Next: xbyVFyFfRdfKPDcs6kUkaJqE7nvkDzXfv4fWWyMSBFU Diff:
OldNewDifferences
722722
723723
724724 @Callable(i)
725+func userMaxDurationREADONLY (userAddressStr) = {
726+ let cfgArray = readConfigArrayOrFail()
727+ let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
728+ let userRecordOption = getString(this, keyLockParamsRecord(userAddressStr))
729+ if ((userRecordOption == unit))
730+ then $Tuple2(nil, $Tuple2("lock", maxLockDuration))
731+ else {
732+ let userRecordArray = split(value(userRecordOption), SEP)
733+ let lockStart = parseIntValue(userRecordArray[IdxLockStart])
734+ let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
735+ let lockEnd = (lockStart + lockDuration)
736+ let remainingDuration = max([(lockEnd - height), 0])
737+ let maxDeltaDuration = (maxLockDuration - remainingDuration)
738+ $Tuple2(nil, $Tuple2("increaseLock", maxDeltaDuration))
739+ }
740+ }
741+
742+
743+
744+@Callable(i)
725745 func getUserGwxAmountAtHeightREADONLY (userAddress,targetHeight) = {
726746 let gwxAmount = calcUserGwxAmountAtHeight(userAddress, targetHeight)
727747 $Tuple2(nil, gwxAmount)
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
4444
4545 func keyReferralsContractAddress () = makeString(["%s%s", "config", "referralsContractAddress"], SEP)
4646
4747
4848 let referralsContractAddressOrFail = addressFromStringValue(strf(this, keyReferralsContractAddress()))
4949
5050 let keyReferralProgramName = makeString(["%s%s", "referral", "programName"], SEP)
5151
5252 let referralProgramNameDefault = "wxlock"
5353
5454 let referralProgramName = valueOrElse(getString(this, keyReferralProgramName), referralProgramNameDefault)
5555
5656 func keyFactoryAddress () = "%s%s__config__factoryAddress"
5757
5858
5959 let IdxFactoryCfgStakingDapp = 1
6060
6161 let IdxFactoryCfgBoostingDapp = 2
6262
6363 let IdxFactoryCfgIdoDapp = 3
6464
6565 let IdxFactoryCfgTeamDapp = 4
6666
6767 let IdxFactoryCfgEmissionDapp = 5
6868
6969 let IdxFactoryCfgRestDapp = 6
7070
7171 let IdxFactoryCfgSlippageDapp = 7
7272
7373 let IdxFactoryCfgDaoDapp = 8
7474
7575 let IdxFactoryCfgMarketingDapp = 9
7676
7777 let IdxFactoryCfgGwxRewardDapp = 10
7878
7979 let IdxFactoryCfgBirdsDapp = 11
8080
8181 func keyFactoryCfg () = "%s__factoryConfig"
8282
8383
8484 func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
8585
8686
8787 func keyFactoryLpList () = "%s__lpTokensList"
8888
8989
9090 func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
9191
9292
9393 func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
9494
9595
9696 func keyFactoryPoolWeightHistory (poolAddress,num) = ((("%s%s__poolWeight__" + poolAddress) + "__") + toString(num))
9797
9898
9999 func readFactoryAddressOrFail () = addressFromStringValue(strf(this, keyFactoryAddress()))
100100
101101
102102 func readLpList () = split(valueOrElse(getString(readFactoryAddressOrFail(), keyFactoryLpList()), ""), SEP)
103103
104104
105105 func readFactoryCfgOrFail (factory) = split(strf(factory, keyFactoryCfg()), SEP)
106106
107107
108108 func getBoostingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgBoostingDapp])
109109
110110
111111 func getEmissionAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgEmissionDapp])
112112
113113
114114 func getStakingAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgStakingDapp])
115115
116116
117117 func getGwxRewardAddressOrFail (factoryCfg) = addressFromStringValue(factoryCfg[IdxFactoryCfgGwxRewardDapp])
118118
119119
120120 func keyManagerPublicKey () = "%s__managerPublicKey"
121121
122122
123123 func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
124124
125125
126126 func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
127127
128128
129129 func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
130130
131131
132132 func keyEmissionStartBlock () = "%s%s__emission__startBlock"
133133
134134
135135 func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
136136
137137
138138 func keyEmissionEndBlock () = "%s%s__emission__endBlock"
139139
140140
141141 func keyNextPeriod () = "%s__nextPeriod"
142142
143143
144144 func keyGwxRewardEmissionStartHeight () = "%s%s__gwxRewardEmissionPart__startHeight"
145145
146146
147147 let IdxCfgAssetId = 1
148148
149149 let IdxCfgMinLockAmount = 2
150150
151151 let IdxCfgMinLockDuration = 3
152152
153153 let IdxCfgMaxLockDuration = 4
154154
155155 let IdxCfgMathContract = 5
156156
157157 func keyConfig () = "%s__config"
158158
159159
160160 func readConfigArrayOrFail () = split(strf(this, keyConfig()), SEP)
161161
162162
163163 let mathContract = addressFromStringValue(readConfigArrayOrFail()[IdxCfgMathContract])
164164
165165 func formatConfigS (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = makeString(["%s%d%d%d", assetId, minLockAmount, minLockDuration, maxLockDuration, mathContract], SEP)
166166
167167
168168 func formatConfig (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = formatConfigS(assetId, toString(minLockAmount), toString(minLockDuration), toString(maxLockDuration), mathContract)
169169
170170
171171 func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
172172 case s: String =>
173173 fromBase58String(s)
174174 case _: Unit =>
175175 unit
176176 case _ =>
177177 throw("Match error")
178178 }
179179
180180
181181 func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
182182 case s: String =>
183183 fromBase58String(s)
184184 case _: Unit =>
185185 unit
186186 case _ =>
187187 throw("Match error")
188188 }
189189
190190
191191 func mustManager (i) = {
192192 let pd = throw("Permission denied")
193193 match managerPublicKeyOrUnit() {
194194 case pk: ByteVector =>
195195 if ((i.callerPublicKey == pk))
196196 then true
197197 else pd
198198 case _: Unit =>
199199 if ((i.caller == this))
200200 then true
201201 else pd
202202 case _ =>
203203 throw("Match error")
204204 }
205205 }
206206
207207
208208 let IdxLockUserNum = 1
209209
210210 let IdxLockAmount = 2
211211
212212 let IdxLockStart = 3
213213
214214 let IdxLockDuration = 4
215215
216216 let IdxLockParamK = 5
217217
218218 let IdxLockParamB = 6
219219
220220 func keyLockParamsRecord (userAddress) = makeString(["%s%s__lock", userAddress], SEP)
221221
222222
223223 func readLockParamsRecordOrFail (userAddress) = split(strf(this, keyLockParamsRecord(userAddress)), SEP)
224224
225225
226226 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)
227227
228228
229229 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))
230230
231231
232232 func keyNextUserNum () = "%s__nextUserNum"
233233
234234
235235 func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
236236
237237
238238 func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
239239
240240
241241 func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
242242
243243
244244 func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
245245
246246
247247 func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
248248
249249
250250 func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
251251
252252
253253 func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
254254
255255
256256 func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
257257
258258
259259 func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
260260
261261
262262 func keyLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
263263
264264
265265 func keyStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
266266
267267
268268 func keyStatsLocksCount () = "%s%s__stats__locksCount"
269269
270270
271271 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
272272
273273
274274 func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
275275
276276
277277 func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastInt", userNum, lpAssetId], SEP)
278278
279279
280280 func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
281281
282282
283283 func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
284284
285285
286286 func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
287287
288288
289289 func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
290290
291291
292292 func keyTotalCachedGwx () = "%s%s__gwxCached__total"
293293
294294
295295 func keyTotalCachedGwxCorrective () = "%s__gwxCachedTotalCorrective"
296296
297297
298298 let factoryContract = readFactoryAddressOrFail()
299299
300300 let factoryCfg = readFactoryCfgOrFail(factoryContract)
301301
302302 let emissionContract = getEmissionAddressOrFail(factoryCfg)
303303
304304 let stakingContract = getStakingAddressOrFail(factoryCfg)
305305
306306 let gwxRewardContract = getGwxRewardAddressOrFail(factoryCfg)
307307
308308 func getTotalCachedGwx (correct) = {
309309 let keyVotingEmissionContract = makeString(["%s", "votingEmissionContract"], SEP)
310310 let votingEmissionContract = addressFromStringValue(getStringValue(factoryContract, keyVotingEmissionContract))
311311 let keyCurrentEpochUi = makeString(["%s", "currentEpochUi"], SEP)
312312 let currentEpochUi = getIntegerValue(votingEmissionContract, keyCurrentEpochUi)
313313 let keyTargetEpoch = makeString(["%s%s", "totalCachedGwxCorrection__activationEpoch"], SEP)
314314 let targetEpochOption = getInteger(this, keyTargetEpoch)
315315 let totalCachedGwxRaw = valueOrElse(getInteger(this, keyTotalCachedGwx()), 0)
316316 let isCorrectionActivated = if (isDefined(targetEpochOption))
317317 then (currentEpochUi >= value(targetEpochOption))
318318 else false
319319 let corrective = if (if (isCorrectionActivated)
320320 then correct
321321 else false)
322322 then valueOrElse(getInteger(this, keyTotalCachedGwxCorrective()), 0)
323323 else 0
324324 max([0, (totalCachedGwxRaw + corrective)])
325325 }
326326
327327
328328 func HistoryEntry (type,user,amount,lockStart,duration,k,b,i) = {
329329 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
330330 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)
331331 StringEntry(historyKEY, historyDATA)
332332 }
333333
334334
335335 func StatsEntry (totalLockedInc,durationInc,lockCountInc,usersCountInc) = {
336336 let locksDurationSumInBlocksKEY = keyStatsLocksDurationSumInBlocks()
337337 let locksCountKEY = keyStatsLocksCount()
338338 let usersCountKEY = keyStatsUsersCount()
339339 let totalAmountKEY = keyLockParamTotalAmount()
340340 let locksDurationSumInBlocks = ioz(this, locksDurationSumInBlocksKEY)
341341 let locksCount = ioz(this, locksCountKEY)
342342 let usersCount = ioz(this, usersCountKEY)
343343 let totalAmount = ioz(this, totalAmountKEY)
344344 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
345345 }
346346
347347
348348 func calcGwxAmount (kRaw,bRaw,h) = {
349349 let SCALE = 1000
350350 (((kRaw * h) + bRaw) / SCALE)
351351 }
352352
353353
354354 func LockParamsEntry (userAddress,userNum,amount,start,duration,k,b,period) = {
355355 let userAmountKEY = keyLockParamUserAmount(userNum)
356356 let startBlockKEY = keyLockParamStartBlock(userNum)
357357 let durationKEY = keyLockParamDuration(userNum)
358358 let kKEY = keyLockParamK(userNum)
359359 let bKEY = keyLockParamB(userNum)
360360 let kByPeriodKEY = keyLockParamByPeriodK(userNum, period)
361361 let bByPeriodKEY = keyLockParamByPeriodB(userNum, period)
362362 let gwxAmount = calcGwxAmount(k, b, height)
363363 [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))]
364364 }
365365
366366
367367 func extractOptionalPaymentAmountOrFail (i,expectedAssetId) = if ((size(i.payments) > 1))
368368 then throw("only one payment is allowed")
369369 else if ((size(i.payments) == 0))
370370 then 0
371371 else {
372372 let pmt = i.payments[0]
373373 if ((value(pmt.assetId) != expectedAssetId))
374374 then throw("invalid asset id in payment")
375375 else pmt.amount
376376 }
377377
378378
379379 func calcUserGwxAmountAtHeight (userAddress,targetHeight) = {
380380 let EMPTY = "empty"
381381 let user2NumMappingKEY = keyUser2NumMapping(userAddress)
382382 let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
383383 let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
384384 let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
385385 let gwxAmountCalc = calcGwxAmount(k, b, targetHeight)
386386 let gwxAmount = if ((0 > gwxAmountCalc))
387387 then 0
388388 else gwxAmountCalc
389389 gwxAmount
390390 }
391391
392392
393393 func calcCurrentGwxAmount (userAddress) = calcUserGwxAmountAtHeight(userAddress, height)
394394
395395
396396 func internalClaimWxBoost (lpAssetIdStr,userAddressStr,readOnly) = {
397397 let EMPTY = "EMPTY"
398398 let userRecordOrEmpty = valueOrElse(getString(this, keyLockParamsRecord(userAddressStr)), EMPTY)
399399 if ((userRecordOrEmpty == EMPTY))
400400 then $Tuple3(0, nil, "userRecord::is::empty")
401401 else {
402402 let userRecordArray = split(userRecordOrEmpty, SEP)
403403 let userNumStr = userRecordArray[IdxLockUserNum]
404404 let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
405405 let EMPTYSTR = "empty"
406406 let $t01496515533 = if ((lpAssetIdStr != EMPTYSTR))
407407 then {
408408 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
409409 let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
410410 let pw0 = valueOrElse(getInteger(factoryContract, keyFactoryPoolWeightHistory(poolAddressStr, 0)), pw1)
411411 $Tuple2(pw0, pw1)
412412 }
413413 else if (readOnly)
414414 then $Tuple2(0, 0)
415415 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
416416 let poolWeight0 = $t01496515533._1
417417 let poolWeight1 = $t01496515533._2
418418 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
419419 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
420420 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
421421 let h = if ((height > emissionEnd))
422422 then emissionEnd
423423 else height
424424 let dh = max([(h - emissionStart), 0])
425425 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNumStr, lpAssetIdStr)
426426 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
427427 let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), ioz(this, userBoostEmissionLastIntegralKEY))
428428 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
429429 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
430430 let udh = fraction(userBoostEmissionIntegral, 3, (2 * wxEmissionPerBlock))
431431 let uLastH = (h - udh)
432432 let udh0 = max([(gwxRewardEmissionStartHeight - uLastH), 0])
433433 let udh1 = ((h - uLastH) - udh0)
434434 if (if (if ((0 > uLastH))
435435 then true
436436 else (0 > udh1))
437437 then true
438438 else (abs(((udh0 + udh1) - udh)) >= 1))
439439 then throw(((((((("invalid udh calc: udh=" + toString(udh)) + " uLastH=") + toString(uLastH)) + " udh0=") + toString(udh0)) + " udh1=") + toString(udh1)))
440440 else if ((0 > userBoostEmissionIntegral))
441441 then throw("wrong calculations")
442442 else {
443443 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
444444 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
445445 let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
446446 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
447447 let totalCachedGwxCorrected = getTotalCachedGwx(true)
448448 let userCurrGwx = calcCurrentGwxAmount(userAddressStr)
449449 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
450450 let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
451451 let userBoostEmissionIntegral0 = if ((udh == 0))
452452 then 0
453453 else fraction(userBoostEmissionIntegral, udh0, udh)
454454 let userBoostEmissionIntegral1 = if ((udh == 0))
455455 then 0
456456 else fraction(userBoostEmissionIntegral, udh1, udh)
457457 let poolUserBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral0, poolWeight0, POOLWEIGHTMULT)
458458 let poolUserBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral1, poolWeight1, POOLWEIGHTMULT)
459459 let userBoostAvaliableToClaimTotalNew0 = if ((totalCachedGwxCorrected == 0))
460460 then 0
461461 else fraction(poolUserBoostEmissionIntegral0, userCurrGwx, totalCachedGwxCorrected)
462462 let userBoostAvaliableToClaimTotalNew1 = if ((totalCachedGwxCorrected == 0))
463463 then 0
464464 else fraction(poolUserBoostEmissionIntegral1, userCurrGwx, totalCachedGwxCorrected)
465465 let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotalNew0 + userBoostAvaliableToClaimTotalNew1)
466466 let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
467467 let userBoostClaimed = ioz(this, userBoostClaimedKEY)
468468 let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
469469 let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
470470 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(totalCachedGwxCorrected)], ":")
471471 $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
472472 }
473473 }
474474 }
475475
476476
477477 func lockActions (i,duration) = {
478478 let cfgArray = readConfigArrayOrFail()
479479 let assetIdStr = cfgArray[IdxCfgAssetId]
480480 let assetId = fromBase58String(assetIdStr)
481481 let minLockAmount = parseIntValue(cfgArray[IdxCfgMinLockAmount])
482482 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
483483 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
484484 if ((size(i.payments) != 1))
485485 then throw("invalid payment - exact one payment must be attached")
486486 else {
487487 let pmt = i.payments[0]
488488 let pmtAmount = pmt.amount
489489 if ((assetId != value(pmt.assetId)))
490490 then throw((("invalid asset is in payment - " + assetIdStr) + " is expected"))
491491 else {
492492 let nextUserNumKEY = keyNextUserNum()
493493 let userAddressStr = toString(i.caller)
494494 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
495495 let userNumStr = if (userIsExisting)
496496 then value(getString(keyUser2NumMapping(userAddressStr)))
497497 else toString(iof(this, nextUserNumKEY))
498498 let userNum = parseIntValue(userNumStr)
499499 let lockStart = height
500500 let startBlockKEY = keyLockParamStartBlock(userNumStr)
501501 let durationKEY = keyLockParamDuration(userNumStr)
502502 let userAmountKEY = keyLockParamUserAmount(userNumStr)
503503 if ((minLockAmount > pmtAmount))
504504 then throw(("amount is less then minLockAmount=" + toString(minLockAmount)))
505505 else if ((minLockDuration > duration))
506506 then throw(("passed duration is less then minLockDuration=" + toString(minLockDuration)))
507507 else if ((duration > maxLockDuration))
508508 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
509509 else if (if (userIsExisting)
510510 then ((iof(this, startBlockKEY) + iof(this, durationKEY)) >= lockStart)
511511 else false)
512512 then throw("there is an active lock - consider to use increaseLock")
513513 else if ((ioz(this, userAmountKEY) > 0))
514514 then throw(("there are locked WXs - consider to use increaseLock " + userAmountKEY))
515515 else {
516516 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
517517 let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
518518 let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
519519 let k = ai(gWxParamsResultList[0])
520520 let b = ai(gWxParamsResultList[1])
521521 let period = toString(ai(gWxParamsResultList[2]))
522522 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
523523 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
524524 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
525525 let h = if ((height > emissionEnd))
526526 then emissionEnd
527527 else height
528528 let dh = max([(h - emissionStart), 0])
529529 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
530530 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
531531 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
532532 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
533533 let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
534534 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
535535 let totalCachedGwxRaw = getTotalCachedGwx(false)
536536 let arr = if (userIsExisting)
537537 then nil
538538 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
539539 $Tuple2(((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
540540 then 0
541541 else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(keyTotalCachedGwx(), (totalCachedGwxRaw + gWxAmountStart))]), gWxAmountStart)
542542 }
543543 }
544544 }
545545 }
546546
547547
548548 @Callable(i)
549549 func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
550550 let checkCaller = mustManager(i)
551551 if ((checkCaller == checkCaller))
552552 then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
553553 else throw("Strict value is not equal to itself.")
554554 }
555555
556556
557557
558558 @Callable(i)
559559 func lockRef (duration,referrerAddress,signature) = {
560560 let $t02389223957 = lockActions(i, duration)
561561 let lockActionsResult = $t02389223957._1
562562 let gWxAmountStart = $t02389223957._2
563563 let referralAddress = toString(i.caller)
564564 let refInv = if (if ((referrerAddress == ""))
565565 then true
566566 else (signature == base58''))
567567 then unit
568568 else invoke(referralsContractAddressOrFail, "createPair", [referralProgramName, referrerAddress, referralAddress, signature], nil)
569569 if ((refInv == refInv))
570570 then {
571571 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
572572 if ((updateRefActivity == updateRefActivity))
573573 then $Tuple2(lockActionsResult, unit)
574574 else throw("Strict value is not equal to itself.")
575575 }
576576 else throw("Strict value is not equal to itself.")
577577 }
578578
579579
580580
581581 @Callable(i)
582582 func lock (duration) = {
583583 let $t02441524480 = lockActions(i, duration)
584584 let lockActionsResult = $t02441524480._1
585585 let gWxAmountStart = $t02441524480._2
586586 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
587587 if ((updateRefActivity == updateRefActivity))
588588 then $Tuple2(lockActionsResult, unit)
589589 else throw("Strict value is not equal to itself.")
590590 }
591591
592592
593593
594594 @Callable(i)
595595 func increaseLock (deltaDuration) = {
596596 let cfgArray = readConfigArrayOrFail()
597597 let assetIdStr = cfgArray[IdxCfgAssetId]
598598 let assetId = fromBase58String(assetIdStr)
599599 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
600600 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
601601 let pmtAmount = extractOptionalPaymentAmountOrFail(i, assetId)
602602 let userAddressStr = toString(i.caller)
603603 let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
604604 let userNumStr = userRecordArray[IdxLockUserNum]
605605 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
606606 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
607607 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
608608 let lockEnd = (lockStart + lockDuration)
609609 let remainingDuration = max([(lockEnd - height), 0])
610610 let userAmountNew = (userAmount + pmtAmount)
611611 let lockDurationNew = (remainingDuration + deltaDuration)
612612 if ((0 > deltaDuration))
613613 then throw("duration is less then zero")
614614 else if ((minLockDuration > lockDurationNew))
615615 then throw(("lockDurationNew is less then minLockDuration=" + toString(minLockDuration)))
616616 else if ((lockDurationNew > maxLockDuration))
617617 then throw(("deltaDuration + existedLockDuration is greater then maxLockDuration=" + toString(maxLockDuration)))
618618 else {
619619 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
620620 let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
621621 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
622622 if ((updateRefActivity == updateRefActivity))
623623 then {
624624 let lockStartNew = height
625625 let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
626626 let k = ai(gWxParamsResultList[0])
627627 let b = ai(gWxParamsResultList[1])
628628 let period = toString(ai(gWxParamsResultList[2]))
629629 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
630630 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
631631 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
632632 let h = if ((height > emissionEnd))
633633 then emissionEnd
634634 else height
635635 let dh = max([(h - emissionStart), 0])
636636 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
637637 let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
638638 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
639639 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
640640 if ((0 > userBoostEmissionIntegral))
641641 then throw("wrong calculations")
642642 else {
643643 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
644644 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
645645 let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
646646 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
647647 let currUserGwx = calcCurrentGwxAmount(userAddressStr)
648648 let gwxDiff = (gWxAmountStart - currUserGwx)
649649 if ((0 > gwxDiff))
650650 then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
651651 else {
652652 let totalCachedGwxRaw = getTotalCachedGwx(false)
653653 let totalCachedGwxCorrected = getTotalCachedGwx(true)
654654 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
655655 let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
656656 let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwxCorrected)
657657 let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
658658 let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
659659 let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
660660 (((LockParamsEntry(userAddressStr, userNumStr, userAmountNew, lockStartNew, lockDurationNew, k, b, period) ++ StatsEntry(pmtAmount, deltaDuration, 0, 0)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, lockDurationNew, k, b, i)) ++ [IntegerEntry(keyTotalCachedGwx(), (totalCachedGwxRaw + gwxDiff))])
661661 }
662662 }
663663 }
664664 else throw("Strict value is not equal to itself.")
665665 }
666666 }
667667
668668
669669
670670 @Callable(i)
671671 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
672672 then throw("permissions denied")
673673 else {
674674 let $t02946129563 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
675675 let userBoostAvailable = $t02946129563._1
676676 let dataState = $t02946129563._2
677677 let debug = $t02946129563._3
678678 $Tuple2(dataState, [userBoostAvailable])
679679 }
680680
681681
682682
683683 @Callable(i)
684684 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
685685 let $t02969529796 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
686686 let userBoostAvailable = $t02969529796._1
687687 let dataState = $t02969529796._2
688688 let debug = $t02969529796._3
689689 $Tuple2(nil, [userBoostAvailable, debug])
690690 }
691691
692692
693693
694694 @Callable(i)
695695 func unlock (userAddress) = {
696696 let userRecordArray = readLockParamsRecordOrFail(userAddress)
697697 let userNumStr = userRecordArray[IdxLockUserNum]
698698 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
699699 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
700700 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
701701 let lockEnd = (lockStart + lockDuration)
702702 let cfgArray = readConfigArrayOrFail()
703703 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
704704 if ((lockEnd >= height))
705705 then throw((("wait " + toString(lockEnd)) + " to unlock"))
706706 else if ((0 >= userAmount))
707707 then throw("nothing to unlock")
708708 else {
709709 let period = valueOrElse(getInteger(mathContract, keyNextPeriod()), 0)
710710 (((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))
711711 }
712712 }
713713
714714
715715
716716 @Callable(i)
717717 func gwxUserInfoREADONLY (userAddress) = {
718718 let gwxAmount = calcCurrentGwxAmount(userAddress)
719719 $Tuple2(nil, [gwxAmount])
720720 }
721721
722722
723723
724724 @Callable(i)
725+func userMaxDurationREADONLY (userAddressStr) = {
726+ let cfgArray = readConfigArrayOrFail()
727+ let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
728+ let userRecordOption = getString(this, keyLockParamsRecord(userAddressStr))
729+ if ((userRecordOption == unit))
730+ then $Tuple2(nil, $Tuple2("lock", maxLockDuration))
731+ else {
732+ let userRecordArray = split(value(userRecordOption), SEP)
733+ let lockStart = parseIntValue(userRecordArray[IdxLockStart])
734+ let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
735+ let lockEnd = (lockStart + lockDuration)
736+ let remainingDuration = max([(lockEnd - height), 0])
737+ let maxDeltaDuration = (maxLockDuration - remainingDuration)
738+ $Tuple2(nil, $Tuple2("increaseLock", maxDeltaDuration))
739+ }
740+ }
741+
742+
743+
744+@Callable(i)
725745 func getUserGwxAmountAtHeightREADONLY (userAddress,targetHeight) = {
726746 let gwxAmount = calcUserGwxAmountAtHeight(userAddress, targetHeight)
727747 $Tuple2(nil, gwxAmount)
728748 }
729749
730750
731751
732752 @Callable(i)
733753 func getTotalCachedGwxREADONLY () = $Tuple2(nil, getTotalCachedGwx(true))
734754
735755
736756
737757 @Callable(i)
738758 func setManager (pendingManagerPublicKey) = {
739759 let checkCaller = mustManager(i)
740760 if ((checkCaller == checkCaller))
741761 then {
742762 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
743763 if ((checkManagerPublicKey == checkManagerPublicKey))
744764 then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
745765 else throw("Strict value is not equal to itself.")
746766 }
747767 else throw("Strict value is not equal to itself.")
748768 }
749769
750770
751771
752772 @Callable(i)
753773 func confirmManager () = {
754774 let pm = pendingManagerPublicKeyOrUnit()
755775 let hasPM = if (isDefined(pm))
756776 then true
757777 else throw("No pending manager")
758778 if ((hasPM == hasPM))
759779 then {
760780 let checkPM = if ((i.callerPublicKey == value(pm)))
761781 then true
762782 else throw("You are not pending manager")
763783 if ((checkPM == checkPM))
764784 then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
765785 else throw("Strict value is not equal to itself.")
766786 }
767787 else throw("Strict value is not equal to itself.")
768788 }
769789
770790
771791 @Verifier(tx)
772792 func verify () = {
773793 let targetPublicKey = match managerPublicKeyOrUnit() {
774794 case pk: ByteVector =>
775795 pk
776796 case _: Unit =>
777797 tx.senderPublicKey
778798 case _ =>
779799 throw("Match error")
780800 }
781801 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
782802 }
783803

github/deemru/w8io/026f985 
72.43 ms