tx · 2aqxbZWuHHMFndQpkSuvdwNXtU2oUhxgPx9M3XKQYnbL

3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy:  -0.02200000 Waves

2023.02.15 13:40 [2450613] smart account 3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy > SELF 0.00000000 Waves

{ "type": 13, "id": "2aqxbZWuHHMFndQpkSuvdwNXtU2oUhxgPx9M3XKQYnbL", "fee": 2200000, "feeAssetId": null, "timestamp": 1676457648751, "version": 2, "chainId": 84, "sender": "3Myn55vLkduxbX3ZXfiDCZhaQsLxYp1kmCy", "senderPublicKey": "9W33iCCNfmFxUbiC6XZcH5x7f6xfwC7Jb3BoExT5q2PV", "proofs": [ "dFiaLhRNCB6SKejKvPL9nUArU7BYPArCnfRoN7MUUFXkq2NmvMouRZ3s29BqMTL3KowsuLvwsa7TdvmX564mm3v" ], "script": "base64:BgLNJAgCEggKBggIAQEBCBIFCgMBCAISAwoBARIDCgEBEgQKAggIEgQKAggIEgMKAQgSAwoBCBIECgIIARIAEgMKAQgSACIDU0VQIgZTQ0FMRTgiBU1VTFQ4Ig5QT09MV0VJR0hUTVVMVCIEc3RyZiIHYWRkcmVzcyIDa2V5IgNpb3oiA2lvZCIKZGVmYXVsdFZhbCIDaW9mIgNhYnMiA3ZhbCIDYWFsIgckbWF0Y2gwIgp2YWxBbnlMeXN0IgJhaSIGdmFsSW50IhtrZXlSZWZlcnJhbHNDb250cmFjdEFkZHJlc3MiHnJlZmVycmFsc0NvbnRyYWN0QWRkcmVzc09yRmFpbCIWa2V5UmVmZXJyYWxQcm9ncmFtTmFtZSIacmVmZXJyYWxQcm9ncmFtTmFtZURlZmF1bHQiE3JlZmVycmFsUHJvZ3JhbU5hbWUiEWtleUZhY3RvcnlBZGRyZXNzIhhJZHhGYWN0b3J5Q2ZnU3Rha2luZ0RhcHAiGUlkeEZhY3RvcnlDZmdCb29zdGluZ0RhcHAiFElkeEZhY3RvcnlDZmdJZG9EYXBwIhVJZHhGYWN0b3J5Q2ZnVGVhbURhcHAiGUlkeEZhY3RvcnlDZmdFbWlzc2lvbkRhcHAiFUlkeEZhY3RvcnlDZmdSZXN0RGFwcCIZSWR4RmFjdG9yeUNmZ1NsaXBwYWdlRGFwcCIUSWR4RmFjdG9yeUNmZ0Rhb0RhcHAiGklkeEZhY3RvcnlDZmdNYXJrZXRpbmdEYXBwIhpJZHhGYWN0b3J5Q2ZnR3d4UmV3YXJkRGFwcCIWSWR4RmFjdG9yeUNmZ0JpcmRzRGFwcCINa2V5RmFjdG9yeUNmZyIaa2V5RmFjdG9yeUxwMkFzc2V0c01hcHBpbmciCmxwQXNzZXRTdHIiEGtleUZhY3RvcnlMcExpc3QiJmtleUZhY3RvcnlMcEFzc2V0VG9Qb29sQ29udHJhY3RBZGRyZXNzIhRrZXlGYWN0b3J5UG9vbFdlaWdodCIPY29udHJhY3RBZGRyZXNzIhtrZXlGYWN0b3J5UG9vbFdlaWdodEhpc3RvcnkiC3Bvb2xBZGRyZXNzIgNudW0iGHJlYWRGYWN0b3J5QWRkcmVzc09yRmFpbCIKcmVhZExwTGlzdCIUcmVhZEZhY3RvcnlDZmdPckZhaWwiB2ZhY3RvcnkiGGdldEJvb3N0aW5nQWRkcmVzc09yRmFpbCIKZmFjdG9yeUNmZyIYZ2V0RW1pc3Npb25BZGRyZXNzT3JGYWlsIhdnZXRTdGFraW5nQWRkcmVzc09yRmFpbCIZZ2V0R3d4UmV3YXJkQWRkcmVzc09yRmFpbCITa2V5TWFuYWdlclB1YmxpY0tleSIaa2V5UGVuZGluZ01hbmFnZXJQdWJsaWNLZXkiHmtleUVtaXNzaW9uUmF0ZVBlckJsb2NrQ3VycmVudCIha2V5RW1pc3Npb25SYXRlUGVyQmxvY2tNYXhDdXJyZW50IhVrZXlFbWlzc2lvblN0YXJ0QmxvY2siGGtleUJvb3N0aW5nVjJTdGFydEhlaWdodCIba2V5RW1pc3Npb25EdXJhdGlvbkluQmxvY2tzIhNrZXlFbWlzc2lvbkVuZEJsb2NrIg1rZXlOZXh0UGVyaW9kIh9rZXlHd3hSZXdhcmRFbWlzc2lvblN0YXJ0SGVpZ2h0Ig1JZHhDZmdBc3NldElkIhNJZHhDZmdNaW5Mb2NrQW1vdW50IhVJZHhDZmdNaW5Mb2NrRHVyYXRpb24iFUlkeENmZ01heExvY2tEdXJhdGlvbiISSWR4Q2ZnTWF0aENvbnRyYWN0IglrZXlDb25maWciFXJlYWRDb25maWdBcnJheU9yRmFpbCIMbWF0aENvbnRyYWN0Ig1mb3JtYXRDb25maWdTIgdhc3NldElkIg1taW5Mb2NrQW1vdW50Ig9taW5Mb2NrRHVyYXRpb24iD21heExvY2tEdXJhdGlvbiIMZm9ybWF0Q29uZmlnIhZtYW5hZ2VyUHVibGljS2V5T3JVbml0IgFzIh1wZW5kaW5nTWFuYWdlclB1YmxpY0tleU9yVW5pdCILbXVzdE1hbmFnZXIiAWkiAnBkIgJwayIOSWR4TG9ja1VzZXJOdW0iDUlkeExvY2tBbW91bnQiDElkeExvY2tTdGFydCIPSWR4TG9ja0R1cmF0aW9uIg1JZHhMb2NrUGFyYW1LIg1JZHhMb2NrUGFyYW1CIhNrZXlMb2NrUGFyYW1zUmVjb3JkIgt1c2VyQWRkcmVzcyIacmVhZExvY2tQYXJhbXNSZWNvcmRPckZhaWwiF2Zvcm1hdExvY2tQYXJhbXNSZWNvcmRTIgd1c2VyTnVtIgZhbW91bnQiBXN0YXJ0IghkdXJhdGlvbiIGcGFyYW1LIgZwYXJhbUIiEGxhc3RVcGRUaW1lc3RhbXAiCWd3eEFtb3VudCIWZm9ybWF0TG9ja1BhcmFtc1JlY29yZCIOa2V5TmV4dFVzZXJOdW0iEmtleVVzZXIyTnVtTWFwcGluZyISa2V5TnVtMlVzZXJNYXBwaW5nIhZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50IhZrZXlMb2NrUGFyYW1TdGFydEJsb2NrIhRrZXlMb2NrUGFyYW1EdXJhdGlvbiINa2V5TG9ja1BhcmFtSyINa2V5TG9ja1BhcmFtQiIVa2V5TG9ja1BhcmFtQnlQZXJpb2RLIgZwZXJpb2QiFWtleUxvY2tQYXJhbUJ5UGVyaW9kQiIXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQiIGtleVN0YXRzTG9ja3NEdXJhdGlvblN1bUluQmxvY2tzIhJrZXlTdGF0c0xvY2tzQ291bnQiEmtleVN0YXRzVXNlcnNDb3VudCIga2V5VXNlckJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwiImtleVVzZXJMcEJvb3N0RW1pc3Npb25MYXN0SU5URUdSQUwiCWxwQXNzZXRJZCIXa2V5VXNlck1heEJvb3N0SU5URUdSQUwiGGtleVRvdGFsTWF4Qm9vc3RJTlRFR1JBTCIha2V5VXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsIhNrZXlVc2VyQm9vc3RDbGFpbWVkIhFrZXlUb3RhbENhY2hlZEd3eCIba2V5VG90YWxDYWNoZWRHd3hDb3JyZWN0aXZlIg9mYWN0b3J5Q29udHJhY3QiEGVtaXNzaW9uQ29udHJhY3QiD3N0YWtpbmdDb250cmFjdCIRZ3d4UmV3YXJkQ29udHJhY3QiGWtleVZvdGluZ0VtaXNzaW9uQ29udHJhY3QiFnZvdGluZ0VtaXNzaW9uQ29udHJhY3QiCmJvb3N0Q29lZmYiAUAiEWdldFRvdGFsQ2FjaGVkR3d4Igdjb3JyZWN0IhFrZXlDdXJyZW50RXBvY2hVaSIOY3VycmVudEVwb2NoVWkiDmtleVRhcmdldEVwb2NoIhF0YXJnZXRFcG9jaE9wdGlvbiIRdG90YWxDYWNoZWRHd3hSYXciFWlzQ29ycmVjdGlvbkFjdGl2YXRlZCIKY29ycmVjdGl2ZSIMSGlzdG9yeUVudHJ5IgR0eXBlIgR1c2VyIglsb2NrU3RhcnQiAWsiAWIiCmhpc3RvcnlLRVkiC2hpc3RvcnlEQVRBIgpTdGF0c0VudHJ5Ig50b3RhbExvY2tlZEluYyILZHVyYXRpb25JbmMiDGxvY2tDb3VudEluYyINdXNlcnNDb3VudEluYyIbbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzS0VZIg1sb2Nrc0NvdW50S0VZIg11c2Vyc0NvdW50S0VZIg50b3RhbEFtb3VudEtFWSIYbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzIgpsb2Nrc0NvdW50Igp1c2Vyc0NvdW50Igt0b3RhbEFtb3VudCINY2FsY0d3eEFtb3VudCIEa1JhdyIEYlJhdyIBaCIFU0NBTEUiD0xvY2tQYXJhbXNFbnRyeSINdXNlckFtb3VudEtFWSINc3RhcnRCbG9ja0tFWSILZHVyYXRpb25LRVkiBGtLRVkiBGJLRVkiDGtCeVBlcmlvZEtFWSIMYkJ5UGVyaW9kS0VZIiJleHRyYWN0T3B0aW9uYWxQYXltZW50QW1vdW50T3JGYWlsIg9leHBlY3RlZEFzc2V0SWQiA3BtdCIZY2FsY1VzZXJHd3hBbW91bnRBdEhlaWdodCIMdGFyZ2V0SGVpZ2h0IgVFTVBUWSISdXNlcjJOdW1NYXBwaW5nS0VZIg1nd3hBbW91bnRDYWxjIhRjYWxjQ3VycmVudEd3eEFtb3VudCIUaW50ZXJuYWxDbGFpbVd4Qm9vc3QiDGxwQXNzZXRJZFN0ciIOdXNlckFkZHJlc3NTdHIiCHJlYWRPbmx5IhF1c2VyUmVjb3JkT3JFbXB0eSIPdXNlclJlY29yZEFycmF5Igp1c2VyTnVtU3RyIghFTVBUWVNUUiIKcG9vbFdlaWdodCIOcG9vbEFkZHJlc3NTdHIiEnd4RW1pc3Npb25QZXJCbG9jayIVYm9vc3RpbmdWMlN0YXJ0SGVpZ2h0IgtlbWlzc2lvbkVuZCICZGgiInVzZXJMcEJvb3N0RW1pc3Npb25MYXN0SW50ZWdyYWxLRVkiIHVzZXJCb29zdEVtaXNzaW9uTGFzdEludGVncmFsS0VZIh11c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRlZ3JhbCIVYm9vc3RFbWlzc2lvbkludGVncmFsIhl1c2VyQm9vc3RFbWlzc2lvbkludGVncmFsIgN1ZGgiBnVMYXN0SCIXdXNlck1heEJvb3N0SW50ZWdyYWxLRVkiGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWSIPdXNlck1heEJvb3N0SW50IhB0b3RhbE1heEJvb3N0SW50Ig0kdDAxNjc1MzE2ODkwIgh1c2VyVm90ZSIKdG90YWxWb3RlcyIhdXNlckJvb3N0QXZhbGFpYmxlVG9DbGFpbVRvdGFsS0VZIh51c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWwiHXBvb2xVc2VyQm9vc3RFbWlzc2lvbkludGVncmFsIiF1c2VyQm9vc3RBdmFsaWFibGVUb0NsYWltVG90YWxOZXciE3VzZXJCb29zdENsYWltZWRLRVkiEHVzZXJCb29zdENsYWltZWQiEnVzZXJCb29zdEF2YWlsYWJsZSIJZGF0YVN0YXRlIgVkZWJ1ZyILbG9ja0FjdGlvbnMiCGNmZ0FycmF5Igphc3NldElkU3RyIglwbXRBbW91bnQiDm5leHRVc2VyTnVtS0VZIg51c2VySXNFeGlzdGluZyIHY29lZmZYOCIOZ1d4QW1vdW50U3RhcnQiE2dXeFBhcmFtc1Jlc3VsdExpc3QiDWVtaXNzaW9uU3RhcnQiA2FyciIRZmFjdG9yeUFkZHJlc3NTdHIiDmxvY2tBc3NldElkU3RyIgttaW5EdXJhdGlvbiILbWF4RHVyYXRpb24iC2NoZWNrQ2FsbGVyIg9yZWZlcnJlckFkZHJlc3MiCXNpZ25hdHVyZSINJHQwMjI4NDIyMjkwNyIRbG9ja0FjdGlvbnNSZXN1bHQiD3JlZmVycmFsQWRkcmVzcyIGcmVmSW52IhF1cGRhdGVSZWZBY3Rpdml0eSINJHQwMjMzNjUyMzQzMCINZGVsdGFEdXJhdGlvbiIKdXNlckFtb3VudCIMbG9ja0R1cmF0aW9uIgdsb2NrRW5kIhFyZW1haW5pbmdEdXJhdGlvbiINdXNlckFtb3VudE5ldyIPbG9ja0R1cmF0aW9uTmV3Igxsb2NrU3RhcnROZXciC2N1cnJVc2VyR3d4Igdnd3hEaWZmIhd0b3RhbENhY2hlZEd3eENvcnJlY3RlZCISdXNlck1heEJvb3N0SW50TmV3IhhyZW1haW5pbmdVc2VyTWF4Qm9vc3RJbnQiE3VzZXJNYXhCb29zdEludERpZmYiDSR0MDI4NDExMjg1MTMiDSR0MDI4NjQ1Mjg3NDYiF3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5IhVjaGVja01hbmFnZXJQdWJsaWNLZXkiAnBtIgVoYXNQTSIHY2hlY2tQTSICdHgiBnZlcmlmeSIPdGFyZ2V0UHVibGljS2V5cgABYQICX18AAWIACAABYwCAwtcvAAFkBQFjAQFlAgFmAWcJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQFmBQFnCQCsAgIJAKwCAgIPbWFuZGF0b3J5IHRoaXMuBQFnAg8gaXMgbm90IGRlZmluZWQBAWgCAWYBZwkBC3ZhbHVlT3JFbHNlAgkAmggCBQFmBQFnAAABAWkDAWYBZwFqCQELdmFsdWVPckVsc2UCCQCaCAIFAWYFAWcFAWoBAWsCAWYBZwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFAWYFAWcJAKwCAgkArAICAg9tYW5kYXRvcnkgdGhpcy4FAWcCDyBpcyBub3QgZGVmaW5lZAEBbAEBbQMJAGYCAAAFAW0JAQEtAQUBbQUBbQEBbgEBbQQBbwUBbQMJAAECBQFvAglMaXN0W0FueV0EAXAFAW8FAXAJAAIBAhtmYWlsIHRvIGNhc3QgaW50byBMaXN0W0FueV0BAXEBAW0EAW8FAW0DCQABAgUBbwIDSW50BAFyBQFvBQFyCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQFzAAkAuQkCCQDMCAICBCVzJXMJAMwIAgIGY29uZmlnCQDMCAICGHJlZmVycmFsc0NvbnRyYWN0QWRkcmVzcwUDbmlsBQFhAAF0CQERQGV4dHJOYXRpdmUoMTA2MikBCQEBZQIFBHRoaXMJAQFzAAABdQkAuQkCCQDMCAICBCVzJXMJAMwIAgIIcmVmZXJyYWwJAMwIAgILcHJvZ3JhbU5hbWUFA25pbAUBYQABdgIGd3hsb2NrAAF3CQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFAXUFAXYBAXgAAhwlcyVzX19jb25maWdfX2ZhY3RvcnlBZGRyZXNzAAF5AAEAAXoAAgABQQADAAFCAAQAAUMABQABRAAGAAFFAAcAAUYACAABRwAJAAFIAAoAAUkACwEBSgACESVzX19mYWN0b3J5Q29uZmlnAQFLAQFMCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAIFAUwJAMwIAgIebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQNuaWwFAWEBAU0AAhAlc19fbHBUb2tlbnNMaXN0AQFOAQFMCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAIFAUwJAMwIAgIebWFwcGluZ3NfX2xwQXNzZXQyUG9vbENvbnRyYWN0BQNuaWwFAWEBAU8BAVAJALkJAgkAzAgCAgQlcyVzCQDMCAICCnBvb2xXZWlnaHQJAMwIAgUBUAUDbmlsBQFhAQFRAgFSAVMJAKwCAgkArAICCQCsAgICEiVzJXNfX3Bvb2xXZWlnaHRfXwUBUgICX18JAKQDAQUBUwEBVAAJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQFlAgUEdGhpcwkBAXgAAQFVAAkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIJAQFUAAkBAU0AAgAFAWEBAVYBAVcJALUJAgkBAWUCBQFXCQEBSgAFAWEBAVgBAVkJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUBWQUBegEBWgEBWQkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQFZBQFDAQJhYQEBWQkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQFZBQF5AQJhYgEBWQkBEUBleHRyTmF0aXZlKDEwNjIpAQkAkQMCBQFZBQFIAQJhYwACFCVzX19tYW5hZ2VyUHVibGljS2V5AQJhZAACGyVzX19wZW5kaW5nTWFuYWdlclB1YmxpY0tleQECYWUAAhslcyVzX19yYXRlUGVyQmxvY2tfX2N1cnJlbnQBAmFmAAIeJXMlc19fcmF0ZVBlckJsb2NrTWF4X19jdXJyZW50AQJhZwACGiVzJXNfX2VtaXNzaW9uX19zdGFydEJsb2NrAQJhaAACHCVzJXNfX2Jvb3N0aW5nVjJfX3N0YXJ0QmxvY2sBAmFpAAIYJXMlc19fZW1pc3Npb25fX2R1cmF0aW9uAQJhagACGCVzJXNfX2VtaXNzaW9uX19lbmRCbG9jawECYWsAAg4lc19fbmV4dFBlcmlvZAECYWwAAiglcyVzX19nd3hSZXdhcmRFbWlzc2lvblBhcnRfX3N0YXJ0SGVpZ2h0AAJhbQABAAJhbgACAAJhbwADAAJhcAAEAAJhcQAFAQJhcgACCiVzX19jb25maWcBAmFzAAkAtQkCCQEBZQIFBHRoaXMJAQJhcgAFAWEAAmF0CQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIJAQJhcwAFAmFxAQJhdQUCYXYCYXcCYXgCYXkCYXQJALkJAgkAzAgCAgglcyVkJWQlZAkAzAgCBQJhdgkAzAgCBQJhdwkAzAgCBQJheAkAzAgCBQJheQkAzAgCBQJhdAUDbmlsBQFhAQJhegUCYXYCYXcCYXgCYXkCYXQJAQJhdQUFAmF2CQCkAwEFAmF3CQCkAwEFAmF4CQCkAwEFAmF5BQJhdAECYUEABAFvCQCiCAEJAQJhYwADCQABAgUBbwIGU3RyaW5nBAJhQgUBbwkA2QQBBQJhQgMJAAECBQFvAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IBAmFDAAQBbwkAoggBCQECYWQAAwkAAQIFAW8CBlN0cmluZwQCYUIFAW8JANkEAQUCYUIDCQABAgUBbwIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJhRAECYUUEAmFGCQACAQIRUGVybWlzc2lvbiBkZW5pZWQEAW8JAQJhQQADCQABAgUBbwIKQnl0ZVZlY3RvcgQCYUcFAW8DCQAAAggFAmFFD2NhbGxlclB1YmxpY0tleQUCYUcGBQJhRgMJAAECBQFvAgRVbml0AwkAAAIIBQJhRQZjYWxsZXIFBHRoaXMGBQJhRgkAAgECC01hdGNoIGVycm9yAAJhSAABAAJhSQACAAJhSgADAAJhSwAEAAJhTAAFAAJhTQAGAQJhTgECYU8JALkJAgkAzAgCAgolcyVzX19sb2NrCQDMCAIFAmFPBQNuaWwFAWEBAmFQAQJhTwkAtQkCCQEBZQIFBHRoaXMJAQJhTgEFAmFPBQFhAQJhUQgCYVICYVMCYVQCYVUCYVYCYVcCYVgCYVkJALkJAgkAzAgCAhAlZCVkJWQlZCVkJWQlZCVkCQDMCAIFAmFSCQDMCAIFAmFTCQDMCAIFAmFUCQDMCAIFAmFVCQDMCAIFAmFWCQDMCAIFAmFXCQDMCAIFAmFYCQDMCAIFAmFZBQNuaWwFAWEBAmFaBwJhUgJhUwJhVAJhVQJhVgJhVwJhWQkBAmFRCAUCYVIJAKQDAQUCYVMJAKQDAQUCYVQJAKQDAQUCYVUJAKQDAQUCYVYJAKQDAQUCYVcJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAKQDAQUCYVkBAmJhAAIPJXNfX25leHRVc2VyTnVtAQJiYgECYU8JALkJAgkAzAgCAhklcyVzJXNfX21hcHBpbmdfX3VzZXIybnVtCQDMCAIFAmFPBQNuaWwFAWEBAmJjAQFTCQC5CQIJAMwIAgIZJXMlcyVzX19tYXBwaW5nX19udW0ydXNlcgkAzAgCBQFTBQNuaWwFAWEBAmJkAQJhUgkAuQkCCQDMCAICFiVzJWQlc19fcGFyYW1CeVVzZXJOdW0JAMwIAgUCYVIJAMwIAgIGYW1vdW50BQNuaWwFAWEBAmJlAQJhUgkAuQkCCQDMCAICFiVzJWQlc19fcGFyYW1CeVVzZXJOdW0JAMwIAgUCYVIJAMwIAgIFc3RhcnQFA25pbAUBYQECYmYBAmFSCQC5CQIJAMwIAgIWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkAzAgCBQJhUgkAzAgCAghkdXJhdGlvbgUDbmlsBQFhAQJiZwECYVIJALkJAgkAzAgCAhYlcyVkJXNfX3BhcmFtQnlVc2VyTnVtCQDMCAIFAmFSCQDMCAICAWsFA25pbAUBYQECYmgBAmFSCQC5CQIJAMwIAgIWJXMlZCVzX19wYXJhbUJ5VXNlck51bQkAzAgCBQJhUgkAzAgCAgFiBQNuaWwFAWEBAmJpAgJhUgJiagkAuQkCCQDMCAICFyVzJWQlcyVkX19wYXJhbUJ5UGVyaW9kCQDMCAIFAmFSCQDMCAICAWsJAMwIAgUCYmoFA25pbAUBYQECYmsCAmFSAmJqCQC5CQIJAMwIAgIXJXMlZCVzJWRfX3BhcmFtQnlQZXJpb2QJAMwIAgUCYVIJAMwIAgIBYgkAzAgCBQJiagUDbmlsBQFhAQJibAACHiVzJXNfX3N0YXRzX19hY3RpdmVUb3RhbExvY2tlZAECYm0AAiUlcyVzX19zdGF0c19fbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzAQJibgACFyVzJXNfX3N0YXRzX19sb2Nrc0NvdW50AQJibwACHSVzJXNfX3N0YXRzX19hY3RpdmVVc2Vyc0NvdW50AQJicAECYVIJALkJAgkAzAgCAiAlcyVkX191c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRWMgkAzAgCBQJhUgUDbmlsBQFhAQJicQICYVICYnIJALkJAgkAzAgCAiAlcyVkX191c2VyQm9vc3RFbWlzc2lvbkxhc3RJbnRWMgkAzAgCBQJhUgkAzAgCBQJicgUDbmlsBQFhAQJicwECYVIJALkJAgkAzAgCAhElcyVkX19tYXhCb29zdEludAkAzAgCBQJhUgUDbmlsBQFhAQJidAACGCVzJXNfX21heEJvb3N0SW50X190b3RhbAECYnUBAmFSCQC5CQIJAMwIAgIkJXMlZF9fdXNlckJvb3N0QXZhbGlhYmxlVG9DbGFpbVRvdGFsCQDMCAIFAmFSBQNuaWwFAWEBAmJ2AQJhUgkAuQkCCQDMCAICFiVzJWRfX3VzZXJCb29zdENsYWltZWQJAMwIAgUCYVIFA25pbAUBYQECYncAAhYlcyVzX19nd3hDYWNoZWRfX3RvdGFsAQJieAACHCVzX19nd3hDYWNoZWRUb3RhbENvcnJlY3RpdmUAAmJ5CQEBVAAAAVkJAQFWAQUCYnkAAmJ6CQEBWgEFAVkAAmJBCQECYWEBBQFZAAJiQgkBAmFiAQUBWQACYkMJALkJAgkAzAgCAgIlcwkAzAgCAhZ2b3RpbmdFbWlzc2lvbkNvbnRyYWN0BQNuaWwFAWEAAmJECQERQGV4dHJOYXRpdmUoMTA2MikBCQERQGV4dHJOYXRpdmUoMTA1MykCBQJieQUCYkMAAmJFCgACYkYJAPwHBAUCYnoCFWdldEJvb3N0Q29lZmZSRUFET05MWQUDbmlsBQNuaWwDCQABAgUCYkYCA0ludAUCYkYJAAIBCQCsAgIJAAMBBQJiRgIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50AQJiRwECYkgEAmJJCQC5CQIJAMwIAgICJXMJAMwIAgIOY3VycmVudEVwb2NoVWkFA25pbAUBYQQCYkoJARFAZXh0ck5hdGl2ZSgxMDUwKQIFAmJEBQJiSQQCYksJALkJAgkAzAgCAgQlcyVzCQDMCAICKXRvdGFsQ2FjaGVkR3d4Q29ycmVjdGlvbl9fYWN0aXZhdGlvbkVwb2NoBQNuaWwFAWEEAmJMCQCaCAIFBHRoaXMFAmJLBAJiTQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQECYncAAAAEAmJOAwkBCWlzRGVmaW5lZAEFAmJMCQBnAgUCYkoJAQV2YWx1ZQEFAmJMBwQCYk8DAwUCYk4FAmJIBwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQECYngAAAAAAAkAlgMBCQDMCAIAAAkAzAgCCQBkAgUCYk0FAmJPBQNuaWwBAmJQCAJiUQJiUgJhUwJiUwJhVQJiVAJiVQJhRQQCYlYJALkJAgkAzAgCAhElcyVzJXMlc19faGlzdG9yeQkAzAgCBQJiUQkAzAgCBQJiUgkAzAgCCQDYBAEIBQJhRQ10cmFuc2FjdGlvbklkBQNuaWwFAWEEAmJXCQC5CQIJAMwIAgIOJWQlZCVkJWQlZCVkJWQJAMwIAgkApAMBCAUJbGFzdEJsb2NrBmhlaWdodAkAzAgCCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAKQDAQUCYVMJAMwIAgkApAMBBQJiUwkAzAgCCQCkAwEFAmFVCQDMCAIJAKQDAQUCYlQJAMwIAgkApAMBBQJiVQUDbmlsBQFhCQELU3RyaW5nRW50cnkCBQJiVgUCYlcBAmJYBAJiWQJiWgJjYQJjYgQCY2MJAQJibQAEAmNkCQECYm4ABAJjZQkBAmJvAAQCY2YJAQJibAAEAmNnCQEBaAIFBHRoaXMFAmNjBAJjaAkBAWgCBQR0aGlzBQJjZAQCY2kJAQFoAgUEdGhpcwUCY2UEAmNqCQEBaAIFBHRoaXMFAmNmCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjYwkAZAIFAmNnBQJiWgkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY2QJAGQCBQJjaAUCY2EJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNlCQBkAgUCY2kFAmNiCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjZgkAZAIFAmNqBQJiWQUDbmlsAQJjawMCY2wCY20CY24EAmNvAOgHCQBpAgkAZAIJAGgCBQJjbAUCY24FAmNtBQJjbwECY3AIAmFPAmFSAmFTAmFUAmFVAmJUAmJVAmJqBAJjcQkBAmJkAQUCYVIEAmNyCQECYmUBBQJhUgQCY3MJAQJiZgEFAmFSBAJjdAkBAmJnAQUCYVIEAmN1CQECYmgBBQJhUgQCY3YJAQJiaQIFAmFSBQJiagQCY3cJAQJiawIFAmFSBQJiagQCYVkJAQJjawMFAmJUBQJiVQUGaGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjcQUCYVMJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNyBQJhVAkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY3MFAmFVCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjdAUCYlQJAMwIAgkBDEludGVnZXJFbnRyeQIFAmN1BQJiVQkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY3YFAmJUCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQJjdwUCYlUJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFOAQUCYU8JAQJhWgcFAmFSBQJhUwUCYVQFAmFVBQJiVAUCYlUFAmFZBQNuaWwBAmN4AgJhRQJjeQMJAGYCCQCQAwEIBQJhRQhwYXltZW50cwABCQACAQIbb25seSBvbmUgcGF5bWVudCBpcyBhbGxvd2VkAwkAAAIJAJADAQgFAmFFCHBheW1lbnRzAAAAAAQCY3oJAJEDAggFAmFFCHBheW1lbnRzAAADCQECIT0CCQEFdmFsdWUBCAUCY3oHYXNzZXRJZAUCY3kJAAIBAhtpbnZhbGlkIGFzc2V0IGlkIGluIHBheW1lbnQIBQJjegZhbW91bnQBAmNBAgJhTwJjQgQCY0MCBWVtcHR5BAJjRAkBAmJiAQUCYU8EAmFSCQELdmFsdWVPckVsc2UCCQCiCAEFAmNEBQJjQwQCYlQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAmJnAQUCYVIAAAQCYlUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAmJoAQUCYVIAAAQCY0UJAQJjawMFAmJUBQJiVQUCY0IEAmFZAwkAZgIAAAUCY0UAAAUCY0UFAmFZAQJjRgECYU8JAQJjQQIFAmFPBQZoZWlnaHQBAmNHAwJjSAJjSQJjSgQCY0MCBUVNUFRZBAJjSwkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQECYU4BBQJjSQUCY0MDCQAAAgUCY0sFAmNDCQCVCgMAAAUDbmlsAhV1c2VyUmVjb3JkOjppczo6ZW1wdHkEAmNMCQC1CQIFAmNLBQFhBAJjTQkAkQMCBQJjTAUCYUgEAmNOAgVlbXB0eQQCY08DCQECIT0CBQJjSAUCY04EAmNQCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUCYnkJAQFLAQUCY0gJAKwCAgIVdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQJjSAkBEUBleHRyTmF0aXZlKDEwNTApAgUCYnkJAQFPAQUCY1ADBQJjSgAACQACAQkArAICAihub3QgcmVhZG9ubHkgbW9kZTogdW5zdXBwb3J0ZWQgbHAgYXNzZXQgBQJjSAQCY1EJAQFrAgUCYnoJAQJhZQAEAmNSCQEBawIFAmJ6CQECYWgABAJjUwkBAWsCBQJiegkBAmFqAAQCY24DCQBmAgUGaGVpZ2h0BQJjUwUCY1MFBmhlaWdodAQCY1QJAJYDAQkAzAgCCQBlAgUCY24FAmNSCQDMCAIAAAUDbmlsBAJjVQkBAmJxAgUCY00FAmNIBAJjVgkBAmJwAQUCY00EAmNXCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAmNVCQEBaAIFBHRoaXMFAmNWBAJjWAkAaQIJAGgCCQBoAgUCY1EFAmNUCQBlAgUCYkUAAQUCYkUEAmNZCQBlAgUCY1gFAmNXBAJjWgkAawMFAmNZBQJiRQkAaAIJAGUCBQJiRQABBQJjUQQCZGEJAGUCBQJjbgUCY1oDCQBmAgAABQJjWQkAAgECEndyb25nIGNhbGN1bGF0aW9ucwQCZGIJAQJicwEFAmNNBAJkYwkBAmJ0AAQCZGQJAQFoAgUEdGhpcwUCZGIEAmRlCQEBaAIFBHRoaXMFAmRjBAJkZgoAAmJGCQD8BwQFAmJEAhNnZXRWb3RlSW5mb1JFQURPTkxZCQDMCAIFAmNICQDMCAIFAmNJBQNuaWwFA25pbAMJAAECBQJiRgIKKEludCwgSW50KQUCYkYJAAIBCQCsAgIJAAMBBQJiRgIfIGNvdWxkbid0IGJlIGNhc3QgdG8gKEludCwgSW50KQQCZGcIBQJkZgJfMQQCZGgIBQJkZgJfMgQCZGkJAQJidQEFAmNNBAJkagkBAWgCBQR0aGlzBQJkaQQCZGsJAGsDBQJjWQUCY08FAWQEAmRsAwkAAAIFAmRoAAAAAAkAawMFAmRrBQJkZwUCZGgEAmRtCQECYnYBBQJjTQQCZG4JAQFoAgUEdGhpcwUCZG0EAmRvCQBlAgUCZGwFAmRuBAJkcAkAzAgCCQEMSW50ZWdlckVudHJ5AgUCY1UFAmNYBQNuaWwEAmRxCQC5CQIJAMwIAgkApAMBBQJjVwkAzAgCCQCkAwEFAmNZCQDMCAIJAKQDAQUCZG4JAMwIAgkApAMBBQJkbwkAzAgCCQCkAwEFAmNPCQDMCAIJAKQDAQUCY24JAMwIAgkApAMBBQJjWgkAzAgCCQCkAwEFAmRhCQDMCAIJAKQDAQUCZGcJAMwIAgkApAMBBQJkaAUDbmlsAgE6CQCVCgMFAmRsBQJkcAUCZHEBAmRyAgJhRQJhVQQCZHMJAQJhcwAEAmR0CQCRAwIFAmRzBQJhbQQCYXYJANkEAQUCZHQEAmF3CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZHMFAmFuBAJheAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRzBQJhbwQCYXkJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkcwUCYXADCQECIT0CCQCQAwEIBQJhRQhwYXltZW50cwABCQACAQI0aW52YWxpZCBwYXltZW50IC0gZXhhY3Qgb25lIHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQCY3oJAJEDAggFAmFFCHBheW1lbnRzAAAEAmR1CAUCY3oGYW1vdW50AwkBAiE9AgUCYXYJAQV2YWx1ZQEIBQJjegdhc3NldElkCQACAQkArAICCQCsAgICHmludmFsaWQgYXNzZXQgaXMgaW4gcGF5bWVudCAtIAUCZHQCDCBpcyBleHBlY3RlZAQCZHYJAQJiYQAEAmNJCQClCAEIBQJhRQZjYWxsZXIEAmR3CQEJaXNEZWZpbmVkAQkAoggBCQECYmIBBQJjSQQCY00DBQJkdwkBBXZhbHVlAQkAoggBCQECYmIBBQJjSQkApAMBCQEBawIFBHRoaXMFAmR2BAJhUgkBDXBhcnNlSW50VmFsdWUBBQJjTQQCYlMFBmhlaWdodAQCY3IJAQJiZQEFAmNNBAJjcwkBAmJmAQUCY00EAmNxCQECYmQBBQJjTQMJAGYCBQJhdwUCZHUJAAIBCQCsAgICImFtb3VudCBpcyBsZXNzIHRoZW4gbWluTG9ja0Ftb3VudD0JAKQDAQUCYXcDCQBmAgUCYXgFAmFVCQACAQkArAICAi1wYXNzZWQgZHVyYXRpb24gaXMgbGVzcyB0aGVuIG1pbkxvY2tEdXJhdGlvbj0JAKQDAQUCYXgDCQBmAgUCYVUFAmF5CQACAQkArAICAjBwYXNzZWQgZHVyYXRpb24gaXMgZ3JlYXRlciB0aGVuIG1heExvY2tEdXJhdGlvbj0JAKQDAQUCYXkDAwUCZHcJAGcCCQBkAgkBAWsCBQR0aGlzBQJjcgkBAWsCBQR0aGlzBQJjcwUCYlMHCQACAQI2dGhlcmUgaXMgYW4gYWN0aXZlIGxvY2sgLSBjb25zaWRlciB0byB1c2UgaW5jcmVhc2VMb2NrAwkAZgIJAQFoAgUEdGhpcwUCY3EAAAkAAgEJAKwCAgI0dGhlcmUgYXJlIGxvY2tlZCBXWHMgLSBjb25zaWRlciB0byB1c2UgaW5jcmVhc2VMb2NrIAUCY3EEAmR4CQBrAwUCYVUFAWMFAmF5BAJkeQkAawMFAmR1BQJkeAUBYwQCZHoJAQFuAQkA/AcEBQJhdAIVY2FsY0d3eFBhcmFtc1JFQURPTkxZCQDMCAIFAmR5CQDMCAIFAmJTCQDMCAIFAmFVBQNuaWwFA25pbAQCYlQJAQFxAQkAkQMCBQJkegAABAJiVQkBAXEBCQCRAwIFAmR6AAEEAmJqCQCkAwEJAQFxAQkAkQMCBQJkegACBAJjUQkBAWsCBQJiegkBAmFlAAQCZEEJAQFrAgUCYnoJAQJhZwAEAmNTCQEBawIFAmJ6CQECYWoABAJjbgMJAGYCBQZoZWlnaHQFAmNTBQJjUwUGaGVpZ2h0BAJjVAkAlgMBCQDMCAIJAGUCBQJjbgUCZEEJAMwIAgAABQNuaWwEAmNWCQECYnABBQJjTQQCY1gJAGkCCQBoAgkAaAIFAmNRBQJjVAACAAMEAmRiCQECYnMBBQJjTQQCZGMJAQJidAAEAmRkCQBpAgkAaAIFAmR5BQJhVQACBAJkZQkBAWgCBQR0aGlzBQJkYwQCYk0JAQJiRwEHBAJkQgMFAmR3BQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIFAmR2CQBkAgUCYVIAAQkAzAgCCQELU3RyaW5nRW50cnkCCQECYmIBBQJjSQUCY00JAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmJjAQUCY00FAmNJBQNuaWwJAJQKAgkAzggCCQDNCAIJAM4IAgkAzggCBQJkQgkBAmNwCAUCY0kFAmNNBQJkdQUCYlMFAmFVBQJiVAUCYlUFAmJqCQECYlgEBQJkdQUCYVUAAQMFAmR3AAAAAQkBAmJQCAIEbG9jawUCY0kFAmR1BQJiUwUCYVUFAmJUBQJiVQUCYUUJAMwIAgkBDEludGVnZXJFbnRyeQIFAmNWBQJjWAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmJ3AAkAZAIFAmJNBQJkeQUDbmlsBQJkeQwCYUUBC2NvbnN0cnVjdG9yBgJkQwJkRAJhdwJkRQJkRgJhdAQCZEcJAQJhRAEFAmFFAwkAAAIFAmRHBQJkRwkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYmEAAAAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFyAAkBAmF6BQUCZEQFAmF3BQJkRQUCZEYFAmF0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQF4AAUCZEMFA25pbAkBAmJYBAAAAAAAAAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFFAQdsb2NrUmVmAwJhVQJkSAJkSQQCZEoJAQJkcgIFAmFFBQJhVQQCZEsIBQJkSgJfMQQCZHkIBQJkSgJfMgQCZEwJAKUIAQgFAmFFBmNhbGxlcgQCZE0DAwkAAAIFAmRIAgAGCQAAAgUCZEkBAAUEdW5pdAkA/AcEBQF0AgpjcmVhdGVQYWlyCQDMCAIFAXcJAMwIAgUCZEgJAMwIAgUCZEwJAMwIAgUCZEkFA25pbAUDbmlsAwkAAAIFAmRNBQJkTQQCZE4JAPwHBAUCYXQCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUCYUUGY2FsbGVyCQDMCAIFAmR5BQNuaWwFA25pbAMJAAACBQJkTgUCZE4JAJQKAgUCZEsFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYUUBBGxvY2sBAmFVBAJkTwkBAmRyAgUCYUUFAmFVBAJkSwgFAmRPAl8xBAJkeQgFAmRPAl8yBAJkTgkA/AcEBQJhdAIWdXBkYXRlUmVmZXJyYWxBY3Rpdml0eQkAzAgCCQClCAEIBQJhRQZjYWxsZXIJAMwIAgUCZHkFA25pbAUDbmlsAwkAAAIFAmROBQJkTgkAlAoCBQJkSwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhRQEMaW5jcmVhc2VMb2NrAQJkUAQCZHMJAQJhcwAEAmR0CQCRAwIFAmRzBQJhbQQCYXYJANkEAQUCZHQEAmF4CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCZHMFAmFvBAJheQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRzBQJhcAQCZHUJAQJjeAIFAmFFBQJhdgQCY0kJAKUIAQgFAmFFBmNhbGxlcgQCY0wJAQJhUAEFAmNJBAJjTQkAkQMCBQJjTAUCYUgEAmRRCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY0wFAmFJBAJiUwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmNMBQJhSgQCZFIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjTAUCYUsEAmRTCQBkAgUCYlMFAmRSBAJkVAkAlgMBCQDMCAIJAGUCBQJkUwUGaGVpZ2h0CQDMCAIAAAUDbmlsBAJkVQkAZAIFAmRRBQJkdQQCZFYJAGQCBQJkVAUCZFADCQBmAgAABQJkUAkAAgECGmR1cmF0aW9uIGlzIGxlc3MgdGhlbiB6ZXJvAwkAZgIFAmF4BQJkVgkAAgEJAKwCAgItbG9ja0R1cmF0aW9uTmV3IGlzIGxlc3MgdGhlbiBtaW5Mb2NrRHVyYXRpb249CQCkAwEFAmF4AwkAZgIFAmRWBQJheQkAAgEJAKwCAgJEZGVsdGFEdXJhdGlvbiArIGV4aXN0ZWRMb2NrRHVyYXRpb24gaXMgZ3JlYXRlciB0aGVuIG1heExvY2tEdXJhdGlvbj0JAKQDAQUCYXkEAmR4CQBrAwUCZFYFAWMFAmF5BAJkeQkAawMFAmRVBQJkeAUBYwQCZE4JAPwHBAUCYXQCFnVwZGF0ZVJlZmVycmFsQWN0aXZpdHkJAMwIAgkApQgBCAUCYUUGY2FsbGVyCQDMCAIFAmR5BQNuaWwFA25pbAMJAAACBQJkTgUCZE4EAmRXBQZoZWlnaHQEAmR6CQEBbgEJAPwHBAUCYXQCFWNhbGNHd3hQYXJhbXNSRUFET05MWQkAzAgCBQJkeQkAzAgCBQJkVwkAzAgCBQJkVgUDbmlsBQNuaWwEAmJUCQEBcQEJAJEDAgUCZHoAAAQCYlUJAQFxAQkAkQMCBQJkegABBAJiagkApAMBCQEBcQEJAJEDAgUCZHoAAgQCY1EJAQFrAgUCYnoJAQJhZQAEAmRBCQEBawIFAmJ6CQECYWcABAJjUwkBAWsCBQJiegkBAmFqAAQCY24DCQBmAgUGaGVpZ2h0BQJjUwUCY1MFBmhlaWdodAQCY1QJAJYDAQkAzAgCCQBlAgUCY24FAmRBCQDMCAIAAAUDbmlsBAJjVgkBAmJwAQUCY00EAmNXCQEBaAIFBHRoaXMFAmNWBAJjWAkAaQIJAGgCCQBoAgUCY1EFAmNUAAIAAwQCY1kJAGUCBQJjWAUCY1cDCQBmAgAABQJjWQkAAgECEndyb25nIGNhbGN1bGF0aW9ucwQCZGIJAQJicwEFAmNNBAJkYwkBAmJ0AAQCZGQJAQFoAgUEdGhpcwUCZGIEAmRlCQEBaAIFBHRoaXMFAmRjBAJkWAkBAmNGAQUCY0kEAmRZCQBlAgUCZHkFAmRYAwkAZgIAAAUCZFkJAAIBCQCsAgICGGd3eERpZmYgaXMgbGVzcyB0aGVuIDA6IAkApAMBBQJkWQQCYk0JAQJiRwEHBAJkWgkBAmJHAQYEAmRpCQECYnUBBQJjTQQCZGoJAQFoAgUEdGhpcwUCZGkEAmRsCQBrAwUCY1kFAmRYBQJkWgQCZWEJAGkCCQBoAgUCZHkFAmRWAAIEAmViCQBpAgkAaAIFAmRYBQJkVAACBAJlYwkAZQIFAmVhBQJlYgkAzggCCQDNCAIJAM4IAgkBAmNwCAUCY0kFAmNNBQJkVQUCZFcFAmRWBQJiVAUCYlUFAmJqCQECYlgEBQJkdQUCZFAAAAAACQECYlAIAgRsb2NrBQJjSQUCZHUFAmJTBQJkVgUCYlQFAmJVBQJhRQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmJ3AAkAZAIFAmJNBQJkWQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFFAQxjbGFpbVd4Qm9vc3QCAmNIAmNJAwkBAiE9AgUCYkEIBQJhRQZjYWxsZXIJAAIBAhJwZXJtaXNzaW9ucyBkZW5pZWQEAmVkCQECY0cDBQJjSAUCY0kHBAJkbwgFAmVkAl8xBAJkcAgFAmVkAl8yBAJkcQgFAmVkAl8zCQCUCgIFAmRwCQDMCAIFAmRvBQNuaWwCYUUBFGNsYWltV3hCb29zdFJFQURPTkxZAgJjSAJjSQQCZWUJAQJjRwMFAmNIBQJjSQYEAmRvCAUCZWUCXzEEAmRwCAUCZWUCXzIEAmRxCAUCZWUCXzMJAJQKAgUDbmlsCQDMCAIFAmRvCQDMCAIFAmRxBQNuaWwCYUUBBnVubG9jawECYU8EAmNMCQECYVABBQJhTwQCY00JAJEDAgUCY0wFAmFIBAJkUQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmNMBQJhSQQCYlMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjTAUCYUoEAmRSCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY0wFAmFLBAJkUwkAZAIFAmJTBQJkUgQCZHMJAQJhcwAEAmF2CQDZBAEJAJEDAgUCZHMFAmFtAwkAZwIFAmRTBQZoZWlnaHQJAAIBCQCsAgIJAKwCAgIFd2FpdCAJAKQDAQUCZFMCCiB0byB1bmxvY2sDCQBnAgAABQJkUQkAAgECEW5vdGhpbmcgdG8gdW5sb2NrBAJiagkBC3ZhbHVlT3JFbHNlAgkAmggCBQJhdAkBAmFrAAAACQDNCAIJAM0IAgkAzggCCQECY3AIBQJhTwUCY00AAAUCYlMFAmRSAAAAAAkApAMBBQJiagkBAmJYBAkBAS0BBQJkUQAAAAAA////////////AQkBAmJQCAIGdW5sb2NrBQJhTwUCZFEFAmJTBQJkUgAAAAAFAmFFCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQJhTwUCZFEFAmF2AmFFARNnd3hVc2VySW5mb1JFQURPTkxZAQJhTwQCYVkJAQJjRgEFAmFPCQCUCgIFA25pbAkAzAgCBQJhWQUDbmlsAmFFASBnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHRSRUFET05MWQICYU8CY0IEAmFZCQECY0ECBQJhTwUCY0IJAJQKAgUDbmlsBQJhWQJhRQEZZ2V0VG90YWxDYWNoZWRHd3hSRUFET05MWQAJAJQKAgUDbmlsCQECYkcBBgJhRQEKc2V0TWFuYWdlcgECZWYEAmRHCQECYUQBBQJhRQMJAAACBQJkRwUCZEcEAmVnCQDZBAEFAmVmAwkAAAIFAmVnBQJlZwkAzAgCCQELU3RyaW5nRW50cnkCCQECYWQABQJlZgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFFAQ5jb25maXJtTWFuYWdlcgAEAmVoCQECYUMABAJlaQMJAQlpc0RlZmluZWQBBQJlaAYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZWkFAmVpBAJlagMJAAACCAUCYUUPY2FsbGVyUHVibGljS2V5CQEFdmFsdWUBBQJlaAYJAAIBAhtZb3UgYXJlIG5vdCBwZW5kaW5nIG1hbmFnZXIDCQAAAgUCZWoFAmVqCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhYwAJANgEAQkBBXZhbHVlAQUCZWgJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBAmFkAAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJlawECZWwABAJlbQQBbwkBAmFBAAMJAAECBQFvAgpCeXRlVmVjdG9yBAJhRwUBbwUCYUcDCQABAgUBbwIEVW5pdAgFAmVrD3NlbmRlclB1YmxpY0tleQkAAgECC01hdGNoIGVycm9yCQD0AwMIBQJlawlib2R5Qnl0ZXMJAJEDAggFAmVrBnByb29mcwAABQJlbTU2Dr8=", "height": 2450613, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 8Riu22NE2M5oWYCakjGFNKwJ31wB82n8CCfUQk4GJA66 Next: Exks2UkriPFqjRP5E8F3QS8vd8gYfCLqdJdYVVTQQwU1 Diff:
OldNewDifferences
130130
131131
132132 func keyEmissionStartBlock () = "%s%s__emission__startBlock"
133+
134+
135+func keyBoostingV2StartHeight () = "%s%s__boostingV2__startBlock"
133136
134137
135138 func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
271274 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
272275
273276
274-func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
277+func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastIntV2", userNum], SEP)
275278
276279
277-func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastInt", userNum, lpAssetId], SEP)
280+func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastIntV2", userNum, lpAssetId], SEP)
278281
279282
280283 func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
305308
306309 let gwxRewardContract = getGwxRewardAddressOrFail(factoryCfg)
307310
311+let keyVotingEmissionContract = makeString(["%s", "votingEmissionContract"], SEP)
312+
313+let votingEmissionContract = addressFromStringValue(getStringValue(factoryContract, keyVotingEmissionContract))
314+
315+let boostCoeff = {
316+ let @ = invoke(emissionContract, "getBoostCoeffREADONLY", nil, nil)
317+ if ($isInstanceOf(@, "Int"))
318+ then @
319+ else throw(($getType(@) + " couldn't be cast to Int"))
320+ }
321+
308322 func getTotalCachedGwx (correct) = {
309- let keyVotingEmissionContract = makeString(["%s", "votingEmissionContract"], SEP)
310- let votingEmissionContract = addressFromStringValue(getStringValue(factoryContract, keyVotingEmissionContract))
311323 let keyCurrentEpochUi = makeString(["%s", "currentEpochUi"], SEP)
312324 let currentEpochUi = getIntegerValue(votingEmissionContract, keyCurrentEpochUi)
313325 let keyTargetEpoch = makeString(["%s%s", "totalCachedGwxCorrection__activationEpoch"], SEP)
401413 else {
402414 let userRecordArray = split(userRecordOrEmpty, SEP)
403415 let userNumStr = userRecordArray[IdxLockUserNum]
404- let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
405416 let EMPTYSTR = "empty"
406- let $t01496515533 = if ((lpAssetIdStr != EMPTYSTR))
417+ let poolWeight = if ((lpAssetIdStr != EMPTYSTR))
407418 then {
408419 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
409- let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
410- let pw0 = valueOrElse(getInteger(factoryContract, keyFactoryPoolWeightHistory(poolAddressStr, 0)), pw1)
411- $Tuple2(pw0, pw1)
420+ getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
412421 }
413422 else if (readOnly)
414- then $Tuple2(0, 0)
423+ then 0
415424 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
416- let poolWeight0 = $t01496515533._1
417- let poolWeight1 = $t01496515533._2
418425 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
419- let emissionStart = iof(emissionContract, keyEmissionStartBlock())
426+ let boostingV2StartHeight = iof(emissionContract, keyBoostingV2StartHeight())
420427 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
421428 let h = if ((height > emissionEnd))
422429 then emissionEnd
423430 else height
424- let dh = max([(h - emissionStart), 0])
431+ let dh = max([(h - boostingV2StartHeight), 0])
425432 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNumStr, lpAssetIdStr)
426433 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
427434 let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), ioz(this, userBoostEmissionLastIntegralKEY))
428- let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
435+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * (boostCoeff - 1)) / boostCoeff)
429436 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
430- let udh = fraction(userBoostEmissionIntegral, 3, (2 * wxEmissionPerBlock))
437+ let udh = fraction(userBoostEmissionIntegral, boostCoeff, ((boostCoeff - 1) * wxEmissionPerBlock))
431438 let uLastH = (h - udh)
432- let udh0 = max([(gwxRewardEmissionStartHeight - uLastH), 0])
433- let udh1 = ((h - uLastH) - udh0)
434- if (if (if ((0 > uLastH))
435- then true
436- else (0 > udh1))
437- then true
438- else (abs(((udh0 + udh1) - udh)) >= 1))
439- then throw(((((((("invalid udh calc: udh=" + toString(udh)) + " uLastH=") + toString(uLastH)) + " udh0=") + toString(udh0)) + " udh1=") + toString(udh1)))
440- else if ((0 > userBoostEmissionIntegral))
441- then throw("wrong calculations")
442- else {
443- let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
444- let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
445- let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
446- let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
447- let totalCachedGwxCorrected = getTotalCachedGwx(true)
448- let userCurrGwx = calcCurrentGwxAmount(userAddressStr)
449- let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
450- let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
451- let userBoostEmissionIntegral0 = if ((udh == 0))
452- then 0
453- else fraction(userBoostEmissionIntegral, udh0, udh)
454- let userBoostEmissionIntegral1 = if ((udh == 0))
455- then 0
456- else fraction(userBoostEmissionIntegral, udh1, udh)
457- let poolUserBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral0, poolWeight0, POOLWEIGHTMULT)
458- let poolUserBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral1, poolWeight1, POOLWEIGHTMULT)
459- let userBoostAvaliableToClaimTotalNew0 = if ((totalCachedGwxCorrected == 0))
460- then 0
461- else fraction(poolUserBoostEmissionIntegral0, userCurrGwx, totalCachedGwxCorrected)
462- let userBoostAvaliableToClaimTotalNew1 = if ((totalCachedGwxCorrected == 0))
463- then 0
464- else fraction(poolUserBoostEmissionIntegral1, userCurrGwx, totalCachedGwxCorrected)
465- let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotalNew0 + userBoostAvaliableToClaimTotalNew1)
466- let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
467- let userBoostClaimed = ioz(this, userBoostClaimedKEY)
468- let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
469- let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
470- 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)], ":")
471- $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
439+ if ((0 > userBoostEmissionIntegral))
440+ then throw("wrong calculations")
441+ else {
442+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
443+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
444+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
445+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
446+ let $t01675316890 = {
447+ let @ = invoke(votingEmissionContract, "getVoteInfoREADONLY", [lpAssetIdStr, userAddressStr], nil)
448+ if ($isInstanceOf(@, "(Int, Int)"))
449+ then @
450+ else throw(($getType(@) + " couldn't be cast to (Int, Int)"))
472451 }
452+ let userVote = $t01675316890._1
453+ let totalVotes = $t01675316890._2
454+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
455+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
456+ let poolUserBoostEmissionIntegral = fraction(userBoostEmissionIntegral, poolWeight, POOLWEIGHTMULT)
457+ let userBoostAvaliableToClaimTotalNew = if ((totalVotes == 0))
458+ then 0
459+ else fraction(poolUserBoostEmissionIntegral, userVote, totalVotes)
460+ let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
461+ let userBoostClaimed = ioz(this, userBoostClaimedKEY)
462+ let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
463+ let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
464+ let debug = makeString([toString(userBoostEmissionLastIntegral), toString(userBoostEmissionIntegral), toString(userBoostClaimed), toString(userBoostAvailable), toString(poolWeight), toString(h), toString(udh), toString(uLastH), toString(userVote), toString(totalVotes)], ":")
465+ $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
466+ }
473467 }
474468 }
475469
557551
558552 @Callable(i)
559553 func lockRef (duration,referrerAddress,signature) = {
560- let $t02389223957 = lockActions(i, duration)
561- let lockActionsResult = $t02389223957._1
562- let gWxAmountStart = $t02389223957._2
554+ let $t02284222907 = lockActions(i, duration)
555+ let lockActionsResult = $t02284222907._1
556+ let gWxAmountStart = $t02284222907._2
563557 let referralAddress = toString(i.caller)
564558 let refInv = if (if ((referrerAddress == ""))
565559 then true
580574
581575 @Callable(i)
582576 func lock (duration) = {
583- let $t02441524480 = lockActions(i, duration)
584- let lockActionsResult = $t02441524480._1
585- let gWxAmountStart = $t02441524480._2
577+ let $t02336523430 = lockActions(i, duration)
578+ let lockActionsResult = $t02336523430._1
579+ let gWxAmountStart = $t02336523430._2
586580 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
587581 if ((updateRefActivity == updateRefActivity))
588582 then $Tuple2(lockActionsResult, unit)
671665 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
672666 then throw("permissions denied")
673667 else {
674- let $t02946129563 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
675- let userBoostAvailable = $t02946129563._1
676- let dataState = $t02946129563._2
677- let debug = $t02946129563._3
668+ let $t02841128513 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
669+ let userBoostAvailable = $t02841128513._1
670+ let dataState = $t02841128513._2
671+ let debug = $t02841128513._3
678672 $Tuple2(dataState, [userBoostAvailable])
679673 }
680674
682676
683677 @Callable(i)
684678 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
685- let $t02969529796 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
686- let userBoostAvailable = $t02969529796._1
687- let dataState = $t02969529796._2
688- let debug = $t02969529796._3
679+ let $t02864528746 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
680+ let userBoostAvailable = $t02864528746._1
681+ let dataState = $t02864528746._2
682+ let debug = $t02864528746._3
689683 $Tuple2(nil, [userBoostAvailable, debug])
690684 }
691685
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"
133+
134+
135+func keyBoostingV2StartHeight () = "%s%s__boostingV2__startBlock"
133136
134137
135138 func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
136139
137140
138141 func keyEmissionEndBlock () = "%s%s__emission__endBlock"
139142
140143
141144 func keyNextPeriod () = "%s__nextPeriod"
142145
143146
144147 func keyGwxRewardEmissionStartHeight () = "%s%s__gwxRewardEmissionPart__startHeight"
145148
146149
147150 let IdxCfgAssetId = 1
148151
149152 let IdxCfgMinLockAmount = 2
150153
151154 let IdxCfgMinLockDuration = 3
152155
153156 let IdxCfgMaxLockDuration = 4
154157
155158 let IdxCfgMathContract = 5
156159
157160 func keyConfig () = "%s__config"
158161
159162
160163 func readConfigArrayOrFail () = split(strf(this, keyConfig()), SEP)
161164
162165
163166 let mathContract = addressFromStringValue(readConfigArrayOrFail()[IdxCfgMathContract])
164167
165168 func formatConfigS (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = makeString(["%s%d%d%d", assetId, minLockAmount, minLockDuration, maxLockDuration, mathContract], SEP)
166169
167170
168171 func formatConfig (assetId,minLockAmount,minLockDuration,maxLockDuration,mathContract) = formatConfigS(assetId, toString(minLockAmount), toString(minLockDuration), toString(maxLockDuration), mathContract)
169172
170173
171174 func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
172175 case s: String =>
173176 fromBase58String(s)
174177 case _: Unit =>
175178 unit
176179 case _ =>
177180 throw("Match error")
178181 }
179182
180183
181184 func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
182185 case s: String =>
183186 fromBase58String(s)
184187 case _: Unit =>
185188 unit
186189 case _ =>
187190 throw("Match error")
188191 }
189192
190193
191194 func mustManager (i) = {
192195 let pd = throw("Permission denied")
193196 match managerPublicKeyOrUnit() {
194197 case pk: ByteVector =>
195198 if ((i.callerPublicKey == pk))
196199 then true
197200 else pd
198201 case _: Unit =>
199202 if ((i.caller == this))
200203 then true
201204 else pd
202205 case _ =>
203206 throw("Match error")
204207 }
205208 }
206209
207210
208211 let IdxLockUserNum = 1
209212
210213 let IdxLockAmount = 2
211214
212215 let IdxLockStart = 3
213216
214217 let IdxLockDuration = 4
215218
216219 let IdxLockParamK = 5
217220
218221 let IdxLockParamB = 6
219222
220223 func keyLockParamsRecord (userAddress) = makeString(["%s%s__lock", userAddress], SEP)
221224
222225
223226 func readLockParamsRecordOrFail (userAddress) = split(strf(this, keyLockParamsRecord(userAddress)), SEP)
224227
225228
226229 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)
227230
228231
229232 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))
230233
231234
232235 func keyNextUserNum () = "%s__nextUserNum"
233236
234237
235238 func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
236239
237240
238241 func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
239242
240243
241244 func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
242245
243246
244247 func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
245248
246249
247250 func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
248251
249252
250253 func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
251254
252255
253256 func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
254257
255258
256259 func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
257260
258261
259262 func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
260263
261264
262265 func keyLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
263266
264267
265268 func keyStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
266269
267270
268271 func keyStatsLocksCount () = "%s%s__stats__locksCount"
269272
270273
271274 func keyStatsUsersCount () = "%s%s__stats__activeUsersCount"
272275
273276
274-func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
277+func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastIntV2", userNum], SEP)
275278
276279
277-func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastInt", userNum, lpAssetId], SEP)
280+func keyUserLpBoostEmissionLastINTEGRAL (userNum,lpAssetId) = makeString(["%s%d__userBoostEmissionLastIntV2", userNum, lpAssetId], SEP)
278281
279282
280283 func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
281284
282285
283286 func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
284287
285288
286289 func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
287290
288291
289292 func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
290293
291294
292295 func keyTotalCachedGwx () = "%s%s__gwxCached__total"
293296
294297
295298 func keyTotalCachedGwxCorrective () = "%s__gwxCachedTotalCorrective"
296299
297300
298301 let factoryContract = readFactoryAddressOrFail()
299302
300303 let factoryCfg = readFactoryCfgOrFail(factoryContract)
301304
302305 let emissionContract = getEmissionAddressOrFail(factoryCfg)
303306
304307 let stakingContract = getStakingAddressOrFail(factoryCfg)
305308
306309 let gwxRewardContract = getGwxRewardAddressOrFail(factoryCfg)
307310
311+let keyVotingEmissionContract = makeString(["%s", "votingEmissionContract"], SEP)
312+
313+let votingEmissionContract = addressFromStringValue(getStringValue(factoryContract, keyVotingEmissionContract))
314+
315+let boostCoeff = {
316+ let @ = invoke(emissionContract, "getBoostCoeffREADONLY", nil, nil)
317+ if ($isInstanceOf(@, "Int"))
318+ then @
319+ else throw(($getType(@) + " couldn't be cast to Int"))
320+ }
321+
308322 func getTotalCachedGwx (correct) = {
309- let keyVotingEmissionContract = makeString(["%s", "votingEmissionContract"], SEP)
310- let votingEmissionContract = addressFromStringValue(getStringValue(factoryContract, keyVotingEmissionContract))
311323 let keyCurrentEpochUi = makeString(["%s", "currentEpochUi"], SEP)
312324 let currentEpochUi = getIntegerValue(votingEmissionContract, keyCurrentEpochUi)
313325 let keyTargetEpoch = makeString(["%s%s", "totalCachedGwxCorrection__activationEpoch"], SEP)
314326 let targetEpochOption = getInteger(this, keyTargetEpoch)
315327 let totalCachedGwxRaw = valueOrElse(getInteger(this, keyTotalCachedGwx()), 0)
316328 let isCorrectionActivated = if (isDefined(targetEpochOption))
317329 then (currentEpochUi >= value(targetEpochOption))
318330 else false
319331 let corrective = if (if (isCorrectionActivated)
320332 then correct
321333 else false)
322334 then valueOrElse(getInteger(this, keyTotalCachedGwxCorrective()), 0)
323335 else 0
324336 max([0, (totalCachedGwxRaw + corrective)])
325337 }
326338
327339
328340 func HistoryEntry (type,user,amount,lockStart,duration,k,b,i) = {
329341 let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP)
330342 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)
331343 StringEntry(historyKEY, historyDATA)
332344 }
333345
334346
335347 func StatsEntry (totalLockedInc,durationInc,lockCountInc,usersCountInc) = {
336348 let locksDurationSumInBlocksKEY = keyStatsLocksDurationSumInBlocks()
337349 let locksCountKEY = keyStatsLocksCount()
338350 let usersCountKEY = keyStatsUsersCount()
339351 let totalAmountKEY = keyLockParamTotalAmount()
340352 let locksDurationSumInBlocks = ioz(this, locksDurationSumInBlocksKEY)
341353 let locksCount = ioz(this, locksCountKEY)
342354 let usersCount = ioz(this, usersCountKEY)
343355 let totalAmount = ioz(this, totalAmountKEY)
344356 [IntegerEntry(locksDurationSumInBlocksKEY, (locksDurationSumInBlocks + durationInc)), IntegerEntry(locksCountKEY, (locksCount + lockCountInc)), IntegerEntry(usersCountKEY, (usersCount + usersCountInc)), IntegerEntry(totalAmountKEY, (totalAmount + totalLockedInc))]
345357 }
346358
347359
348360 func calcGwxAmount (kRaw,bRaw,h) = {
349361 let SCALE = 1000
350362 (((kRaw * h) + bRaw) / SCALE)
351363 }
352364
353365
354366 func LockParamsEntry (userAddress,userNum,amount,start,duration,k,b,period) = {
355367 let userAmountKEY = keyLockParamUserAmount(userNum)
356368 let startBlockKEY = keyLockParamStartBlock(userNum)
357369 let durationKEY = keyLockParamDuration(userNum)
358370 let kKEY = keyLockParamK(userNum)
359371 let bKEY = keyLockParamB(userNum)
360372 let kByPeriodKEY = keyLockParamByPeriodK(userNum, period)
361373 let bByPeriodKEY = keyLockParamByPeriodB(userNum, period)
362374 let gwxAmount = calcGwxAmount(k, b, height)
363375 [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))]
364376 }
365377
366378
367379 func extractOptionalPaymentAmountOrFail (i,expectedAssetId) = if ((size(i.payments) > 1))
368380 then throw("only one payment is allowed")
369381 else if ((size(i.payments) == 0))
370382 then 0
371383 else {
372384 let pmt = i.payments[0]
373385 if ((value(pmt.assetId) != expectedAssetId))
374386 then throw("invalid asset id in payment")
375387 else pmt.amount
376388 }
377389
378390
379391 func calcUserGwxAmountAtHeight (userAddress,targetHeight) = {
380392 let EMPTY = "empty"
381393 let user2NumMappingKEY = keyUser2NumMapping(userAddress)
382394 let userNum = valueOrElse(getString(user2NumMappingKEY), EMPTY)
383395 let k = valueOrElse(getInteger(keyLockParamK(userNum)), 0)
384396 let b = valueOrElse(getInteger(keyLockParamB(userNum)), 0)
385397 let gwxAmountCalc = calcGwxAmount(k, b, targetHeight)
386398 let gwxAmount = if ((0 > gwxAmountCalc))
387399 then 0
388400 else gwxAmountCalc
389401 gwxAmount
390402 }
391403
392404
393405 func calcCurrentGwxAmount (userAddress) = calcUserGwxAmountAtHeight(userAddress, height)
394406
395407
396408 func internalClaimWxBoost (lpAssetIdStr,userAddressStr,readOnly) = {
397409 let EMPTY = "EMPTY"
398410 let userRecordOrEmpty = valueOrElse(getString(this, keyLockParamsRecord(userAddressStr)), EMPTY)
399411 if ((userRecordOrEmpty == EMPTY))
400412 then $Tuple3(0, nil, "userRecord::is::empty")
401413 else {
402414 let userRecordArray = split(userRecordOrEmpty, SEP)
403415 let userNumStr = userRecordArray[IdxLockUserNum]
404- let gwxRewardEmissionStartHeight = valueOrElse(getInteger(gwxRewardContract, keyGwxRewardEmissionStartHeight()), 0)
405416 let EMPTYSTR = "empty"
406- let $t01496515533 = if ((lpAssetIdStr != EMPTYSTR))
417+ let poolWeight = if ((lpAssetIdStr != EMPTYSTR))
407418 then {
408419 let poolAddressStr = valueOrErrorMessage(getString(factoryContract, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
409- let pw1 = getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
410- let pw0 = valueOrElse(getInteger(factoryContract, keyFactoryPoolWeightHistory(poolAddressStr, 0)), pw1)
411- $Tuple2(pw0, pw1)
420+ getIntegerValue(factoryContract, keyFactoryPoolWeight(poolAddressStr))
412421 }
413422 else if (readOnly)
414- then $Tuple2(0, 0)
423+ then 0
415424 else throw(("not readonly mode: unsupported lp asset " + lpAssetIdStr))
416- let poolWeight0 = $t01496515533._1
417- let poolWeight1 = $t01496515533._2
418425 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
419- let emissionStart = iof(emissionContract, keyEmissionStartBlock())
426+ let boostingV2StartHeight = iof(emissionContract, keyBoostingV2StartHeight())
420427 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
421428 let h = if ((height > emissionEnd))
422429 then emissionEnd
423430 else height
424- let dh = max([(h - emissionStart), 0])
431+ let dh = max([(h - boostingV2StartHeight), 0])
425432 let userLpBoostEmissionLastIntegralKEY = keyUserLpBoostEmissionLastINTEGRAL(userNumStr, lpAssetIdStr)
426433 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
427434 let userBoostEmissionLastIntegral = valueOrElse(getInteger(this, userLpBoostEmissionLastIntegralKEY), ioz(this, userBoostEmissionLastIntegralKEY))
428- let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
435+ let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * (boostCoeff - 1)) / boostCoeff)
429436 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
430- let udh = fraction(userBoostEmissionIntegral, 3, (2 * wxEmissionPerBlock))
437+ let udh = fraction(userBoostEmissionIntegral, boostCoeff, ((boostCoeff - 1) * wxEmissionPerBlock))
431438 let uLastH = (h - udh)
432- let udh0 = max([(gwxRewardEmissionStartHeight - uLastH), 0])
433- let udh1 = ((h - uLastH) - udh0)
434- if (if (if ((0 > uLastH))
435- then true
436- else (0 > udh1))
437- then true
438- else (abs(((udh0 + udh1) - udh)) >= 1))
439- then throw(((((((("invalid udh calc: udh=" + toString(udh)) + " uLastH=") + toString(uLastH)) + " udh0=") + toString(udh0)) + " udh1=") + toString(udh1)))
440- else if ((0 > userBoostEmissionIntegral))
441- then throw("wrong calculations")
442- else {
443- let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
444- let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
445- let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
446- let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
447- let totalCachedGwxCorrected = getTotalCachedGwx(true)
448- let userCurrGwx = calcCurrentGwxAmount(userAddressStr)
449- let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
450- let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
451- let userBoostEmissionIntegral0 = if ((udh == 0))
452- then 0
453- else fraction(userBoostEmissionIntegral, udh0, udh)
454- let userBoostEmissionIntegral1 = if ((udh == 0))
455- then 0
456- else fraction(userBoostEmissionIntegral, udh1, udh)
457- let poolUserBoostEmissionIntegral0 = fraction(userBoostEmissionIntegral0, poolWeight0, POOLWEIGHTMULT)
458- let poolUserBoostEmissionIntegral1 = fraction(userBoostEmissionIntegral1, poolWeight1, POOLWEIGHTMULT)
459- let userBoostAvaliableToClaimTotalNew0 = if ((totalCachedGwxCorrected == 0))
460- then 0
461- else fraction(poolUserBoostEmissionIntegral0, userCurrGwx, totalCachedGwxCorrected)
462- let userBoostAvaliableToClaimTotalNew1 = if ((totalCachedGwxCorrected == 0))
463- then 0
464- else fraction(poolUserBoostEmissionIntegral1, userCurrGwx, totalCachedGwxCorrected)
465- let userBoostAvaliableToClaimTotalNew = (userBoostAvaliableToClaimTotalNew0 + userBoostAvaliableToClaimTotalNew1)
466- let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
467- let userBoostClaimed = ioz(this, userBoostClaimedKEY)
468- let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
469- let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
470- 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)], ":")
471- $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
439+ if ((0 > userBoostEmissionIntegral))
440+ then throw("wrong calculations")
441+ else {
442+ let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
443+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
444+ let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
445+ let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
446+ let $t01675316890 = {
447+ let @ = invoke(votingEmissionContract, "getVoteInfoREADONLY", [lpAssetIdStr, userAddressStr], nil)
448+ if ($isInstanceOf(@, "(Int, Int)"))
449+ then @
450+ else throw(($getType(@) + " couldn't be cast to (Int, Int)"))
472451 }
452+ let userVote = $t01675316890._1
453+ let totalVotes = $t01675316890._2
454+ let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
455+ let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
456+ let poolUserBoostEmissionIntegral = fraction(userBoostEmissionIntegral, poolWeight, POOLWEIGHTMULT)
457+ let userBoostAvaliableToClaimTotalNew = if ((totalVotes == 0))
458+ then 0
459+ else fraction(poolUserBoostEmissionIntegral, userVote, totalVotes)
460+ let userBoostClaimedKEY = keyUserBoostClaimed(userNumStr)
461+ let userBoostClaimed = ioz(this, userBoostClaimedKEY)
462+ let userBoostAvailable = (userBoostAvaliableToClaimTotalNew - userBoostClaimed)
463+ let dataState = [IntegerEntry(userLpBoostEmissionLastIntegralKEY, boostEmissionIntegral)]
464+ let debug = makeString([toString(userBoostEmissionLastIntegral), toString(userBoostEmissionIntegral), toString(userBoostClaimed), toString(userBoostAvailable), toString(poolWeight), toString(h), toString(udh), toString(uLastH), toString(userVote), toString(totalVotes)], ":")
465+ $Tuple3(userBoostAvaliableToClaimTotalNew, dataState, debug)
466+ }
473467 }
474468 }
475469
476470
477471 func lockActions (i,duration) = {
478472 let cfgArray = readConfigArrayOrFail()
479473 let assetIdStr = cfgArray[IdxCfgAssetId]
480474 let assetId = fromBase58String(assetIdStr)
481475 let minLockAmount = parseIntValue(cfgArray[IdxCfgMinLockAmount])
482476 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
483477 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
484478 if ((size(i.payments) != 1))
485479 then throw("invalid payment - exact one payment must be attached")
486480 else {
487481 let pmt = i.payments[0]
488482 let pmtAmount = pmt.amount
489483 if ((assetId != value(pmt.assetId)))
490484 then throw((("invalid asset is in payment - " + assetIdStr) + " is expected"))
491485 else {
492486 let nextUserNumKEY = keyNextUserNum()
493487 let userAddressStr = toString(i.caller)
494488 let userIsExisting = isDefined(getString(keyUser2NumMapping(userAddressStr)))
495489 let userNumStr = if (userIsExisting)
496490 then value(getString(keyUser2NumMapping(userAddressStr)))
497491 else toString(iof(this, nextUserNumKEY))
498492 let userNum = parseIntValue(userNumStr)
499493 let lockStart = height
500494 let startBlockKEY = keyLockParamStartBlock(userNumStr)
501495 let durationKEY = keyLockParamDuration(userNumStr)
502496 let userAmountKEY = keyLockParamUserAmount(userNumStr)
503497 if ((minLockAmount > pmtAmount))
504498 then throw(("amount is less then minLockAmount=" + toString(minLockAmount)))
505499 else if ((minLockDuration > duration))
506500 then throw(("passed duration is less then minLockDuration=" + toString(minLockDuration)))
507501 else if ((duration > maxLockDuration))
508502 then throw(("passed duration is greater then maxLockDuration=" + toString(maxLockDuration)))
509503 else if (if (userIsExisting)
510504 then ((iof(this, startBlockKEY) + iof(this, durationKEY)) >= lockStart)
511505 else false)
512506 then throw("there is an active lock - consider to use increaseLock")
513507 else if ((ioz(this, userAmountKEY) > 0))
514508 then throw(("there are locked WXs - consider to use increaseLock " + userAmountKEY))
515509 else {
516510 let coeffX8 = fraction(duration, MULT8, maxLockDuration)
517511 let gWxAmountStart = fraction(pmtAmount, coeffX8, MULT8)
518512 let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStart, duration], nil))
519513 let k = ai(gWxParamsResultList[0])
520514 let b = ai(gWxParamsResultList[1])
521515 let period = toString(ai(gWxParamsResultList[2]))
522516 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
523517 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
524518 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
525519 let h = if ((height > emissionEnd))
526520 then emissionEnd
527521 else height
528522 let dh = max([(h - emissionStart), 0])
529523 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
530524 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
531525 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
532526 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
533527 let userMaxBoostInt = ((gWxAmountStart * duration) / 2)
534528 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
535529 let totalCachedGwxRaw = getTotalCachedGwx(false)
536530 let arr = if (userIsExisting)
537531 then nil
538532 else [IntegerEntry(nextUserNumKEY, (userNum + 1)), StringEntry(keyUser2NumMapping(userAddressStr), userNumStr), StringEntry(keyNum2UserMapping(userNumStr), userAddressStr)]
539533 $Tuple2(((((arr ++ LockParamsEntry(userAddressStr, userNumStr, pmtAmount, lockStart, duration, k, b, period)) ++ StatsEntry(pmtAmount, duration, 1, if (userIsExisting)
540534 then 0
541535 else 1)) :+ HistoryEntry("lock", userAddressStr, pmtAmount, lockStart, duration, k, b, i)) ++ [IntegerEntry(userBoostEmissionLastIntegralKEY, boostEmissionIntegral), IntegerEntry(keyTotalCachedGwx(), (totalCachedGwxRaw + gWxAmountStart))]), gWxAmountStart)
542536 }
543537 }
544538 }
545539 }
546540
547541
548542 @Callable(i)
549543 func constructor (factoryAddressStr,lockAssetIdStr,minLockAmount,minDuration,maxDuration,mathContract) = {
550544 let checkCaller = mustManager(i)
551545 if ((checkCaller == checkCaller))
552546 then ([IntegerEntry(keyNextUserNum(), 0), StringEntry(keyConfig(), formatConfig(lockAssetIdStr, minLockAmount, minDuration, maxDuration, mathContract)), StringEntry(keyFactoryAddress(), factoryAddressStr)] ++ StatsEntry(0, 0, 0, 0))
553547 else throw("Strict value is not equal to itself.")
554548 }
555549
556550
557551
558552 @Callable(i)
559553 func lockRef (duration,referrerAddress,signature) = {
560- let $t02389223957 = lockActions(i, duration)
561- let lockActionsResult = $t02389223957._1
562- let gWxAmountStart = $t02389223957._2
554+ let $t02284222907 = lockActions(i, duration)
555+ let lockActionsResult = $t02284222907._1
556+ let gWxAmountStart = $t02284222907._2
563557 let referralAddress = toString(i.caller)
564558 let refInv = if (if ((referrerAddress == ""))
565559 then true
566560 else (signature == base58''))
567561 then unit
568562 else invoke(referralsContractAddressOrFail, "createPair", [referralProgramName, referrerAddress, referralAddress, signature], nil)
569563 if ((refInv == refInv))
570564 then {
571565 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
572566 if ((updateRefActivity == updateRefActivity))
573567 then $Tuple2(lockActionsResult, unit)
574568 else throw("Strict value is not equal to itself.")
575569 }
576570 else throw("Strict value is not equal to itself.")
577571 }
578572
579573
580574
581575 @Callable(i)
582576 func lock (duration) = {
583- let $t02441524480 = lockActions(i, duration)
584- let lockActionsResult = $t02441524480._1
585- let gWxAmountStart = $t02441524480._2
577+ let $t02336523430 = lockActions(i, duration)
578+ let lockActionsResult = $t02336523430._1
579+ let gWxAmountStart = $t02336523430._2
586580 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
587581 if ((updateRefActivity == updateRefActivity))
588582 then $Tuple2(lockActionsResult, unit)
589583 else throw("Strict value is not equal to itself.")
590584 }
591585
592586
593587
594588 @Callable(i)
595589 func increaseLock (deltaDuration) = {
596590 let cfgArray = readConfigArrayOrFail()
597591 let assetIdStr = cfgArray[IdxCfgAssetId]
598592 let assetId = fromBase58String(assetIdStr)
599593 let minLockDuration = parseIntValue(cfgArray[IdxCfgMinLockDuration])
600594 let maxLockDuration = parseIntValue(cfgArray[IdxCfgMaxLockDuration])
601595 let pmtAmount = extractOptionalPaymentAmountOrFail(i, assetId)
602596 let userAddressStr = toString(i.caller)
603597 let userRecordArray = readLockParamsRecordOrFail(userAddressStr)
604598 let userNumStr = userRecordArray[IdxLockUserNum]
605599 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
606600 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
607601 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
608602 let lockEnd = (lockStart + lockDuration)
609603 let remainingDuration = max([(lockEnd - height), 0])
610604 let userAmountNew = (userAmount + pmtAmount)
611605 let lockDurationNew = (remainingDuration + deltaDuration)
612606 if ((0 > deltaDuration))
613607 then throw("duration is less then zero")
614608 else if ((minLockDuration > lockDurationNew))
615609 then throw(("lockDurationNew is less then minLockDuration=" + toString(minLockDuration)))
616610 else if ((lockDurationNew > maxLockDuration))
617611 then throw(("deltaDuration + existedLockDuration is greater then maxLockDuration=" + toString(maxLockDuration)))
618612 else {
619613 let coeffX8 = fraction(lockDurationNew, MULT8, maxLockDuration)
620614 let gWxAmountStart = fraction(userAmountNew, coeffX8, MULT8)
621615 let updateRefActivity = invoke(mathContract, "updateReferralActivity", [toString(i.caller), gWxAmountStart], nil)
622616 if ((updateRefActivity == updateRefActivity))
623617 then {
624618 let lockStartNew = height
625619 let gWxParamsResultList = aal(invoke(mathContract, "calcGwxParamsREADONLY", [gWxAmountStart, lockStartNew, lockDurationNew], nil))
626620 let k = ai(gWxParamsResultList[0])
627621 let b = ai(gWxParamsResultList[1])
628622 let period = toString(ai(gWxParamsResultList[2]))
629623 let wxEmissionPerBlock = iof(emissionContract, keyEmissionRatePerBlockCurrent())
630624 let emissionStart = iof(emissionContract, keyEmissionStartBlock())
631625 let emissionEnd = iof(emissionContract, keyEmissionEndBlock())
632626 let h = if ((height > emissionEnd))
633627 then emissionEnd
634628 else height
635629 let dh = max([(h - emissionStart), 0])
636630 let userBoostEmissionLastIntegralKEY = keyUserBoostEmissionLastINTEGRAL(userNumStr)
637631 let userBoostEmissionLastIntegral = ioz(this, userBoostEmissionLastIntegralKEY)
638632 let boostEmissionIntegral = (((wxEmissionPerBlock * dh) * 2) / 3)
639633 let userBoostEmissionIntegral = (boostEmissionIntegral - userBoostEmissionLastIntegral)
640634 if ((0 > userBoostEmissionIntegral))
641635 then throw("wrong calculations")
642636 else {
643637 let userMaxBoostIntegralKEY = keyUserMaxBoostINTEGRAL(userNumStr)
644638 let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
645639 let userMaxBoostInt = ioz(this, userMaxBoostIntegralKEY)
646640 let totalMaxBoostInt = ioz(this, totalMaxBoostIntegralKEY)
647641 let currUserGwx = calcCurrentGwxAmount(userAddressStr)
648642 let gwxDiff = (gWxAmountStart - currUserGwx)
649643 if ((0 > gwxDiff))
650644 then throw(("gwxDiff is less then 0: " + toString(gwxDiff)))
651645 else {
652646 let totalCachedGwxRaw = getTotalCachedGwx(false)
653647 let totalCachedGwxCorrected = getTotalCachedGwx(true)
654648 let userBoostAvalaibleToClaimTotalKEY = keyUserBoostAvalaibleToClaimTotal(userNumStr)
655649 let userBoostAvaliableToClaimTotal = ioz(this, userBoostAvalaibleToClaimTotalKEY)
656650 let userBoostAvaliableToClaimTotalNew = fraction(userBoostEmissionIntegral, currUserGwx, totalCachedGwxCorrected)
657651 let userMaxBoostIntNew = ((gWxAmountStart * lockDurationNew) / 2)
658652 let remainingUserMaxBoostInt = ((currUserGwx * remainingDuration) / 2)
659653 let userMaxBoostIntDiff = (userMaxBoostIntNew - remainingUserMaxBoostInt)
660654 (((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))])
661655 }
662656 }
663657 }
664658 else throw("Strict value is not equal to itself.")
665659 }
666660 }
667661
668662
669663
670664 @Callable(i)
671665 func claimWxBoost (lpAssetIdStr,userAddressStr) = if ((stakingContract != i.caller))
672666 then throw("permissions denied")
673667 else {
674- let $t02946129563 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
675- let userBoostAvailable = $t02946129563._1
676- let dataState = $t02946129563._2
677- let debug = $t02946129563._3
668+ let $t02841128513 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, false)
669+ let userBoostAvailable = $t02841128513._1
670+ let dataState = $t02841128513._2
671+ let debug = $t02841128513._3
678672 $Tuple2(dataState, [userBoostAvailable])
679673 }
680674
681675
682676
683677 @Callable(i)
684678 func claimWxBoostREADONLY (lpAssetIdStr,userAddressStr) = {
685- let $t02969529796 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
686- let userBoostAvailable = $t02969529796._1
687- let dataState = $t02969529796._2
688- let debug = $t02969529796._3
679+ let $t02864528746 = internalClaimWxBoost(lpAssetIdStr, userAddressStr, true)
680+ let userBoostAvailable = $t02864528746._1
681+ let dataState = $t02864528746._2
682+ let debug = $t02864528746._3
689683 $Tuple2(nil, [userBoostAvailable, debug])
690684 }
691685
692686
693687
694688 @Callable(i)
695689 func unlock (userAddress) = {
696690 let userRecordArray = readLockParamsRecordOrFail(userAddress)
697691 let userNumStr = userRecordArray[IdxLockUserNum]
698692 let userAmount = parseIntValue(userRecordArray[IdxLockAmount])
699693 let lockStart = parseIntValue(userRecordArray[IdxLockStart])
700694 let lockDuration = parseIntValue(userRecordArray[IdxLockDuration])
701695 let lockEnd = (lockStart + lockDuration)
702696 let cfgArray = readConfigArrayOrFail()
703697 let assetId = fromBase58String(cfgArray[IdxCfgAssetId])
704698 if ((lockEnd >= height))
705699 then throw((("wait " + toString(lockEnd)) + " to unlock"))
706700 else if ((0 >= userAmount))
707701 then throw("nothing to unlock")
708702 else {
709703 let period = valueOrElse(getInteger(mathContract, keyNextPeriod()), 0)
710704 (((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))
711705 }
712706 }
713707
714708
715709
716710 @Callable(i)
717711 func gwxUserInfoREADONLY (userAddress) = {
718712 let gwxAmount = calcCurrentGwxAmount(userAddress)
719713 $Tuple2(nil, [gwxAmount])
720714 }
721715
722716
723717
724718 @Callable(i)
725719 func getUserGwxAmountAtHeightREADONLY (userAddress,targetHeight) = {
726720 let gwxAmount = calcUserGwxAmountAtHeight(userAddress, targetHeight)
727721 $Tuple2(nil, gwxAmount)
728722 }
729723
730724
731725
732726 @Callable(i)
733727 func getTotalCachedGwxREADONLY () = $Tuple2(nil, getTotalCachedGwx(true))
734728
735729
736730
737731 @Callable(i)
738732 func setManager (pendingManagerPublicKey) = {
739733 let checkCaller = mustManager(i)
740734 if ((checkCaller == checkCaller))
741735 then {
742736 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
743737 if ((checkManagerPublicKey == checkManagerPublicKey))
744738 then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
745739 else throw("Strict value is not equal to itself.")
746740 }
747741 else throw("Strict value is not equal to itself.")
748742 }
749743
750744
751745
752746 @Callable(i)
753747 func confirmManager () = {
754748 let pm = pendingManagerPublicKeyOrUnit()
755749 let hasPM = if (isDefined(pm))
756750 then true
757751 else throw("No pending manager")
758752 if ((hasPM == hasPM))
759753 then {
760754 let checkPM = if ((i.callerPublicKey == value(pm)))
761755 then true
762756 else throw("You are not pending manager")
763757 if ((checkPM == checkPM))
764758 then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
765759 else throw("Strict value is not equal to itself.")
766760 }
767761 else throw("Strict value is not equal to itself.")
768762 }
769763
770764
771765 @Verifier(tx)
772766 func verify () = {
773767 let targetPublicKey = match managerPublicKeyOrUnit() {
774768 case pk: ByteVector =>
775769 pk
776770 case _: Unit =>
777771 tx.senderPublicKey
778772 case _ =>
779773 throw("Match error")
780774 }
781775 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
782776 }
783777

github/deemru/w8io/3ef1775 
123.69 ms