tx · FnjdA9Rj9FxjWAKpa45AtPk5xfNBPzmKCN2dqmAzu8xx

3MuS6qVvhBR6wSynFRdcE3fVqmGBjoc7Hhx:  -0.01400000 Waves

2023.07.27 14:19 [2684188] smart account 3MuS6qVvhBR6wSynFRdcE3fVqmGBjoc7Hhx > SELF 0.00000000 Waves

{ "type": 13, "id": "FnjdA9Rj9FxjWAKpa45AtPk5xfNBPzmKCN2dqmAzu8xx", "fee": 1400000, "feeAssetId": null, "timestamp": 1690456684589, "version": 2, "chainId": 84, "sender": "3MuS6qVvhBR6wSynFRdcE3fVqmGBjoc7Hhx", "senderPublicKey": "62CHk4MqTdq3LqeUycy7TPnpvwrjgerSa2FqAY2EafXn", "proofs": [ "mJEatqbbgnbTn3251YUJUbxRVG1ST82AMnxWHF4jeygFj4uYxkjSXc667N8uzMrfyaDDLfENTeS7DSYgX9ou7hY" ], "script": "base64:BwJoCAISBAoCCAgSBAoCCAESBAoCCAQSBAoCCAISAwoBCBIDCgEBEgMKAQESBQoDAgECEgUKAwIYGBIECgICARIECgICARIFCgMBAQESBQoDAQEBEgASAwoBCBIAEgASAwoBCBIAEgMKAQgxAANTRVACAl9fAAVXQVZFUwIFV0FWRVMAEGNvbnRyYWN0RmlsZW5hbWUCDGZhY3RvcnkucmlkZQEHd3JhcEVycgEBcwkArAICCQCsAgIFEGNvbnRyYWN0RmlsZW5hbWUCAjogBQFzAQh0aHJvd0VycgEBcwkAAgEJAQd3cmFwRXJyAQUBcwEPc3RyaW5nVG9Bc3NldElkAQFzAwkAAAIFAXMFBVdBVkVTBQR1bml0CQDZBAEFAXMAD0FETUlOX0xJU1RfU0laRQAFAAZRVU9SVU0AAwARVFhJRF9CWVRFU19MRU5HVEgAIAEYa2V5QWxsb3dlZFR4SWRWb3RlUHJlZml4AQR0eElkCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICCWFsbG93VHhJZAkAzAgCBQR0eElkBQNuaWwFA1NFUAEQa2V5RnVsbEFkbWluVm90ZQIGcHJlZml4DGFkbWluQWRkcmVzcwkAuQkCCQDMCAIFBnByZWZpeAkAzAgCBQxhZG1pbkFkZHJlc3MFA25pbAUDU0VQARNrZXlBZG1pbkFkZHJlc3NMaXN0AAkAuQkCCQDMCAICAiVzCQDMCAICEGFkbWluQWRkcmVzc0xpc3QFA25pbAUDU0VQAQ5rZXlBbGxvd2VkVHhJZAAJALkJAgkAzAgCAgIlcwkAzAgCAgR0eElkBQNuaWwFA1NFUAEMZ2V0QWRtaW5Wb3RlAgZwcmVmaXgFYWRtaW4EB3ZvdGVLZXkJARBrZXlGdWxsQWRtaW5Wb3RlAgUGcHJlZml4BQVhZG1pbgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQd2b3RlS2V5AAABDWdldEFkbWluc0xpc3QABAckbWF0Y2gwCQCdCAIFBHRoaXMJARNrZXlBZG1pbkFkZHJlc3NMaXN0AAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJALUJAgUBcwUDU0VQBQNuaWwBDWlzSW5BZG1pbkxpc3QBB2FkZHJlc3MJAQ9jb250YWluc0VsZW1lbnQCCQENZ2V0QWRtaW5zTGlzdAAFB2FkZHJlc3MBEmdlblZvdGVzS2V5c0hlbHBlcgIBYQxhZG1pbkFkZHJlc3MECyR0MDEzNzUxMzk5BQFhBAZyZXN1bHQIBQskdDAxMzc1MTM5OQJfMQQGcHJlZml4CAULJHQwMTM3NTEzOTkCXzIJAJQKAgkAzQgCBQZyZXN1bHQJARBrZXlGdWxsQWRtaW5Wb3RlAgUGcHJlZml4BQxhZG1pbkFkZHJlc3MFBnByZWZpeAEMZ2VuVm90ZXNLZXlzAQlrZXlQcmVmaXgECWFkbWluTGlzdAkBE2tleUFkbWluQWRkcmVzc0xpc3QABAskdDAxNTQ2MTYzMAoAAiRsCQENZ2V0QWRtaW5zTGlzdAAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAUJa2V5UHJlZml4CgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARJnZW5Wb3Rlc0tleXNIZWxwZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFBAZyZXN1bHQIBQskdDAxNTQ2MTYzMAJfMQQGcHJlZml4CAULJHQwMTU0NjE2MzACXzIFBnJlc3VsdAEQY291bnRWb3Rlc0hlbHBlcgIGcmVzdWx0B3ZvdGVLZXkJAGQCBQZyZXN1bHQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUHdm90ZUtleQAAAQpjb3VudFZvdGVzAQZwcmVmaXgEBXZvdGVzCQEMZ2VuVm90ZXNLZXlzAQUGcHJlZml4CgACJGwFBXZvdGVzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARBjb3VudFZvdGVzSGVscGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQEQY2xlYXJWb3Rlc0hlbHBlcgIGcmVzdWx0A2tleQkAzQgCBQZyZXN1bHQJAQtEZWxldGVFbnRyeQEFA2tleQETZ2V0Q2xlYXJWb3RlRW50cmllcwEGcHJlZml4BAV2b3RlcwkBDGdlblZvdGVzS2V5cwEFBnByZWZpeAoAAiRsBQV2b3RlcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQY2xlYXJWb3Rlc0hlbHBlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUBDHZvdGVJTlRFUk5BTAQTY2FsbGVyQWRkcmVzc1N0cmluZwlrZXlQcmVmaXgIbWluVm90ZXMKdm90ZVJlc3VsdAQHdm90ZUtleQkBEGtleUZ1bGxBZG1pblZvdGUCBQlrZXlQcmVmaXgFE2NhbGxlckFkZHJlc3NTdHJpbmcEEGFkbWluQ3VycmVudFZvdGUJAQxnZXRBZG1pblZvdGUCBQlrZXlQcmVmaXgFE2NhbGxlckFkZHJlc3NTdHJpbmcEA2VycgMJAQEhAQkBDWlzSW5BZG1pbkxpc3QBBRNjYWxsZXJBZGRyZXNzU3RyaW5nCQEIdGhyb3dFcnIBCQCsAgIJAKwCAgIJQWRkcmVzczogBRNjYWxsZXJBZGRyZXNzU3RyaW5nAhIgbm90IGluIEFkbWluIGxpc3QDCQAAAgUQYWRtaW5DdXJyZW50Vm90ZQABCQEIdGhyb3dFcnIBCQCsAgIFB3ZvdGVLZXkCEiB5b3UgYWxyZWFkeSB2b3RlZAUEdW5pdAMJAAACBQNlcnIFA2VycgQFdm90ZXMJAQpjb3VudFZvdGVzAQUJa2V5UHJlZml4AwkAZwIJAGQCBQV2b3RlcwABBQhtaW5Wb3RlcwQQY2xlYXJWb3RlRW50cmllcwkBE2dldENsZWFyVm90ZUVudHJpZXMBBQlrZXlQcmVmaXgJAM4IAgUQY2xlYXJWb3RlRW50cmllcwUKdm90ZVJlc3VsdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdm90ZUtleQABBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BFGtleUNhbGN1bGF0b3JBZGRyZXNzAAIOJXNfX2NhbGN1bGF0b3IBF2tleVByb3h5VHJlYXN1cnlBZGRyZXNzAAIRJXNfX3Byb3h5VHJlYXN1cnkBD2tleUNoaWxkQWRkcmVzcwACCSVzX19jaGlsZAEYa2V5QmxvY2tQcm9jZXNzaW5nUmV3YXJkAAIZJXNfX2Jsb2NrUHJvY2Vzc2luZ1Jld2FyZAEVa2V5TmV4dEJsb2NrVG9Qcm9jZXNzAAIWJXNfX25leHRCbG9ja1RvUHJvY2VzcwEMa2V5THBBc3NldElkAAINJXNfX2xwQXNzZXRJZAAXY2FsY3VsYXRvckFkZHJlc3NPcHRpb24EByRtYXRjaDAJAJ0IAgUEdGhpcwkBFGtleUNhbGN1bGF0b3JBZGRyZXNzAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJAKYIAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IAF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsCQETdmFsdWVPckVycm9yTWVzc2FnZQIFF2NhbGN1bGF0b3JBZGRyZXNzT3B0aW9uCQEHd3JhcEVycgECGmludmFsaWQgY2FsY3VsYXRvciBhZGRyZXNzABpwcm94eVRyZWFzdXJ5QWRkcmVzc09wdGlvbgQHJG1hdGNoMAkAnQgCBQR0aGlzCQEXa2V5UHJveHlUcmVhc3VyeUFkZHJlc3MAAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkApggBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgAacHJveHlUcmVhc3VyeUFkZHJlc3NPckZhaWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgUacHJveHlUcmVhc3VyeUFkZHJlc3NPcHRpb24JAQd3cmFwRXJyAQIeaW52YWxpZCBwcm94eSB0cmVhc3VyeSBhZGRyZXNzARBrZXlDb25maWdBZGRyZXNzAAIKJXNfX2NvbmZpZwESa2V5Q2hpbGRyZW5BZGRyZXNzAAIRY29udHJhY3RfY2hpbGRyZW4BFmtleVZvdGluZ1Jlc3VsdEFkZHJlc3MAAhZjb250cmFjdF92b3RpbmdfcmVzdWx0ARlrZXlQcm9wb3NhbEFsbG93QnJvYWRjYXN0AgdhZGRyZXNzBHR4SWQJAKwCAgkArAICCQCsAgICGXByb3Bvc2FsX2FsbG93X2Jyb2FkY2FzdF8JAKUIAQUHYWRkcmVzcwIBXwkA2AQBBQR0eElkARFrZXlJbnZlc3RlZEJ5VXNlcgIMY2hpbGRBZGRyZXNzC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIIaW52ZXN0b3IJAMwIAgkApQgBBQxjaGlsZEFkZHJlc3MJAMwIAgkApQgBBQt1c2VyQWRkcmVzcwUDbmlsAgFfABNjb25maWdBZGRyZXNzT3B0aW9uBAckbWF0Y2gwCQCdCAIFBHRoaXMJARBrZXlDb25maWdBZGRyZXNzAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJAKYIAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IAE2NvbmZpZ0FkZHJlc3NPckZhaWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgUTY29uZmlnQWRkcmVzc09wdGlvbgkBB3dyYXBFcnIBAhZpbnZhbGlkIGNvbmZpZyBhZGRyZXNzABl2b3RpbmdSZXN1bHRBZGRyZXNzT3B0aW9uBAckbWF0Y2gwBRNjb25maWdBZGRyZXNzT3B0aW9uAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAEByRtYXRjaDEJAJ0IAgUBYQkBFmtleVZvdGluZ1Jlc3VsdEFkZHJlc3MAAwkAAQIFByRtYXRjaDECBlN0cmluZwQBcwUHJG1hdGNoMQkApggBBQFzAwkAAQIFByRtYXRjaDECBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IAGXZvdGluZ1Jlc3VsdEFkZHJlc3NPckZhaWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgUZdm90aW5nUmVzdWx0QWRkcmVzc09wdGlvbgkBB3dyYXBFcnIBAh1pbnZhbGlkIHZvdGluZyByZXN1bHQgYWRkcmVzcwAVY2hpbGRyZW5BZGRyZXNzT3B0aW9uBAckbWF0Y2gwBRNjb25maWdBZGRyZXNzT3B0aW9uAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAEByRtYXRjaDEJAJ0IAgUBYQkBEmtleUNoaWxkcmVuQWRkcmVzcwADCQABAgUHJG1hdGNoMQIGU3RyaW5nBAFzBQckbWF0Y2gxCQCmCAEFAXMDCQABAgUHJG1hdGNoMQIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgAVY2hpbGRyZW5BZGRyZXNzT3JGYWlsCQETdmFsdWVPckVycm9yTWVzc2FnZQIFFWNoaWxkcmVuQWRkcmVzc09wdGlvbgkBB3dyYXBFcnIBAhhpbnZhbGlkIGNoaWxkcmVuIGFkZHJlc3MAD2xwQXNzZXRJZE9wdGlvbgQHJG1hdGNoMAkAnQgCBQR0aGlzCQEMa2V5THBBc3NldElkAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJANkEAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IAD2xwQXNzZXRJZE9yRmFpbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBQ9scEFzc2V0SWRPcHRpb24JAQd3cmFwRXJyAQIRaW52YWxpZCBscEFzc2V0SWQBC29ubHlBZGRyZXNzAgFpB2FkZHJlc3MDCQAAAggFAWkGY2FsbGVyBQdhZGRyZXNzBgkBCHRocm93RXJyAQIRcGVybWlzc2lvbiBkZW5pZWQBCG9ubHlUaGlzAQFpCQELb25seUFkZHJlc3MCBQFpBQR0aGlzAQ5vbmx5Q2FsY3VsYXRvcgEBaQkBC29ubHlBZGRyZXNzAgUBaQUXY2FsY3VsYXRvckFkZHJlc3NPckZhaWwUAWkBC3N0cmluZ0VudHJ5AgNrZXkDdmFsAwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFA2tleQUDdmFsBQNuaWwFA2tleQkAlAoCBQNuaWwFBHVuaXQBaQEMaW50ZWdlckVudHJ5AgNrZXkDdmFsAwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQNrZXkFA3ZhbAUDbmlsBQNrZXkJAJQKAgUDbmlsBQR1bml0AWkBDGJvb2xlYW5FbnRyeQIDa2V5A3ZhbAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQEMQm9vbGVhbkVudHJ5AgUDa2V5BQN2YWwFA25pbAUDa2V5CQCUCgIFA25pbAUEdW5pdAFpAQtiaW5hcnlFbnRyeQIDa2V5A3ZhbAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQELQmluYXJ5RW50cnkCBQNrZXkFA3ZhbAUDbmlsBQNrZXkJAJQKAgUDbmlsBQR1bml0AWkBC2RlbGV0ZUVudHJ5AQNrZXkDCQEOb25seUNhbGN1bGF0b3IBBQFpCQCUCgIJAMwIAgkBC0RlbGV0ZUVudHJ5AQUDa2V5BQNuaWwFA2tleQkAlAoCBQNuaWwFBHVuaXQBaQEHcmVpc3N1ZQEGYW1vdW50AwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCCQDMCAIJAQdSZWlzc3VlAwUPbHBBc3NldElkT3JGYWlsBQZhbW91bnQGBQNuaWwFBmFtb3VudAkAlAoCBQNuaWwFBHVuaXQBaQEEYnVybgEGYW1vdW50AwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCCQDMCAIJAQRCdXJuAgUPbHBBc3NldElkT3JGYWlsBQZhbW91bnQFA25pbAUGYW1vdW50CQCUCgIFA25pbAUEdW5pdAFpAQ10cmFuc2ZlckFzc2V0Aw5yZWNlcGllbnRCeXRlcwZhbW91bnQHYXNzZXRJZAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEFDnJlY2VwaWVudEJ5dGVzBQZhbW91bnQFB2Fzc2V0SWQFA25pbAUGYW1vdW50CQCUCgIFA25pbAUEdW5pdAFpAQ50cmFuc2ZlckFzc2V0cwMOcmVjZXBpZW50Qnl0ZXMKYXNzZXRzTGlzdAthbW91bnRzTGlzdAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkKAQ5hZGROZXdUcmFuc2ZlcgIFYWNjdW0LbmV4dEFzc2V0SWQECyR0MDc0NTc3NDgzBQVhY2N1bQQJdHJhbnNmZXJzCAULJHQwNzQ1Nzc0ODMCXzEEAWoIBQskdDA3NDU3NzQ4MwJfMgQLbmV3VHJhbnNmZXIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQUOcmVjZXBpZW50Qnl0ZXMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQthbW91bnRzTGlzdAUBagkBD3N0cmluZ1RvQXNzZXRJZAEJAJEDAgUKYXNzZXRzTGlzdAUBagQQdXBkYXRlZFRyYW5zZmVycwkAzQgCBQl0cmFuc2ZlcnMFC25ld1RyYW5zZmVyCQCUCgIFEHVwZGF0ZWRUcmFuc2ZlcnMJAGQCBQFqAAEECyR0MDc3NDM3ODI0CgACJGwFCmFzc2V0c0xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ5hZGROZXdUcmFuc2ZlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQPYXNzZXRzVHJhbnNmZXJzCAULJHQwNzc0Mzc4MjQCXzEECl9sYXN0SW5kZXgIBQskdDA3NzQzNzgyNAJfMgkAlAoCBQ9hc3NldHNUcmFuc2ZlcnMFBHVuaXQJAJQKAgUDbmlsBQR1bml0AWkBDXRyYW5zZmVyV2F2ZXMCDnJlY2VwaWVudEJ5dGVzBmFtb3VudAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEFDnJlY2VwaWVudEJ5dGVzBQZhbW91bnQFBHVuaXQFA25pbAUGYW1vdW50CQCUCgIFA25pbAUEdW5pdAFpARl0cmFuc2ZlckZyb21Qcm94eVRyZWFzdXJ5Ag5yZWNpcGllbnRCeXRlcw1yZXdhcmRzQW1vdW50AwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCBQNuaWwJAPwHBAUacHJveHlUcmVhc3VyeUFkZHJlc3NPckZhaWwCDXRyYW5zZmVyV2F2ZXMJAMwIAgUOcmVjaXBpZW50Qnl0ZXMJAMwIAgUNcmV3YXJkc0Ftb3VudAUDbmlsBQNuaWwJAJQKAgUDbmlsBQR1bml0AWkBCGZpbmFsaXplAxhuZXdUcmVhc3VyeVZvbHVtZUluV2F2ZXMXcHdyTWFuYWdlcnNCb251c0luV2F2ZXMgdHJlYXN1cnlWb2x1bWVEaWZmQWxsb2NhdGlvbkNvZWYJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAghmaW5hbGl6ZQkAzAgCCAgFAWkGY2FsbGVyBWJ5dGVzCQDMCAIFGG5ld1RyZWFzdXJ5Vm9sdW1lSW5XYXZlcwkAzAgCBRdwd3JNYW5hZ2Vyc0JvbnVzSW5XYXZlcwkAzAgCBSB0cmVhc3VyeVZvbHVtZURpZmZBbGxvY2F0aW9uQ29lZgUDbmlsCAUBaQhwYXltZW50cwFpARBmaW5hbGl6ZVJFQURPTkxZAxhuZXdUcmVhc3VyeVZvbHVtZUluV2F2ZXMXcHdyTWFuYWdlcnNCb251c0luV2F2ZXMgdHJlYXN1cnlWb2x1bWVEaWZmQWxsb2NhdGlvbkNvZWYJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAhBmaW5hbGl6ZVJFQURPTkxZCQDMCAIFGG5ld1RyZWFzdXJ5Vm9sdW1lSW5XYXZlcwkAzAgCBRdwd3JNYW5hZ2Vyc0JvbnVzSW5XYXZlcwkAzAgCBSB0cmVhc3VyeVZvbHVtZURpZmZBbGxvY2F0aW9uQ29lZgUDbmlsBQNuaWwBaQEHY2xhaW1MUAAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAgdjbGFpbUxQCQDMCAIICAUBaQZjYWxsZXIFYnl0ZXMFA25pbAgFAWkIcGF5bWVudHMBaQEPY2xhaW1Db2xsYXRlcmFsAQd0eElkU3RyCQCUCgIFA25pbAkA/QcEBRdjYWxjdWxhdG9yQWRkcmVzc09yRmFpbAIPY2xhaW1Db2xsYXRlcmFsCQDMCAIICAUBaQZjYWxsZXIFYnl0ZXMJAMwIAgkA2QQBBQd0eElkU3RyBQNuaWwIBQFpCHBheW1lbnRzAWkBBmludmVzdAAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAgZpbnZlc3QJAMwIAggIBQFpBmNhbGxlcgVieXRlcwUDbmlsCAUBaQhwYXltZW50cwFpAQh3aXRoZHJhdwAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAgh3aXRoZHJhdwkAzAgCCAgFAWkGY2FsbGVyBWJ5dGVzBQNuaWwIBQFpCHBheW1lbnRzAWkBDmNhbmNlbFdpdGhkcmF3AQd0eElkU3RyCQCUCgIFA25pbAkA/QcEBRdjYWxjdWxhdG9yQWRkcmVzc09yRmFpbAIOY2FuY2VsV2l0aGRyYXcJAMwIAggIBQFpBmNhbGxlcgVieXRlcwkAzAgCCQDZBAEFB3R4SWRTdHIFA25pbAgFAWkIcGF5bWVudHMBaQENcHJvY2Vzc0Jsb2NrcwAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAg1wcm9jZXNzQmxvY2tzCQDMCAIICAUBaQZjYWxsZXIFYnl0ZXMFA25pbAgFAWkIcGF5bWVudHMBaQELdm90ZUZvclR4SWQBBHR4SWQEE2NhbGxlckFkZHJlc3NTdHJpbmcJANgEAQgIBQFpBmNhbGxlcgVieXRlcwQJa2V5UHJlZml4CQEYa2V5QWxsb3dlZFR4SWRWb3RlUHJlZml4AQUEdHhJZAQGcmVzdWx0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlBbGxvd2VkVHhJZAAFBHR4SWQFA25pbAQRYWxsb3dlZFR4SWRPcHRpb24JAJ0IAgUEdGhpcwkBDmtleUFsbG93ZWRUeElkAAQDZXJyCQDMCAIDCQAAAgkAyAEBCQDZBAEFBHR4SWQFEVRYSURfQllURVNfTEVOR1RIBgkBCHRocm93RXJyAQkArAICBQR0eElkAhIgaXMgbm90IHZhbGlkIHR4SWQJAMwIAgMDCQAAAgURYWxsb3dlZFR4SWRPcHRpb24FBHVuaXQGCQECIT0CCQEFdmFsdWUBBRFhbGxvd2VkVHhJZE9wdGlvbgUEdHhJZAYJAQh0aHJvd0VycgEJAKwCAgUEdHhJZAITIGlzIGFscmVhZHkgYWxsb3dlZAUDbmlsAwkAAAIFA2VycgUDZXJyCQEMdm90ZUlOVEVSTkFMBAUTY2FsbGVyQWRkcmVzc1N0cmluZwUJa2V5UHJlZml4BQZRVU9SVU0FBnJlc3VsdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAECmJ5UHJvcG9zYWwEByRtYXRjaDAFGXZvdGluZ1Jlc3VsdEFkZHJlc3NPcHRpb24DCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQPcHJvcG9zYWxBZGRyZXNzBQckbWF0Y2gwCQELdmFsdWVPckVsc2UCCQCbCAIFD3Byb3Bvc2FsQWRkcmVzcwkBGWtleVByb3Bvc2FsQWxsb3dCcm9hZGNhc3QCBQR0aGlzCAUCdHgCaWQHBwQIYnlBZG1pbnMJAAACCAUCdHgCaWQJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQEOa2V5QWxsb3dlZFR4SWQAAgAEB2J5T3duZXIDCQBnAgkAkAMBCQENZ2V0QWRtaW5zTGlzdAAFBlFVT1JVTQcJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXkDAwUKYnlQcm9wb3NhbAYFCGJ5QWRtaW5zBgUHYnlPd25lcv1ux4I=", "height": 2684188, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 4ey9kFvkF3YadfYHJ9QfATr3LvnvKiRUxjhrd3tcswrH Next: D5Td2rbPe6mDS8JpFxjA4iKjmL2Eh7q69gtXFsJkT3FZ Full:
OldNewDifferences
1-{-# STDLIB_VERSION 6 #-}
1+{-# STDLIB_VERSION 7 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let separator = "__"
4+let SEP = "__"
55
6-let MULT8 = 100000000
6+let WAVES = "WAVES"
77
8-func wrapErr (msg) = makeString(["voting_verified_v2.ride:", msg], " ")
8+let contractFilename = "factory.ride"
9+
10+func wrapErr (s) = ((contractFilename + ": ") + s)
911
1012
11-func throwErr (msg) = throw(wrapErr(msg))
13+func throwErr (s) = throw(wrapErr(s))
1214
1315
14-func asInt (val) = match val {
15- case valInt: Int =>
16- valInt
16+func stringToAssetId (s) = if ((s == WAVES))
17+ then unit
18+ else fromBase58String(s)
19+
20+
21+let ADMIN_LIST_SIZE = 5
22+
23+let QUORUM = 3
24+
25+let TXID_BYTES_LENGTH = 32
26+
27+func keyAllowedTxIdVotePrefix (txId) = makeString(["%s%s%s", "allowTxId", txId], SEP)
28+
29+
30+func keyFullAdminVote (prefix,adminAddress) = makeString([prefix, adminAddress], SEP)
31+
32+
33+func keyAdminAddressList () = makeString(["%s", "adminAddressList"], SEP)
34+
35+
36+func keyAllowedTxId () = makeString(["%s", "txId"], SEP)
37+
38+
39+func getAdminVote (prefix,admin) = {
40+ let voteKey = keyFullAdminVote(prefix, admin)
41+ valueOrElse(getInteger(voteKey), 0)
42+ }
43+
44+
45+func getAdminsList () = match getString(this, keyAdminAddressList()) {
46+ case s: String =>
47+ split(s, SEP)
1748 case _ =>
18- throw("Failed to cast into Integer")
49+ nil
1950 }
2051
2152
22-func getIntegerOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
53+func isInAdminList (address) = containsElement(getAdminsList(), address)
2354
2455
25-func getIntegerOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), wrapErr((key + " is not defined")))
26-
27-
28-func getStringOrEmpty (address,key) = valueOrElse(getString(address, key), "")
29-
30-
31-func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), wrapErr((key + " is not defined")))
32-
33-
34-let keyBoostingContract = makeString(["%s", "boostingContract"], separator)
35-
36-let keyEmissionContract = makeString(["%s", "emissionContract"], separator)
37-
38-let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
39-
40-let boostingContract = addressFromStringValue(getStringValue(keyBoostingContract))
41-
42-let emissionContract = addressFromStringValue(getStringValue(keyEmissionContract))
43-
44-let assetsStoreContract = addressFromStringValue(getStringValue(keyAssetsStoreContract))
45-
46-let keyEmissionConfig = makeString(["%s", "config"], separator)
47-
48-let wxAssetIdStr = split(getStringOrFail(emissionContract, keyEmissionConfig), separator)[1]
49-
50-let wxAssetId = fromBase58String(wxAssetIdStr)
51-
52-let keyVotingThresholdAdd = makeString(["%s%s", "votingThreshold", "add"], separator)
53-
54-let keyVotingThresholdRemove = makeString(["%s%s", "votingThreshold", "remove"], separator)
55-
56-let keyPeriodLengthRemove = makeString(["%s", "periodLengthRemove"], separator)
57-
58-let keyMaxPeriodLength = makeString(["%s", "maxPeriodLength"], separator)
59-
60-let keyMinPeriodLength = makeString(["%s", "minPeriodLength"], separator)
61-
62-func keyVotingRewardAssetId (assetId,index) = makeString(["%s%s%d", "votingRewardAssetId", assetId, toString(index)], separator)
63-
64-
65-func keyVotingReward (userAddress,assetId,index) = makeString(["%s%s%s%d", "votingReward", toString(userAddress), assetId, toString(index)], separator)
66-
67-
68-func keyTotalVotingReward (assetId,index) = makeString(["%s%s%d", "totalVotingReward", assetId, toString(index)], separator)
69-
70-
71-let keyFinalizeCallRewardAmount = makeString(["%s", "finalizeCallRewardAmount"], separator)
72-
73-let keyMinSuggestRemoveBalance = makeString(["%s", "minSuggestRemoveBalance"], separator)
74-
75-func keyCurrentIndex (assetId) = makeString(["%s%s", "currentIndex", assetId], separator)
76-
77-
78-func keyVote (assetId,index,caller) = makeString(["%s%s%d%s", "vote", assetId, toString(index), toString(caller)], separator)
79-
80-
81-func voteValue (inFavor,gwxAmount) = makeString(["%s%d", toString(inFavor), toString(gwxAmount)], separator)
82-
83-
84-func keySuggestIssuer (assetId,index) = makeString(["%s%s%d", "suggestIssuer", assetId, toString(index)], separator)
85-
86-
87-func keyClaimHistory (userAddress,assetId,index) = makeString(["%s%s%s%d", "history", toString(userAddress), assetId, toString(index)], separator)
88-
89-
90-let keyFeePerBlock = makeString(["%s", "feePerBlock"], separator)
91-
92-let feePerBlock = getIntegerOrFail(this, keyFeePerBlock)
93-
94-let keyMinWxMinForSuggestAddAmountRequired = makeString(["%s", "wxMinForSuggestAddAmountRequired"], separator)
95-
96-let keyWxForSuggestRemoveAmountRequired = makeString(["%s", "wxForSuggestRemoveAmountRequired"], separator)
97-
98-func keyVotingInfo (assetId,index) = makeString(["%s%s%d", "votingInfo", assetId, toString(index)], separator)
99-
100-
101-func votingInfoValue (isRewardExist,rewardAssetId,rewardAmount,votingType,status,votingStartHeight,votingEndHeight,votesQuorum,votesFor,votesAgainst) = makeString(["%s%s%d%s%s%d%d%d%d%d", toString(isRewardExist), rewardAssetId, toString(rewardAmount), votingType, status, toString(votingStartHeight), toString(votingEndHeight), toString(votesQuorum), toString(votesFor), toString(votesAgainst)], separator)
102-
103-
104-func keyAssetImage (assetId) = makeString(["%s%s", "assetImage", assetId], separator)
105-
106-
107-func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
108- let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
109- asInt(gwxAmount)
56+func genVotesKeysHelper (a,adminAddress) = {
57+ let $t013751399 = a
58+ let result = $t013751399._1
59+ let prefix = $t013751399._2
60+ $Tuple2((result :+ keyFullAdminVote(prefix, adminAddress)), prefix)
11061 }
11162
11263
113-func keyManagerVaultAddress () = "%s__managerVaultAddress"
64+func genVotesKeys (keyPrefix) = {
65+ let adminList = keyAdminAddressList()
66+ let $t015461630 = {
67+ let $l = getAdminsList()
68+ let $s = size($l)
69+ let $acc0 = $Tuple2(nil, keyPrefix)
70+ func $f0_1 ($a,$i) = if (($i >= $s))
71+ then $a
72+ else genVotesKeysHelper($a, $l[$i])
11473
74+ func $f0_2 ($a,$i) = if (($i >= $s))
75+ then $a
76+ else throw("List size exceeds 5")
11577
116-func keyManagerPublicKey () = "%s__managerPublicKey"
117-
118-
119-func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
120- case s: String =>
121- addressFromStringValue(s)
122- case _ =>
123- this
124-}
125-
126-
127-func managerPublicKeyOrUnit () = {
128- let managerVaultAddress = getManagerVaultAddressOrThis()
129- match getString(managerVaultAddress, keyManagerPublicKey()) {
130- case s: String =>
131- fromBase58String(s)
132- case _: Unit =>
133- unit
134- case _ =>
135- throw("Match error")
136- }
78+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
79+ }
80+ let result = $t015461630._1
81+ let prefix = $t015461630._2
82+ result
13783 }
13884
13985
140-func getVotingInfoParts (votingInfo) = {
141- let votingInfoParts = split(votingInfo, separator)
142- let isRewardExistStr = votingInfoParts[1]
143- let isRewardExist = if ((isRewardExistStr == "true"))
144- then true
145- else false
146- let rewardAssetId = votingInfoParts[2]
147- let rewardAmount = parseIntValue(votingInfoParts[3])
148- let votingType = votingInfoParts[4]
149- let status = votingInfoParts[5]
150- let votingStartHeight = parseIntValue(votingInfoParts[6])
151- let votingEndHeight = parseIntValue(votingInfoParts[7])
152- let votesQuorum = parseIntValue(votingInfoParts[8])
153- let votesFor = parseIntValue(votingInfoParts[9])
154- let votesAgainst = parseIntValue(votingInfoParts[10])
155- $Tuple10(isRewardExist, rewardAssetId, rewardAmount, votingType, status, votingStartHeight, votingEndHeight, votesQuorum, votesFor, votesAgainst)
86+func countVotesHelper (result,voteKey) = (result + valueOrElse(getInteger(voteKey), 0))
87+
88+
89+func countVotes (prefix) = {
90+ let votes = genVotesKeys(prefix)
91+ let $l = votes
92+ let $s = size($l)
93+ let $acc0 = 0
94+ func $f0_1 ($a,$i) = if (($i >= $s))
95+ then $a
96+ else countVotesHelper($a, $l[$i])
97+
98+ func $f0_2 ($a,$i) = if (($i >= $s))
99+ then $a
100+ else throw("List size exceeds 5")
101+
102+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
156103 }
157104
158105
159-func votingExistChecks (assetId,currentIndex) = {
160- let votingInfo = valueOrErrorMessage(getString(keyVotingInfo(assetId, currentIndex)), wrapErr("voting info not found"))
161- let votingInfoArray = split(votingInfo, separator)
162- let status = votingInfoArray[5]
163- let votingEndHeight = valueOrErrorMessage(parseIntValue(votingInfoArray[7]), wrapErr("voting start height not found"))
164- let suggestIssuer = valueOrErrorMessage(getString(keySuggestIssuer(assetId, currentIndex)), wrapErr("voting issuer not found"))
165- let checks = [if ((status == "inProgress"))
166- then true
167- else throwErr("no voting in progress"), if ((votingEndHeight > height))
168- then true
169- else throwErr("voting expired")]
170- if ((checks == checks))
171- then $Tuple3(status, votingEndHeight, suggestIssuer)
172- else throw("Strict value is not equal to itself.")
106+func clearVotesHelper (result,key) = (result :+ DeleteEntry(key))
107+
108+
109+func getClearVoteEntries (prefix) = {
110+ let votes = genVotesKeys(prefix)
111+ let $l = votes
112+ let $s = size($l)
113+ let $acc0 = nil
114+ func $f0_1 ($a,$i) = if (($i >= $s))
115+ then $a
116+ else clearVotesHelper($a, $l[$i])
117+
118+ func $f0_2 ($a,$i) = if (($i >= $s))
119+ then $a
120+ else throw("List size exceeds 5")
121+
122+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
173123 }
174124
175125
176-func calculateReward (voter,assetId,index) = {
177- let voteKey = keyVote(assetId, index, voter)
178- let lastVote = valueOrErrorMessage(getString(voteKey), wrapErr("you have not voted"))
179- let lastVoteParts = split(lastVote, separator)
180- let gwxAmount = parseIntValue(lastVoteParts[2])
181- let votingInfoStr = valueOrErrorMessage(getString(keyVotingInfo(assetId, index)), wrapErr("voting info not found"))
182- let votingParts = getVotingInfoParts(votingInfoStr)
183- let votesFor = votingParts._9
184- let votesAgainst = votingParts._10
185- let partOfTheTotalVotesX8 = fraction(gwxAmount, MULT8, (votesFor + votesAgainst))
186- let totalVotingReward = valueOrElse(getInteger(keyTotalVotingReward(assetId, index)), 0)
187- let voterRewardAmount = fraction(partOfTheTotalVotesX8, totalVotingReward, MULT8, FLOOR)
188- voterRewardAmount
189- }
190-
191-
192-@Callable(i)
193-func suggestAdd (assetId,periodLength,assetImage) = {
194- let wxPayment = i.payments[0]
195- let wxPaymentAssetId = value(wxPayment.assetId)
196- let wxPaymentAmount = value(wxPayment.amount)
197- let minPeriodLength = getIntegerValue(keyMinPeriodLength)
198- let maxPeriodLength = getIntegerValue(keyMaxPeriodLength)
199- let tokenIsVerified = {
200- let @ = invoke(assetsStoreContract, "isVerifiedREADONLY", [assetId], nil)
201- if ($isInstanceOf(@, "Boolean"))
202- then @
203- else throw(($getType(@) + " couldn't be cast to Boolean"))
204- }
205- let checks = [if (if ((periodLength >= minPeriodLength))
206- then (maxPeriodLength >= periodLength)
207- else false)
208- then true
209- else throwErr("invalid periodLength"), if ((tokenIsVerified == false))
210- then true
211- else throwErr("token already verified"), if ((wxPaymentAmount > (periodLength * feePerBlock)))
212- then true
213- else throwErr("not enough wx for given period"), if ((wxPaymentAmount >= getIntegerValue(keyMinWxMinForSuggestAddAmountRequired)))
214- then true
215- else throwErr("payment less then min for suggest")]
216- if ((checks == checks))
126+func voteINTERNAL (callerAddressString,keyPrefix,minVotes,voteResult) = {
127+ let voteKey = keyFullAdminVote(keyPrefix, callerAddressString)
128+ let adminCurrentVote = getAdminVote(keyPrefix, callerAddressString)
129+ let err = if (!(isInAdminList(callerAddressString)))
130+ then throwErr((("Address: " + callerAddressString) + " not in Admin list"))
131+ else if ((adminCurrentVote == 1))
132+ then throwErr((voteKey + " you already voted"))
133+ else unit
134+ if ((err == err))
217135 then {
218- let currentIndexKey = keyCurrentIndex(assetId)
219- let currentIndex = getInteger(currentIndexKey)
220- let newIndex = if (isDefined(currentIndex))
221- then (value(currentIndex) + 1)
222- else 0
223- let $t087849424 = if ((size(i.payments) > 1))
136+ let votes = countVotes(keyPrefix)
137+ if (((votes + 1) >= minVotes))
224138 then {
225- let votingRewardPayment = i.payments[1]
226- let votingRewardPaymentAssetId = toBase58String(value(votingRewardPayment.assetId))
227- let votingRewardPaymentAmount = value(votingRewardPayment.amount)
228- $Tuple4(true, votingRewardPaymentAssetId, votingRewardPaymentAmount, [StringEntry(keyVotingRewardAssetId(assetId, newIndex), votingRewardPaymentAssetId), IntegerEntry(keyTotalVotingReward(assetId, newIndex), votingRewardPaymentAmount)])
139+ let clearVoteEntries = getClearVoteEntries(keyPrefix)
140+ (clearVoteEntries ++ voteResult)
229141 }
230- else $Tuple4(false, "EMPTY", 0, nil)
231- let isRewardExist = $t087849424._1
232- let rewardAssetId = $t087849424._2
233- let rewardAmount = $t087849424._3
234- let votingRewardActions = $t087849424._4
235- let votesQuorum = valueOrErrorMessage(getInteger(keyVotingThresholdAdd), wrapErr("votingThresholdAdd not set"))
236- let votingInfo = votingInfoValue(isRewardExist, rewardAssetId, rewardAmount, "verification", "inProgress", height, (height + periodLength), votesQuorum, 0, 0)
237- let finalizeCallRewardAmount = getIntegerValue(keyFinalizeCallRewardAmount)
238- let burnWxAmount = (wxPaymentAmount - finalizeCallRewardAmount)
239- ([IntegerEntry(currentIndexKey, newIndex), StringEntry(keySuggestIssuer(assetId, newIndex), toString(i.caller)), StringEntry(keyVotingInfo(assetId, newIndex), votingInfo), StringEntry(keyAssetImage(assetId), assetImage), Burn(wxPaymentAssetId, burnWxAmount)] ++ votingRewardActions)
142+ else [IntegerEntry(voteKey, 1)]
240143 }
241144 else throw("Strict value is not equal to itself.")
242145 }
243146
244147
148+func keyCalculatorAddress () = "%s__calculator"
149+
150+
151+func keyProxyTreasuryAddress () = "%s__proxyTreasury"
152+
153+
154+func keyChildAddress () = "%s__child"
155+
156+
157+func keyBlockProcessingReward () = "%s__blockProcessingReward"
158+
159+
160+func keyNextBlockToProcess () = "%s__nextBlockToProcess"
161+
162+
163+func keyLpAssetId () = "%s__lpAssetId"
164+
165+
166+let calculatorAddressOption = match getString(this, keyCalculatorAddress()) {
167+ case s: String =>
168+ addressFromString(s)
169+ case _: Unit =>
170+ unit
171+ case _ =>
172+ throw("Match error")
173+}
174+
175+let calculatorAddressOrFail = valueOrErrorMessage(calculatorAddressOption, wrapErr("invalid calculator address"))
176+
177+let proxyTreasuryAddressOption = match getString(this, keyProxyTreasuryAddress()) {
178+ case s: String =>
179+ addressFromString(s)
180+ case _: Unit =>
181+ unit
182+ case _ =>
183+ throw("Match error")
184+}
185+
186+let proxyTreasuryAddressOrFail = valueOrErrorMessage(proxyTreasuryAddressOption, wrapErr("invalid proxy treasury address"))
187+
188+func keyConfigAddress () = "%s__config"
189+
190+
191+func keyChildrenAddress () = "contract_children"
192+
193+
194+func keyVotingResultAddress () = "contract_voting_result"
195+
196+
197+func keyProposalAllowBroadcast (address,txId) = ((("proposal_allow_broadcast_" + toString(address)) + "_") + toBase58String(txId))
198+
199+
200+func keyInvestedByUser (childAddress,userAddress) = makeString(["investor", toString(childAddress), toString(userAddress)], "_")
201+
202+
203+let configAddressOption = match getString(this, keyConfigAddress()) {
204+ case s: String =>
205+ addressFromString(s)
206+ case _: Unit =>
207+ unit
208+ case _ =>
209+ throw("Match error")
210+}
211+
212+let configAddressOrFail = valueOrErrorMessage(configAddressOption, wrapErr("invalid config address"))
213+
214+let votingResultAddressOption = match configAddressOption {
215+ case a: Address =>
216+ match getString(a, keyVotingResultAddress()) {
217+ case s: String =>
218+ addressFromString(s)
219+ case _: Unit =>
220+ unit
221+ case _ =>
222+ throw("Match error")
223+ }
224+ case _: Unit =>
225+ unit
226+ case _ =>
227+ throw("Match error")
228+}
229+
230+let votingResultAddressOrFail = valueOrErrorMessage(votingResultAddressOption, wrapErr("invalid voting result address"))
231+
232+let childrenAddressOption = match configAddressOption {
233+ case a: Address =>
234+ match getString(a, keyChildrenAddress()) {
235+ case s: String =>
236+ addressFromString(s)
237+ case _: Unit =>
238+ unit
239+ case _ =>
240+ throw("Match error")
241+ }
242+ case _: Unit =>
243+ unit
244+ case _ =>
245+ throw("Match error")
246+}
247+
248+let childrenAddressOrFail = valueOrErrorMessage(childrenAddressOption, wrapErr("invalid children address"))
249+
250+let lpAssetIdOption = match getString(this, keyLpAssetId()) {
251+ case s: String =>
252+ fromBase58String(s)
253+ case _: Unit =>
254+ unit
255+ case _ =>
256+ throw("Match error")
257+}
258+
259+let lpAssetIdOrFail = valueOrErrorMessage(lpAssetIdOption, wrapErr("invalid lpAssetId"))
260+
261+func onlyAddress (i,address) = if ((i.caller == address))
262+ then true
263+ else throwErr("permission denied")
264+
265+
266+func onlyThis (i) = onlyAddress(i, this)
267+
268+
269+func onlyCalculator (i) = onlyAddress(i, calculatorAddressOrFail)
270+
245271
246272 @Callable(i)
247-func suggestRemove (assetId) = {
248- let gwxAmountAtNow = getUserGwxAmountAtHeight(toString(i.caller), height)
249- let minSuggestRemoveBalance = getIntegerValue(keyMinSuggestRemoveBalance)
250- let wxPayment = i.payments[0]
251- let wxPaymentAssetId = value(wxPayment.assetId)
252- let wxPaymentAmount = value(wxPayment.amount)
253- let tokenIsVerified = {
254- let @ = invoke(assetsStoreContract, "isVerifiedREADONLY", [assetId], nil)
255- if ($isInstanceOf(@, "Boolean"))
256- then @
257- else throw(($getType(@) + " couldn't be cast to Boolean"))
258- }
259- let checks = [if (tokenIsVerified)
260- then true
261- else throwErr("token not verified"), if ((gwxAmountAtNow >= minSuggestRemoveBalance))
262- then true
263- else throwErr("not enough gWXes"), if ((wxPaymentAmount >= getIntegerValue(keyWxForSuggestRemoveAmountRequired)))
264- then true
265- else throwErr("payment less then min for suggest")]
266- if ((checks == checks))
267- then {
268- let currentIndexKey = keyCurrentIndex(assetId)
269- let currentIndex = getInteger(currentIndexKey)
270- let newIndex = if (isDefined(currentIndex))
271- then (value(currentIndex) + 1)
272- else 0
273- let periodLength = valueOrErrorMessage(getInteger(keyPeriodLengthRemove), wrapErr("periodLengthRemove not set"))
274- let votingEndHeight = (height + periodLength)
275- let votesQuorum = valueOrErrorMessage(getInteger(keyVotingThresholdRemove), wrapErr("votingThresholdRemove not set"))
276- let votingInfo = votingInfoValue(false, "EMPTY", 0, "deverification", "inProgress", height, (height + periodLength), votesQuorum, 0, 0)
277-[IntegerEntry(currentIndexKey, newIndex), StringEntry(keySuggestIssuer(assetId, newIndex), toString(i.caller)), StringEntry(keyVotingInfo(assetId, newIndex), votingInfo)]
278- }
279- else throw("Strict value is not equal to itself.")
280- }
273+func stringEntry (key,val) = if (onlyCalculator(i))
274+ then $Tuple2([StringEntry(key, val)], key)
275+ else $Tuple2(nil, unit)
281276
282277
283278
284279 @Callable(i)
285-func vote (assetId,inFavor) = {
286- let currentIndexKey = keyCurrentIndex(assetId)
287- let currentIndex = valueOrErrorMessage(getInteger(currentIndexKey), wrapErr("voting does not exist"))
288- let votingInfo = votingExistChecks(assetId, currentIndex)
289- if ((votingInfo == votingInfo))
290- then {
291- let currentVotingEndHeight = votingInfo._2
292- let gwxAmountAtEnd = getUserGwxAmountAtHeight(toString(i.caller), currentVotingEndHeight)
293- let voteKey = keyVote(assetId, currentIndex, i.caller)
294- let checks = [if ((getString(voteKey) == unit))
295- then true
296- else throwErr("You have already voted"), if ((gwxAmountAtEnd > 0))
297- then true
298- else throw("You'll not have gWX at the end of voting")]
299- if ((checks == checks))
300- then {
301- let votingInfoStr = valueOrErrorMessage(getString(keyVotingInfo(assetId, currentIndex)), wrapErr("voting info not found"))
302- let votingInfoParts = getVotingInfoParts(votingInfoStr)
303- let votesFor = votingInfoParts._9
304- let votesAgainst = votingInfoParts._10
305- let $t01274512906 = if (inFavor)
306- then $Tuple2((votesFor + gwxAmountAtEnd), votesAgainst)
307- else $Tuple2(votesFor, (votesAgainst + gwxAmountAtEnd))
308- let newVotesFor = $t01274512906._1
309- let newVotesAgainst = $t01274512906._2
310- let newVotingInfoValue = votingInfoValue(votingInfoParts._1, votingInfoParts._2, votingInfoParts._3, votingInfoParts._4, votingInfoParts._5, votingInfoParts._6, votingInfoParts._7, votingInfoParts._8, newVotesFor, newVotesAgainst)
311- let votingRewardAction = match getString(keyVotingRewardAssetId(assetId, currentIndex)) {
312- case pk: String =>
313-[StringEntry(keyVotingReward(i.caller, assetId, currentIndex), voteValue(inFavor, gwxAmountAtEnd))]
314- case _: Unit =>
315- nil
316- case _ =>
317- throw("Match error")
318- }
319- ([StringEntry(voteKey, voteValue(inFavor, gwxAmountAtEnd)), StringEntry(keyVotingInfo(assetId, currentIndex), newVotingInfoValue)] ++ votingRewardAction)
320- }
321- else throw("Strict value is not equal to itself.")
322- }
323- else throw("Strict value is not equal to itself.")
324- }
280+func integerEntry (key,val) = if (onlyCalculator(i))
281+ then $Tuple2([IntegerEntry(key, val)], key)
282+ else $Tuple2(nil, unit)
325283
326284
327285
328286 @Callable(i)
329-func cancelVote (assetId) = {
330- let currentIndexKey = keyCurrentIndex(assetId)
331- let currentIndex = valueOrErrorMessage(getInteger(currentIndexKey), wrapErr("voting does not exist"))
332- let voteKey = keyVote(assetId, currentIndex, i.caller)
333- let lastVote = valueOrErrorMessage(getString(voteKey), wrapErr("you have not voted"))
334- let lastVoteParts = split(lastVote, separator)
335- let inFavor = lastVoteParts[1]
336- let gwxAmount = parseIntValue(lastVoteParts[2])
337- let votingInfo = votingExistChecks(assetId, currentIndex)
338- if ((votingInfo == votingInfo))
339- then {
340- let checks = [if (if ((inFavor == "true"))
341- then true
342- else (inFavor == "false"))
343- then true
344- else throwErr("invalid vote")]
345- if ((checks == checks))
346- then {
347- let votingInfoStr = valueOrErrorMessage(getString(keyVotingInfo(assetId, currentIndex)), wrapErr("voting info not found"))
348- let votingInfoParts = getVotingInfoParts(votingInfoStr)
349- let votesFor = votingInfoParts._9
350- let votesAgainst = votingInfoParts._10
351- let $t01453114692 = if ((inFavor == "true"))
352- then $Tuple2((votesFor - gwxAmount), votesAgainst)
353- else $Tuple2(votesFor, (votesAgainst - gwxAmount))
354- let newVotesFor = $t01453114692._1
355- let newVotesAgainst = $t01453114692._2
356- let newVotingInfoValue = votingInfoValue(votingInfoParts._1, votingInfoParts._2, votingInfoParts._3, votingInfoParts._4, votingInfoParts._5, votingInfoParts._6, votingInfoParts._7, votingInfoParts._8, newVotesFor, newVotesAgainst)
357-[StringEntry(keyVotingInfo(assetId, currentIndex), newVotingInfoValue), DeleteEntry(voteKey), DeleteEntry(keyVotingReward(i.caller, assetId, currentIndex))]
358- }
359- else throw("Strict value is not equal to itself.")
360- }
361- else throw("Strict value is not equal to itself.")
362- }
287+func booleanEntry (key,val) = if (onlyCalculator(i))
288+ then $Tuple2([BooleanEntry(key, val)], key)
289+ else $Tuple2(nil, unit)
363290
364291
365292
366293 @Callable(i)
367-func finalize (assetId) = {
368- let currentIndexKey = keyCurrentIndex(assetId)
369- let currentIndex = valueOrElse(getInteger(currentIndexKey), 0)
370- let votingThresholdAdd = valueOrErrorMessage(getInteger(keyVotingThresholdAdd), wrapErr("votingThresholdAdd not set"))
371- let votingThresholdRemove = valueOrErrorMessage(getInteger(keyVotingThresholdRemove), wrapErr("votingThresholdRemove not set"))
372- let votingInfoStr = valueOrErrorMessage(getString(keyVotingInfo(assetId, currentIndex)), wrapErr("voting info not found"))
373- let votingInfoParts = getVotingInfoParts(votingInfoStr)
374- let votingType = votingInfoParts._4
375- let status = votingInfoParts._5
376- let votingEndHeight = votingInfoParts._7
377- let votingQuorum = votingInfoParts._8
378- let votesFor = votingInfoParts._9
379- let votesAgainst = votingInfoParts._10
380- let checks = [if ((status == "inProgress"))
381- then true
382- else throwErr("voting not in progress"), if ((height >= votingEndHeight))
383- then true
384- else throwErr("voting not finished"), if (isDefined(getString(keyAssetImage(assetId))))
385- then true
386- else throwErr("asset image not set")]
387- if ((checks == checks))
388- then {
389- let votingAccepted = if (if (((votesFor + votesAgainst) >= votingQuorum))
390- then (votesFor > votesAgainst)
391- else false)
392- then true
393- else false
394- let newStatus = if (votingAccepted)
395- then "accepted"
396- else "rejected"
397- let assetImage = getStringValue(keyAssetImage(assetId))
398- let isVotingAccepted = if (votingAccepted)
399- then {
400- let votingAcceptedInvokes = if ((votingType == "verification"))
401- then invoke(assetsStoreContract, "createOrUpdate", [assetId, assetImage, true], nil)
402- else invoke(assetsStoreContract, "setVerified", [assetId, false], nil)
403- votingAcceptedInvokes
404- }
405- else nil
406- if ((isVotingAccepted == isVotingAccepted))
407- then {
408- let newVotingInfoValue = votingInfoValue(votingInfoParts._1, votingInfoParts._2, votingInfoParts._3, votingInfoParts._4, newStatus, votingInfoParts._6, votingInfoParts._7, votingInfoParts._8, votingInfoParts._9, votingInfoParts._10)
409- let finalizeCallRewardAmount = getIntegerValue(keyFinalizeCallRewardAmount)
410-[StringEntry(keyVotingInfo(assetId, currentIndex), newVotingInfoValue), ScriptTransfer(i.caller, finalizeCallRewardAmount, wxAssetId)]
411- }
412- else throw("Strict value is not equal to itself.")
413- }
414- else throw("Strict value is not equal to itself.")
415- }
294+func binaryEntry (key,val) = if (onlyCalculator(i))
295+ then $Tuple2([BinaryEntry(key, val)], key)
296+ else $Tuple2(nil, unit)
416297
417298
418299
419300 @Callable(i)
420-func claimREADONLY (assetId,index,userAddressStr) = {
421- let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), wrapErr("invalid address"))
422- let votingRewardAssetIdStr = getString(keyVotingRewardAssetId(assetId, index))
423- let rewardAmount = if (isDefined(votingRewardAssetIdStr))
424- then calculateReward(userAddress, assetId, index)
425- else 0
426- $Tuple2(nil, rewardAmount)
427- }
301+func deleteEntry (key) = if (onlyCalculator(i))
302+ then $Tuple2([DeleteEntry(key)], key)
303+ else $Tuple2(nil, unit)
428304
429305
430306
431307 @Callable(i)
432-func claim (assetId,index) = {
433- let callerAddress = i.caller
434- let claimHistoryKey = keyClaimHistory(callerAddress, assetId, index)
435- let claimHistory = getInteger(claimHistoryKey)
436- let checks = [if ((claimHistory == unit))
308+func reissue (amount) = if (onlyCalculator(i))
309+ then $Tuple2([Reissue(lpAssetIdOrFail, amount, true)], amount)
310+ else $Tuple2(nil, unit)
311+
312+
313+
314+@Callable(i)
315+func burn (amount) = if (onlyCalculator(i))
316+ then $Tuple2([Burn(lpAssetIdOrFail, amount)], amount)
317+ else $Tuple2(nil, unit)
318+
319+
320+
321+@Callable(i)
322+func transferAsset (recepientBytes,amount,assetId) = if (onlyCalculator(i))
323+ then $Tuple2([ScriptTransfer(Address(recepientBytes), amount, assetId)], amount)
324+ else $Tuple2(nil, unit)
325+
326+
327+
328+@Callable(i)
329+func transferAssets (recepientBytes,assetsList,amountsList) = if (onlyCalculator(i))
330+ then {
331+ func addNewTransfer (accum,nextAssetId) = {
332+ let $t074577483 = accum
333+ let transfers = $t074577483._1
334+ let j = $t074577483._2
335+ let newTransfer = ScriptTransfer(Address(recepientBytes), parseIntValue(amountsList[j]), stringToAssetId(assetsList[j]))
336+ let updatedTransfers = (transfers :+ newTransfer)
337+ $Tuple2(updatedTransfers, (j + 1))
338+ }
339+
340+ let $t077437824 = {
341+ let $l = assetsList
342+ let $s = size($l)
343+ let $acc0 = $Tuple2(nil, 0)
344+ func $f0_1 ($a,$i) = if (($i >= $s))
345+ then $a
346+ else addNewTransfer($a, $l[$i])
347+
348+ func $f0_2 ($a,$i) = if (($i >= $s))
349+ then $a
350+ else throw("List size exceeds 10")
351+
352+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
353+ }
354+ let assetsTransfers = $t077437824._1
355+ let _lastIndex = $t077437824._2
356+ $Tuple2(assetsTransfers, unit)
357+ }
358+ else $Tuple2(nil, unit)
359+
360+
361+
362+@Callable(i)
363+func transferWaves (recepientBytes,amount) = if (onlyCalculator(i))
364+ then $Tuple2([ScriptTransfer(Address(recepientBytes), amount, unit)], amount)
365+ else $Tuple2(nil, unit)
366+
367+
368+
369+@Callable(i)
370+func transferFromProxyTreasury (recipientBytes,rewardsAmount) = if (onlyCalculator(i))
371+ then $Tuple2(nil, invoke(proxyTreasuryAddressOrFail, "transferWaves", [recipientBytes, rewardsAmount], nil))
372+ else $Tuple2(nil, unit)
373+
374+
375+
376+@Callable(i)
377+func finalize (newTreasuryVolumeInWaves,pwrManagersBonusInWaves,treasuryVolumeDiffAllocationCoef) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "finalize", [i.caller.bytes, newTreasuryVolumeInWaves, pwrManagersBonusInWaves, treasuryVolumeDiffAllocationCoef], i.payments))
378+
379+
380+
381+@Callable(i)
382+func finalizeREADONLY (newTreasuryVolumeInWaves,pwrManagersBonusInWaves,treasuryVolumeDiffAllocationCoef) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "finalizeREADONLY", [newTreasuryVolumeInWaves, pwrManagersBonusInWaves, treasuryVolumeDiffAllocationCoef], nil))
383+
384+
385+
386+@Callable(i)
387+func claimLP () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "claimLP", [i.caller.bytes], i.payments))
388+
389+
390+
391+@Callable(i)
392+func claimCollateral (txIdStr) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "claimCollateral", [i.caller.bytes, fromBase58String(txIdStr)], i.payments))
393+
394+
395+
396+@Callable(i)
397+func invest () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "invest", [i.caller.bytes], i.payments))
398+
399+
400+
401+@Callable(i)
402+func withdraw () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "withdraw", [i.caller.bytes], i.payments))
403+
404+
405+
406+@Callable(i)
407+func cancelWithdraw (txIdStr) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "cancelWithdraw", [i.caller.bytes, fromBase58String(txIdStr)], i.payments))
408+
409+
410+
411+@Callable(i)
412+func processBlocks () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "processBlocks", [i.caller.bytes], i.payments))
413+
414+
415+
416+@Callable(i)
417+func voteForTxId (txId) = {
418+ let callerAddressString = toBase58String(i.caller.bytes)
419+ let keyPrefix = keyAllowedTxIdVotePrefix(txId)
420+ let result = [StringEntry(keyAllowedTxId(), txId)]
421+ let allowedTxIdOption = getString(this, keyAllowedTxId())
422+ let err = [if ((size(fromBase58String(txId)) == TXID_BYTES_LENGTH))
437423 then true
438- else throwErr("already claimed")]
439- if ((checks == checks))
440- then {
441- let rewardAmount = if ((calculateReward(callerAddress, assetId, index) > 0))
442- then calculateReward(callerAddress, assetId, index)
443- else throwErr("nothing to claim")
444- let votingRewardAssetIdStr = getString(keyVotingRewardAssetId(assetId, index))
445- let rewardAction = if (isDefined(votingRewardAssetIdStr))
446- then {
447- let votingRewardAssetId = fromBase58String(value(votingRewardAssetIdStr))
448-[ScriptTransfer(callerAddress, rewardAmount, votingRewardAssetId), IntegerEntry(claimHistoryKey, rewardAmount), DeleteEntry(keyVotingReward(callerAddress, assetId, index))]
449- }
450- else throwErr("nothing to claim")
451- rewardAction
452- }
424+ else throwErr((txId + " is not valid txId")), if (if ((allowedTxIdOption == unit))
425+ then true
426+ else (value(allowedTxIdOption) != txId))
427+ then true
428+ else throwErr((txId + " is already allowed"))]
429+ if ((err == err))
430+ then voteINTERNAL(callerAddressString, keyPrefix, QUORUM, result)
453431 else throw("Strict value is not equal to itself.")
454432 }
455433
456434
457435 @Verifier(tx)
458436 func verify () = {
459- let targetPublicKey = match managerPublicKeyOrUnit() {
460- case pk: ByteVector =>
461- pk
462- case _: Unit =>
463- tx.senderPublicKey
437+ let byProposal = match votingResultAddressOption {
438+ case proposalAddress: Address =>
439+ valueOrElse(getBoolean(proposalAddress, keyProposalAllowBroadcast(this, tx.id)), false)
464440 case _ =>
465- throw("Match error")
441+ false
466442 }
467- sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
443+ let byAdmins = (tx.id == fromBase58String(valueOrElse(getString(this, keyAllowedTxId()), "")))
444+ let byOwner = if ((size(getAdminsList()) >= QUORUM))
445+ then false
446+ else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
447+ if (if (byProposal)
448+ then true
449+ else byAdmins)
450+ then true
451+ else byOwner
468452 }
469453

github/deemru/w8io/3ef1775 
86.91 ms