tx · 5DuSwdMY1kQs56ZuCHXcsognf8kVwEM9GgLj1uWvg7TR

3N9wLKKtDBphos7U3xzsPqgvJJ5zPQEU6pV:  -0.01300000 Waves

2023.07.05 10:13 [2652303] smart account 3N9wLKKtDBphos7U3xzsPqgvJJ5zPQEU6pV > SELF 0.00000000 Waves

{ "type": 13, "id": "5DuSwdMY1kQs56ZuCHXcsognf8kVwEM9GgLj1uWvg7TR", "fee": 1300000, "feeAssetId": null, "timestamp": 1688541222239, "version": 1, "sender": "3N9wLKKtDBphos7U3xzsPqgvJJ5zPQEU6pV", "senderPublicKey": "GKX7DbVJVEtTB6ak3PXWHNPUhC3jym3ozbtZ7a36rGu6", "proofs": [ "4qSmW2U5qA3rtSjRCG4Qqnemrc6yES5eAj1jjkUQeDQseUuG541x3A4WiRwP93LC4htvtyRuNjiYvcT413QPhJvf" ], "script": "base64:BwJaCAISBAoCCAgSBAoCCAESBAoCCAQSBAoCCAISAwoBCBIDCgEBEgMKAQESBQoDAgECEgQKAgIBEgQKAgIBEgUKAwEBARIAEgMKAQgSABIAEgMKAQgSABIDCgEILwADU0VQAgJfXwAQY29udHJhY3RGaWxlbmFtZQIMZmFjdG9yeS5yaWRlAQd3cmFwRXJyAQFzCQCsAgIJAKwCAgUQY29udHJhY3RGaWxlbmFtZQICOiAFAXMBCHRocm93RXJyAQFzCQACAQkBB3dyYXBFcnIBBQFzAA9BRE1JTl9MSVNUX1NJWkUABQAGUVVPUlVNAAMAEVRYSURfQllURVNfTEVOR1RIACABGGtleUFsbG93ZWRUeElkVm90ZVByZWZpeAEEdHhJZAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCAglhbGxvd1R4SWQJAMwIAgUEdHhJZAUDbmlsBQNTRVABEGtleUZ1bGxBZG1pblZvdGUCBnByZWZpeAxhZG1pbkFkZHJlc3MJALkJAgkAzAgCBQZwcmVmaXgJAMwIAgUMYWRtaW5BZGRyZXNzBQNuaWwFA1NFUAETa2V5QWRtaW5BZGRyZXNzTGlzdAAJALkJAgkAzAgCAgIlcwkAzAgCAhBhZG1pbkFkZHJlc3NMaXN0BQNuaWwFA1NFUAEOa2V5QWxsb3dlZFR4SWQACQC5CQIJAMwIAgICJXMJAMwIAgIEdHhJZAUDbmlsBQNTRVABDGdldEFkbWluVm90ZQIGcHJlZml4BWFkbWluBAd2b3RlS2V5CQEQa2V5RnVsbEFkbWluVm90ZQIFBnByZWZpeAUFYWRtaW4JAQt2YWx1ZU9yRWxzZQIJAJ8IAQUHdm90ZUtleQAAAQ1nZXRBZG1pbnNMaXN0AAQHJG1hdGNoMAkAnQgCBQR0aGlzCQETa2V5QWRtaW5BZGRyZXNzTGlzdAADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQC1CQIFAXMFA1NFUAUDbmlsAQ1pc0luQWRtaW5MaXN0AQdhZGRyZXNzCQEPY29udGFpbnNFbGVtZW50AgkBDWdldEFkbWluc0xpc3QABQdhZGRyZXNzARJnZW5Wb3Rlc0tleXNIZWxwZXICAWEMYWRtaW5BZGRyZXNzBAskdDAxMjYyMTI4NgUBYQQGcmVzdWx0CAULJHQwMTI2MjEyODYCXzEEBnByZWZpeAgFCyR0MDEyNjIxMjg2Al8yCQCUCgIJAM0IAgUGcmVzdWx0CQEQa2V5RnVsbEFkbWluVm90ZQIFBnByZWZpeAUMYWRtaW5BZGRyZXNzBQZwcmVmaXgBDGdlblZvdGVzS2V5cwEJa2V5UHJlZml4BAlhZG1pbkxpc3QJARNrZXlBZG1pbkFkZHJlc3NMaXN0AAQLJHQwMTQzMzE1MTcKAAIkbAkBDWdldEFkbWluc0xpc3QACgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwFCWtleVByZWZpeAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQESZ2VuVm90ZXNLZXlzSGVscGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQQGcmVzdWx0CAULJHQwMTQzMzE1MTcCXzEEBnByZWZpeAgFCyR0MDE0MzMxNTE3Al8yBQZyZXN1bHQBEGNvdW50Vm90ZXNIZWxwZXICBnJlc3VsdAd2b3RlS2V5CQBkAgUGcmVzdWx0CQELdmFsdWVPckVsc2UCCQCfCAEFB3ZvdGVLZXkAAAEKY291bnRWb3RlcwEGcHJlZml4BAV2b3RlcwkBDGdlblZvdGVzS2V5cwEFBnByZWZpeAoAAiRsBQV2b3RlcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQY291bnRWb3Rlc0hlbHBlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUBEGNsZWFyVm90ZXNIZWxwZXICBnJlc3VsdANrZXkJAM0IAgUGcmVzdWx0CQELRGVsZXRlRW50cnkBBQNrZXkBE2dldENsZWFyVm90ZUVudHJpZXMBBnByZWZpeAQFdm90ZXMJAQxnZW5Wb3Rlc0tleXMBBQZwcmVmaXgKAAIkbAUFdm90ZXMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEGNsZWFyVm90ZXNIZWxwZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAQx2b3RlSU5URVJOQUwEE2NhbGxlckFkZHJlc3NTdHJpbmcJa2V5UHJlZml4CG1pblZvdGVzCnZvdGVSZXN1bHQEB3ZvdGVLZXkJARBrZXlGdWxsQWRtaW5Wb3RlAgUJa2V5UHJlZml4BRNjYWxsZXJBZGRyZXNzU3RyaW5nBBBhZG1pbkN1cnJlbnRWb3RlCQEMZ2V0QWRtaW5Wb3RlAgUJa2V5UHJlZml4BRNjYWxsZXJBZGRyZXNzU3RyaW5nBANlcnIDCQEBIQEJAQ1pc0luQWRtaW5MaXN0AQUTY2FsbGVyQWRkcmVzc1N0cmluZwkBCHRocm93RXJyAQkArAICCQCsAgICCUFkZHJlc3M6IAUTY2FsbGVyQWRkcmVzc1N0cmluZwISIG5vdCBpbiBBZG1pbiBsaXN0AwkAAAIFEGFkbWluQ3VycmVudFZvdGUAAQkBCHRocm93RXJyAQkArAICBQd2b3RlS2V5AhIgeW91IGFscmVhZHkgdm90ZWQFBHVuaXQDCQAAAgUDZXJyBQNlcnIEBXZvdGVzCQEKY291bnRWb3RlcwEFCWtleVByZWZpeAMJAGcCCQBkAgUFdm90ZXMAAQUIbWluVm90ZXMEEGNsZWFyVm90ZUVudHJpZXMJARNnZXRDbGVhclZvdGVFbnRyaWVzAQUJa2V5UHJlZml4CQDOCAIFEGNsZWFyVm90ZUVudHJpZXMFCnZvdGVSZXN1bHQJAMwIAgkBDEludGVnZXJFbnRyeQIFB3ZvdGVLZXkAAQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARRrZXlDYWxjdWxhdG9yQWRkcmVzcwACDiVzX19jYWxjdWxhdG9yARdrZXlQcm94eVRyZWFzdXJ5QWRkcmVzcwACESVzX19wcm94eVRyZWFzdXJ5AQ9rZXlDaGlsZEFkZHJlc3MAAgklc19fY2hpbGQBGGtleUJsb2NrUHJvY2Vzc2luZ1Jld2FyZAACGSVzX19ibG9ja1Byb2Nlc3NpbmdSZXdhcmQBFWtleU5leHRCbG9ja1RvUHJvY2VzcwACFiVzX19uZXh0QmxvY2tUb1Byb2Nlc3MBDGtleUxwQXNzZXRJZAACDSVzX19scEFzc2V0SWQAF2NhbGN1bGF0b3JBZGRyZXNzT3B0aW9uBAckbWF0Y2gwCQCdCAIFBHRoaXMJARRrZXlDYWxjdWxhdG9yQWRkcmVzcwADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQCmCAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yABdjYWxjdWxhdG9yQWRkcmVzc09yRmFpbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBRdjYWxjdWxhdG9yQWRkcmVzc09wdGlvbgkBB3dyYXBFcnIBAhppbnZhbGlkIGNhbGN1bGF0b3IgYWRkcmVzcwAacHJveHlUcmVhc3VyeUFkZHJlc3NPcHRpb24EByRtYXRjaDAJAJ0IAgUEdGhpcwkBF2tleVByb3h5VHJlYXN1cnlBZGRyZXNzAAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJAKYIAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IAGnByb3h5VHJlYXN1cnlBZGRyZXNzT3JGYWlsCQETdmFsdWVPckVycm9yTWVzc2FnZQIFGnByb3h5VHJlYXN1cnlBZGRyZXNzT3B0aW9uCQEHd3JhcEVycgECHmludmFsaWQgcHJveHkgdHJlYXN1cnkgYWRkcmVzcwEQa2V5Q29uZmlnQWRkcmVzcwACCiVzX19jb25maWcBEmtleUNoaWxkcmVuQWRkcmVzcwACEWNvbnRyYWN0X2NoaWxkcmVuARZrZXlWb3RpbmdSZXN1bHRBZGRyZXNzAAIWY29udHJhY3Rfdm90aW5nX3Jlc3VsdAEZa2V5UHJvcG9zYWxBbGxvd0Jyb2FkY2FzdAIHYWRkcmVzcwR0eElkCQCsAgIJAKwCAgkArAICAhlwcm9wb3NhbF9hbGxvd19icm9hZGNhc3RfCQClCAEFB2FkZHJlc3MCAV8JANgEAQUEdHhJZAERa2V5SW52ZXN0ZWRCeVVzZXICDGNoaWxkQWRkcmVzcwt1c2VyQWRkcmVzcwkAuQkCCQDMCAICCGludmVzdG9yCQDMCAIJAKUIAQUMY2hpbGRBZGRyZXNzCQDMCAIJAKUIAQULdXNlckFkZHJlc3MFA25pbAIBXwATY29uZmlnQWRkcmVzc09wdGlvbgQHJG1hdGNoMAkAnQgCBQR0aGlzCQEQa2V5Q29uZmlnQWRkcmVzcwADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQCmCAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yABNjb25maWdBZGRyZXNzT3JGYWlsCQETdmFsdWVPckVycm9yTWVzc2FnZQIFE2NvbmZpZ0FkZHJlc3NPcHRpb24JAQd3cmFwRXJyAQIWaW52YWxpZCBjb25maWcgYWRkcmVzcwAZdm90aW5nUmVzdWx0QWRkcmVzc09wdGlvbgQHJG1hdGNoMAUTY29uZmlnQWRkcmVzc09wdGlvbgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAFhBQckbWF0Y2gwBAckbWF0Y2gxCQCdCAIFAWEJARZrZXlWb3RpbmdSZXN1bHRBZGRyZXNzAAMJAAECBQckbWF0Y2gxAgZTdHJpbmcEAXMFByRtYXRjaDEJAKYIAQUBcwMJAAECBQckbWF0Y2gxAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yABl2b3RpbmdSZXN1bHRBZGRyZXNzT3JGYWlsCQETdmFsdWVPckVycm9yTWVzc2FnZQIFGXZvdGluZ1Jlc3VsdEFkZHJlc3NPcHRpb24JAQd3cmFwRXJyAQIdaW52YWxpZCB2b3RpbmcgcmVzdWx0IGFkZHJlc3MAFWNoaWxkcmVuQWRkcmVzc09wdGlvbgQHJG1hdGNoMAUTY29uZmlnQWRkcmVzc09wdGlvbgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAFhBQckbWF0Y2gwBAckbWF0Y2gxCQCdCAIFAWEJARJrZXlDaGlsZHJlbkFkZHJlc3MAAwkAAQIFByRtYXRjaDECBlN0cmluZwQBcwUHJG1hdGNoMQkApggBBQFzAwkAAQIFByRtYXRjaDECBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IAFWNoaWxkcmVuQWRkcmVzc09yRmFpbAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBRVjaGlsZHJlbkFkZHJlc3NPcHRpb24JAQd3cmFwRXJyAQIYaW52YWxpZCBjaGlsZHJlbiBhZGRyZXNzAA9scEFzc2V0SWRPcHRpb24EByRtYXRjaDAJAJ0IAgUEdGhpcwkBDGtleUxwQXNzZXRJZAADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQDZBAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAA9scEFzc2V0SWRPckZhaWwJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgUPbHBBc3NldElkT3B0aW9uCQEHd3JhcEVycgECEWludmFsaWQgbHBBc3NldElkAQtvbmx5QWRkcmVzcwIBaQdhZGRyZXNzAwkAAAIIBQFpBmNhbGxlcgUHYWRkcmVzcwYJAQh0aHJvd0VycgECEXBlcm1pc3Npb24gZGVuaWVkAQhvbmx5VGhpcwEBaQkBC29ubHlBZGRyZXNzAgUBaQUEdGhpcwEOb25seUNhbGN1bGF0b3IBAWkJAQtvbmx5QWRkcmVzcwIFAWkFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsEgFpAQtzdHJpbmdFbnRyeQIDa2V5A3ZhbAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQNrZXkFA3ZhbAUDbmlsBQNrZXkJAJQKAgUDbmlsBQR1bml0AWkBDGludGVnZXJFbnRyeQIDa2V5A3ZhbAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUDa2V5BQN2YWwFA25pbAUDa2V5CQCUCgIFA25pbAUEdW5pdAFpAQxib29sZWFuRW50cnkCA2tleQN2YWwDCQEOb25seUNhbGN1bGF0b3IBBQFpCQCUCgIJAMwIAgkBDEJvb2xlYW5FbnRyeQIFA2tleQUDdmFsBQNuaWwFA2tleQkAlAoCBQNuaWwFBHVuaXQBaQELYmluYXJ5RW50cnkCA2tleQN2YWwDCQEOb25seUNhbGN1bGF0b3IBBQFpCQCUCgIJAMwIAgkBC0JpbmFyeUVudHJ5AgUDa2V5BQN2YWwFA25pbAUDa2V5CQCUCgIFA25pbAUEdW5pdAFpAQtkZWxldGVFbnRyeQEDa2V5AwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCCQDMCAIJAQtEZWxldGVFbnRyeQEFA2tleQUDbmlsBQNrZXkJAJQKAgUDbmlsBQR1bml0AWkBB3JlaXNzdWUBBmFtb3VudAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQEHUmVpc3N1ZQMFD2xwQXNzZXRJZE9yRmFpbAUGYW1vdW50BgUDbmlsBQZhbW91bnQJAJQKAgUDbmlsBQR1bml0AWkBBGJ1cm4BBmFtb3VudAMJAQ5vbmx5Q2FsY3VsYXRvcgEFAWkJAJQKAgkAzAgCCQEEQnVybgIFD2xwQXNzZXRJZE9yRmFpbAUGYW1vdW50BQNuaWwFBmFtb3VudAkAlAoCBQNuaWwFBHVuaXQBaQENdHJhbnNmZXJBc3NldAMOcmVjZXBpZW50Qnl0ZXMGYW1vdW50B2Fzc2V0SWQDCQEOb25seUNhbGN1bGF0b3IBBQFpCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBB0FkZHJlc3MBBQ5yZWNlcGllbnRCeXRlcwUGYW1vdW50BQdhc3NldElkBQNuaWwFBmFtb3VudAkAlAoCBQNuaWwFBHVuaXQBaQENdHJhbnNmZXJXYXZlcwIOcmVjZXBpZW50Qnl0ZXMGYW1vdW50AwkBDm9ubHlDYWxjdWxhdG9yAQUBaQkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQUOcmVjZXBpZW50Qnl0ZXMFBmFtb3VudAUEdW5pdAUDbmlsBQZhbW91bnQJAJQKAgUDbmlsBQR1bml0AWkBGXRyYW5zZmVyRnJvbVByb3h5VHJlYXN1cnkCDnJlY2lwaWVudEJ5dGVzDXJld2FyZHNBbW91bnQDCQEOb25seUNhbGN1bGF0b3IBBQFpCQCUCgIFA25pbAkA/AcEBRpwcm94eVRyZWFzdXJ5QWRkcmVzc09yRmFpbAINdHJhbnNmZXJXYXZlcwkAzAgCBQ5yZWNpcGllbnRCeXRlcwkAzAgCBQ1yZXdhcmRzQW1vdW50BQNuaWwFA25pbAkAlAoCBQNuaWwFBHVuaXQBaQEIZmluYWxpemUDGG5ld1RyZWFzdXJ5Vm9sdW1lSW5XYXZlcxdwd3JNYW5hZ2Vyc0JvbnVzSW5XYXZlcyB0cmVhc3VyeVZvbHVtZURpZmZBbGxvY2F0aW9uQ29lZgkAlAoCBQNuaWwJAP0HBAUXY2FsY3VsYXRvckFkZHJlc3NPckZhaWwCCGZpbmFsaXplCQDMCAIICAUBaQZjYWxsZXIFYnl0ZXMJAMwIAgUYbmV3VHJlYXN1cnlWb2x1bWVJbldhdmVzCQDMCAIFF3B3ck1hbmFnZXJzQm9udXNJbldhdmVzCQDMCAIFIHRyZWFzdXJ5Vm9sdW1lRGlmZkFsbG9jYXRpb25Db2VmBQNuaWwIBQFpCHBheW1lbnRzAWkBB2NsYWltTFAACQCUCgIFA25pbAkA/QcEBRdjYWxjdWxhdG9yQWRkcmVzc09yRmFpbAIHY2xhaW1MUAkAzAgCCAgFAWkGY2FsbGVyBWJ5dGVzBQNuaWwIBQFpCHBheW1lbnRzAWkBCmNsYWltV2F2ZXMBB3R4SWRTdHIJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAgpjbGFpbVdhdmVzCQDMCAIICAUBaQZjYWxsZXIFYnl0ZXMJAMwIAgkA2QQBBQd0eElkU3RyBQNuaWwIBQFpCHBheW1lbnRzAWkBBmludmVzdAAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAgZpbnZlc3QJAMwIAggIBQFpBmNhbGxlcgVieXRlcwUDbmlsCAUBaQhwYXltZW50cwFpAQh3aXRoZHJhdwAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAgh3aXRoZHJhdwkAzAgCCAgFAWkGY2FsbGVyBWJ5dGVzBQNuaWwIBQFpCHBheW1lbnRzAWkBDmNhbmNlbFdpdGhkcmF3AQd0eElkU3RyCQCUCgIFA25pbAkA/QcEBRdjYWxjdWxhdG9yQWRkcmVzc09yRmFpbAIOY2FuY2VsV2l0aGRyYXcJAMwIAggIBQFpBmNhbGxlcgVieXRlcwkAzAgCCQDZBAEFB3R4SWRTdHIFA25pbAgFAWkIcGF5bWVudHMBaQENcHJvY2Vzc0Jsb2NrcwAJAJQKAgUDbmlsCQD9BwQFF2NhbGN1bGF0b3JBZGRyZXNzT3JGYWlsAg1wcm9jZXNzQmxvY2tzCQDMCAIICAUBaQZjYWxsZXIFYnl0ZXMFA25pbAgFAWkIcGF5bWVudHMBaQELdm90ZUZvclR4SWQBBHR4SWQEE2NhbGxlckFkZHJlc3NTdHJpbmcJANgEAQgIBQFpBmNhbGxlcgVieXRlcwQJa2V5UHJlZml4CQEYa2V5QWxsb3dlZFR4SWRWb3RlUHJlZml4AQUEdHhJZAQGcmVzdWx0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlBbGxvd2VkVHhJZAAFBHR4SWQFA25pbAQRYWxsb3dlZFR4SWRPcHRpb24JAJ0IAgUEdGhpcwkBDmtleUFsbG93ZWRUeElkAAQDZXJyCQDMCAIDCQAAAgkAyAEBCQDZBAEFBHR4SWQFEVRYSURfQllURVNfTEVOR1RIBgkBCHRocm93RXJyAQkArAICBQR0eElkAhIgaXMgbm90IHZhbGlkIHR4SWQJAMwIAgMDCQAAAgURYWxsb3dlZFR4SWRPcHRpb24FBHVuaXQGCQECIT0CCQEFdmFsdWUBBRFhbGxvd2VkVHhJZE9wdGlvbgUEdHhJZAYJAQh0aHJvd0VycgEJAKwCAgUEdHhJZAITIGlzIGFscmVhZHkgYWxsb3dlZAUDbmlsAwkAAAIFA2VycgUDZXJyCQEMdm90ZUlOVEVSTkFMBAUTY2FsbGVyQWRkcmVzc1N0cmluZwUJa2V5UHJlZml4BQZRVU9SVU0FBnJlc3VsdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAECmJ5UHJvcG9zYWwEByRtYXRjaDAFGXZvdGluZ1Jlc3VsdEFkZHJlc3NPcHRpb24DCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQPcHJvcG9zYWxBZGRyZXNzBQckbWF0Y2gwCQELdmFsdWVPckVsc2UCCQCbCAIFD3Byb3Bvc2FsQWRkcmVzcwkBGWtleVByb3Bvc2FsQWxsb3dCcm9hZGNhc3QCBQR0aGlzCAUCdHgCaWQHBwQIYnlBZG1pbnMJAAACCAUCdHgCaWQJANkEAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQEOa2V5QWxsb3dlZFR4SWQAAgAEB2J5T3duZXIDCQBnAgkAkAMBCQENZ2V0QWRtaW5zTGlzdAAFBlFVT1JVTQcJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXkDAwUKYnlQcm9wb3NhbAYFCGJ5QWRtaW5zBgUHYnlPd25lcsGySmY=", "chainId": 84, "height": 2652303, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3J844DxTN85g5x4pS4GGiLe9GDJxn2MXCNpPs45BeoMq Next: B2K7kQfptcWhnEpbWULCVwZbwkveix5Pb3yeVoQyCgc2 Diff:
OldNewDifferences
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
55
6-let CONTRACT_NAME = "calculator.ride"
6+let contractFilename = "factory.ride"
77
8-let SCALE8 = 100000000
9-
10-let PENDING = "PENDING"
11-
12-let FINISHED = "FINISHED"
13-
14-let WAVES = "WAVES"
15-
16-func wrapErr (s) = ((CONTRACT_NAME + ": ") + s)
8+func wrapErr (s) = ((contractFilename + ": ") + s)
179
1810
1911 func throwErr (s) = throw(wrapErr(s))
2012
2113
22-func assetIdToString (assetId) = match assetId {
23- case b: ByteVector =>
24- toBase58String(b)
25- case _: Unit =>
26- WAVES
14+let ADMIN_LIST_SIZE = 5
15+
16+let QUORUM = 3
17+
18+let TXID_BYTES_LENGTH = 32
19+
20+func keyAllowedTxIdVotePrefix (txId) = makeString(["%s%s%s", "allowTxId", txId], SEP)
21+
22+
23+func keyFullAdminVote (prefix,adminAddress) = makeString([prefix, adminAddress], SEP)
24+
25+
26+func keyAdminAddressList () = makeString(["%s", "adminAddressList"], SEP)
27+
28+
29+func keyAllowedTxId () = makeString(["%s", "txId"], SEP)
30+
31+
32+func getAdminVote (prefix,admin) = {
33+ let voteKey = keyFullAdminVote(prefix, admin)
34+ valueOrElse(getInteger(voteKey), 0)
35+ }
36+
37+
38+func getAdminsList () = match getString(this, keyAdminAddressList()) {
39+ case s: String =>
40+ split(s, SEP)
2741 case _ =>
28- throw("Match error")
42+ nil
2943 }
3044
3145
32-func abs (n) = if ((0 > n))
33- then -(n)
34- else n
46+func isInAdminList (address) = containsElement(getAdminsList(), address)
3547
3648
37-func keyFactoryAddress () = makeString(["%s", "factory"], SEP)
49+func genVotesKeysHelper (a,adminAddress) = {
50+ let $t012621286 = a
51+ let result = $t012621286._1
52+ let prefix = $t012621286._2
53+ $Tuple2((result :+ keyFullAdminVote(prefix, adminAddress)), prefix)
54+ }
3855
3956
40-func keyManagerPublicKey () = makeString(["%s", "managerPublicKey"], SEP)
57+func genVotesKeys (keyPrefix) = {
58+ let adminList = keyAdminAddressList()
59+ let $t014331517 = {
60+ let $l = getAdminsList()
61+ let $s = size($l)
62+ let $acc0 = $Tuple2(nil, keyPrefix)
63+ func $f0_1 ($a,$i) = if (($i >= $s))
64+ then $a
65+ else genVotesKeysHelper($a, $l[$i])
66+
67+ func $f0_2 ($a,$i) = if (($i >= $s))
68+ then $a
69+ else throw("List size exceeds 5")
70+
71+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
72+ }
73+ let result = $t014331517._1
74+ let prefix = $t014331517._2
75+ result
76+ }
4177
4278
43-func keyLpAssetId () = makeString(["%s", "lpAssetId"], SEP)
79+func countVotesHelper (result,voteKey) = (result + valueOrElse(getInteger(voteKey), 0))
4480
4581
46-func keyProxyTreasuryAddress () = makeString(["%s", "proxyTreasury"], SEP)
82+func countVotes (prefix) = {
83+ let votes = genVotesKeys(prefix)
84+ let $l = votes
85+ let $s = size($l)
86+ let $acc0 = 0
87+ func $f0_1 ($a,$i) = if (($i >= $s))
88+ then $a
89+ else countVotesHelper($a, $l[$i])
90+
91+ func $f0_2 ($a,$i) = if (($i >= $s))
92+ then $a
93+ else throw("List size exceeds 5")
94+
95+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
96+ }
4797
4898
49-func keyMainTreasuryAddress () = makeString(["%s", "mainTreasury"], SEP)
99+func clearVotesHelper (result,key) = (result :+ DeleteEntry(key))
50100
51101
52-func keyInvested (assetId) = makeString(["%s%s", "invested", assetIdToString(assetId)], SEP)
102+func getClearVoteEntries (prefix) = {
103+ let votes = genVotesKeys(prefix)
104+ let $l = votes
105+ let $s = size($l)
106+ let $acc0 = nil
107+ func $f0_1 ($a,$i) = if (($i >= $s))
108+ then $a
109+ else clearVotesHelper($a, $l[$i])
110+
111+ func $f0_2 ($a,$i) = if (($i >= $s))
112+ then $a
113+ else throw("List size exceeds 5")
114+
115+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
116+ }
53117
54118
55-func keyDonated (assetId) = makeString(["%s%s", "donated", assetIdToString(assetId)], SEP)
119+func voteINTERNAL (callerAddressString,keyPrefix,minVotes,voteResult) = {
120+ let voteKey = keyFullAdminVote(keyPrefix, callerAddressString)
121+ let adminCurrentVote = getAdminVote(keyPrefix, callerAddressString)
122+ let err = if (!(isInAdminList(callerAddressString)))
123+ then throwErr((("Address: " + callerAddressString) + " not in Admin list"))
124+ else if ((adminCurrentVote == 1))
125+ then throwErr((voteKey + " you already voted"))
126+ else unit
127+ if ((err == err))
128+ then {
129+ let votes = countVotes(keyPrefix)
130+ if (((votes + 1) >= minVotes))
131+ then {
132+ let clearVoteEntries = getClearVoteEntries(keyPrefix)
133+ (clearVoteEntries ++ voteResult)
134+ }
135+ else [IntegerEntry(voteKey, 1)]
136+ }
137+ else throw("Strict value is not equal to itself.")
138+ }
56139
57140
58-func keyAvailable (userAddress) = makeString(["%s%s", "available", toString(userAddress)], SEP)
141+func keyCalculatorAddress () = "%s__calculator"
59142
60143
61-func keyClaimed (userAddress) = makeString(["%s%s", "claimed", toString(userAddress)], SEP)
144+func keyProxyTreasuryAddress () = "%s__proxyTreasury"
62145
63146
64-func keyCurrentPeriod () = makeString(["%s", "currentPeriod"], SEP)
65-
66-
67-func keyPriceForPeriod (period) = makeString(["%s%d", "price", toString(period)], SEP)
68-
69-
70-func keyStartHeight (period) = makeString(["%s%d", "startHeight", toString(period)], SEP)
71-
72-
73-func keyPeriodLength () = "%s__periodLength"
147+func keyChildAddress () = "%s__child"
74148
75149
76150 func keyBlockProcessingReward () = "%s__blockProcessingReward"
79153 func keyNextBlockToProcess () = "%s__nextBlockToProcess"
80154
81155
82-func keyBlockProcessed (height) = makeString(["%s%d", "blockProcessed", toString(height)], SEP)
156+func keyLpAssetId () = "%s__lpAssetId"
83157
84158
85-func keyWithdrawal () = "%s__withdrawal"
86-
87-
88-func keyWithdrawalRequest (userAddress,txId) = makeString(["%s%s%s", "withdrawal", toString(userAddress), toBase58String(txId)], SEP)
89-
90-
91-func valueWithdrawalRequest (status,lpAssetAmount,targetPeriod,claimTxId) = {
92- let claimTxIdStr = match claimTxId {
93- case b: ByteVector =>
94- toBase58String(b)
95- case _: Unit =>
96- "SOON"
97- case _ =>
98- throw("Match error")
99- }
100- makeString(["%s%d%d%s", status, toString(lpAssetAmount), toString(targetPeriod), claimTxIdStr], SEP)
101- }
102-
103-
104-func parseWithdrawalRequestValueOrFail (s) = {
105- let parts = split(s, SEP)
106- if ((size(parts) == 5))
107- then {
108- let status = parts[1]
109- let lpAssetAmount = valueOrErrorMessage(parseInt(parts[2]), wrapErr("invalid lpAssetAmount"))
110- let targetPeriod = valueOrErrorMessage(parseInt(parts[3]), wrapErr("invalid targetPeriod"))
111- let claimTxId = parts[4]
112- $Tuple4(status, lpAssetAmount, targetPeriod, claimTxId)
113- }
114- else throwErr("invalid withdrawal request value")
115- }
116-
117-
118-let factoryAddressOption = match getString(this, keyFactoryAddress()) {
159+let calculatorAddressOption = match getString(this, keyCalculatorAddress()) {
119160 case s: String =>
120161 addressFromString(s)
121162 case _: Unit =>
124165 throw("Match error")
125166 }
126167
127-let factoryAddressOrFail = valueOrErrorMessage(factoryAddressOption, wrapErr("invalid factory address"))
168+let calculatorAddressOrFail = valueOrErrorMessage(calculatorAddressOption, wrapErr("invalid calculator address"))
128169
129-let lpAssetIdOption = match factoryAddressOption {
130- case a: Address =>
131- match getString(a, keyLpAssetId()) {
132- case s: String =>
133- fromBase58String(s)
134- case _: Unit =>
135- unit
136- case _ =>
137- throw("Match error")
138- }
170+let proxyTreasuryAddressOption = match getString(this, keyProxyTreasuryAddress()) {
171+ case s: String =>
172+ addressFromString(s)
139173 case _: Unit =>
140174 unit
141175 case _ =>
142176 throw("Match error")
143177 }
144178
145-let lpAssetIdOrFail = valueOrErrorMessage(lpAssetIdOption, wrapErr("invalid lpAssetId"))
179+let proxyTreasuryAddressOrFail = valueOrErrorMessage(proxyTreasuryAddressOption, wrapErr("invalid proxy treasury address"))
146180
147-let proxyTreasuryAddressOption = match factoryAddressOption {
181+func keyConfigAddress () = "%s__config"
182+
183+
184+func keyChildrenAddress () = "contract_children"
185+
186+
187+func keyVotingResultAddress () = "contract_voting_result"
188+
189+
190+func keyProposalAllowBroadcast (address,txId) = ((("proposal_allow_broadcast_" + toString(address)) + "_") + toBase58String(txId))
191+
192+
193+func keyInvestedByUser (childAddress,userAddress) = makeString(["investor", toString(childAddress), toString(userAddress)], "_")
194+
195+
196+let configAddressOption = match getString(this, keyConfigAddress()) {
197+ case s: String =>
198+ addressFromString(s)
199+ case _: Unit =>
200+ unit
201+ case _ =>
202+ throw("Match error")
203+}
204+
205+let configAddressOrFail = valueOrErrorMessage(configAddressOption, wrapErr("invalid config address"))
206+
207+let votingResultAddressOption = match configAddressOption {
148208 case a: Address =>
149- match getString(a, keyProxyTreasuryAddress()) {
209+ match getString(a, keyVotingResultAddress()) {
150210 case s: String =>
151211 addressFromString(s)
152212 case _: Unit =>
160220 throw("Match error")
161221 }
162222
163-let proxyTreasuryAddressOrFail = valueOrErrorMessage(proxyTreasuryAddressOption, wrapErr("invalid proxy treasury address"))
223+let votingResultAddressOrFail = valueOrErrorMessage(votingResultAddressOption, wrapErr("invalid voting result address"))
164224
165-let featureTreasuryAddressOption = match factoryAddressOption {
225+let childrenAddressOption = match configAddressOption {
166226 case a: Address =>
167- match getString(a, keyMainTreasuryAddress()) {
227+ match getString(a, keyChildrenAddress()) {
168228 case s: String =>
169229 addressFromString(s)
170230 case _: Unit =>
178238 throw("Match error")
179239 }
180240
181-let featureTreasuryAddressOrFail = valueOrErrorMessage(featureTreasuryAddressOption, wrapErr("invalid feature treasury address"))
241+let childrenAddressOrFail = valueOrErrorMessage(childrenAddressOption, wrapErr("invalid children address"))
182242
183-func getManagerPublicKeyOrUnit () = match factoryAddressOption {
184- case fa: Address =>
185- match getString(fa, keyManagerPublicKey()) {
186- case pub: String =>
187- fromBase58String(pub)
188- case _ =>
189- unit
190- }
243+let lpAssetIdOption = match getString(this, keyLpAssetId()) {
244+ case s: String =>
245+ fromBase58String(s)
246+ case _: Unit =>
247+ unit
191248 case _ =>
192- unit
249+ throw("Match error")
193250 }
194251
252+let lpAssetIdOrFail = valueOrErrorMessage(lpAssetIdOption, wrapErr("invalid lpAssetId"))
195253
196254 func onlyAddress (i,address) = if ((i.caller == address))
197255 then true
198256 else throwErr("permission denied")
199257
200258
201-func onlyFactory (i) = onlyAddress(i, factoryAddressOrFail)
259+func onlyThis (i) = onlyAddress(i, this)
202260
203261
204-func rewardForOption (rewards,target) = {
205- let s = size(rewards)
206- let $t046414666 = rewards[0]
207- let a0 = $t046414666._1
208- let r0 = $t046414666._2
209- let $t046694694 = rewards[1]
210- let a1 = $t046694694._1
211- let r1 = $t046694694._2
212- let $t046974722 = rewards[2]
213- let a2 = $t046974722._1
214- let r2 = $t046974722._2
215- if (if ((s > 0))
216- then (a0 == target)
217- else false)
218- then r0
219- else if (if ((s > 1))
220- then (a1 == target)
221- else false)
222- then r1
223- else if (if ((s > 2))
224- then (a2 == target)
225- else false)
226- then r2
227- else unit
228- }
262+func onlyCalculator (i) = onlyAddress(i, calculatorAddressOrFail)
229263
230264
231265 @Callable(i)
232-func claimLP (userAddressBytes) = {
233- let checkCaller = onlyFactory(i)
234- if ((checkCaller == checkCaller))
235- then {
236- let userAddress = Address(userAddressBytes)
237- let available = valueOrElse(getInteger(factoryAddressOrFail, keyAvailable(userAddress)), 0)
238- let claimed = valueOrElse(getInteger(factoryAddressOrFail, keyClaimed(userAddress)), 0)
239- let factoryActions = if ((available > 0))
240- then [invoke(factoryAddressOrFail, "transferAsset", [userAddressBytes, available, lpAssetIdOrFail], nil), invoke(factoryAddressOrFail, "integerEntry", [keyAvailable(userAddress), 0], nil), invoke(factoryAddressOrFail, "integerEntry", [keyClaimed(userAddress), (claimed + available)], nil)]
241- else throwErr("nothing to claim")
242- $Tuple2(nil, factoryActions)
243- }
244- else throw("Strict value is not equal to itself.")
245- }
266+func stringEntry (key,val) = if (onlyCalculator(i))
267+ then $Tuple2([StringEntry(key, val)], key)
268+ else $Tuple2(nil, unit)
246269
247270
248271
249272 @Callable(i)
250-func finalize (userAddressBytes,newTreasuryVolumeInWaves,pwrManagersBonusInWaves,treasuryVolumeDiffAllocationCoef) = {
251- let checkCaller = onlyFactory(i)
252- if ((checkCaller == checkCaller))
253- then {
254- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
255- let periodLength = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPeriodLength()), wrapErr("invalid period length"))
256- let currentStartHeight = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyStartHeight(currentPeriodOrFail)), wrapErr("invalid start height"))
257- let currentPriceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(currentPeriodOrFail)), wrapErr("invalid price"))
258- let nextBlockToProcess = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyNextBlockToProcess()), wrapErr("invalid next block to process"))
259- let periodEndHeight = ((currentStartHeight + periodLength) - 1)
260- let checks = [if ((i.originCaller == featureTreasuryAddressOrFail))
261- then true
262- else throwErr("permission denied"), if ((nextBlockToProcess > periodEndHeight))
263- then true
264- else throwErr("unprocessed blocks"), if ((newTreasuryVolumeInWaves >= 0))
265- then true
266- else throwErr("invalid new treasury volume"), if ((pwrManagersBonusInWaves >= 0))
267- then true
268- else throwErr("invalid PWR managers bonus"), if (if ((treasuryVolumeDiffAllocationCoef >= -(SCALE8)))
269- then (SCALE8 >= treasuryVolumeDiffAllocationCoef)
270- else false)
271- then true
272- else throwErr("invalid treasury volume diff allocation coefficient")]
273- if ((checks == checks))
274- then {
275- let donatedWavesAmount = valueOrElse(getInteger(factoryAddressOrFail, keyDonated(unit)), 0)
276- let investedWavesAmount = valueOrElse(getInteger(factoryAddressOrFail, keyInvested(unit)), 0)
277- let currentTreasuryVolumeInWaves = (donatedWavesAmount + investedWavesAmount)
278- let profitRaw = (newTreasuryVolumeInWaves - currentTreasuryVolumeInWaves)
279- let pwrManagersBonusAmount = if (if ((profitRaw > 0))
280- then (profitRaw >= pwrManagersBonusInWaves)
281- else false)
282- then pwrManagersBonusInWaves
283- else 0
284- let profit = (profitRaw - pwrManagersBonusAmount)
285- let donationPart = if ((currentTreasuryVolumeInWaves > 0))
286- then fraction(donatedWavesAmount, SCALE8, currentTreasuryVolumeInWaves)
287- else 0
288- let donationProfitPartRaw = fraction(profit, donationPart, SCALE8)
289- let investmentProfitPartRaw = (profit - donationProfitPartRaw)
290- let treasuryVolumeDiffAllocationCoefAbs = abs(treasuryVolumeDiffAllocationCoef)
291- let amountToDonation = fraction(investmentProfitPartRaw, if ((0 > treasuryVolumeDiffAllocationCoef))
292- then treasuryVolumeDiffAllocationCoefAbs
293- else 0, SCALE8)
294- let amountToInvestment = fraction(donationProfitPartRaw, if ((treasuryVolumeDiffAllocationCoef > 0))
295- then treasuryVolumeDiffAllocationCoefAbs
296- else 0, SCALE8)
297- let donationProfitPart = ((donationProfitPartRaw - amountToInvestment) + amountToDonation)
298- let investmentProfitPart = ((investmentProfitPartRaw - amountToDonation) + amountToInvestment)
299- let investedWavesAmountNew = (investedWavesAmount + investmentProfitPart)
300- let newPeriod = (currentPeriodOrFail + 1)
301- let lpAssetQuantity = valueOrErrorMessage(assetInfo(lpAssetIdOrFail), wrapErr("invalid lpAsset info")).quantity
302- let newPrice = fraction(investedWavesAmountNew, SCALE8, lpAssetQuantity)
303- let lpAssetAmountToBurn = valueOrElse(getInteger(factoryAddressOrFail, keyWithdrawal()), 0)
304- let newLpAmount = (lpAssetQuantity - lpAssetAmountToBurn)
305- let newInvestAmount = max([0, fraction(newLpAmount, newPrice, SCALE8)])
306- let paymentAmountMin = max([0, fraction(lpAssetAmountToBurn, newPrice, SCALE8)])
307- let paymentOption = if ((size(i.payments) > 0))
308- then i.payments[0]
309- else unit
310- let paymentAmount = value(paymentOption).amount
311- let paymentAssetId = value(paymentOption).assetId
312- let checkPayment = if (if ((paymentAmountMin == 0))
313- then true
314- else if (if ((paymentOption != unit))
315- then (paymentAssetId == unit)
316- else false)
317- then (paymentAmount >= paymentAmountMin)
318- else false)
319- then true
320- else throwErr(("invalid payments, payment amount min: " + toString(paymentAmountMin)))
321- if ((checkPayment == checkPayment))
322- then {
323- let actions = if ((paymentOption != unit))
324- then [ScriptTransfer(factoryAddressOrFail, paymentAmount, paymentAssetId)]
325- else nil
326- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyCurrentPeriod(), newPeriod], nil), invoke(factoryAddressOrFail, "integerEntry", [keyPriceForPeriod(newPeriod), newPrice], nil), invoke(factoryAddressOrFail, "integerEntry", [keyStartHeight(newPeriod), (periodEndHeight + 1)], nil), invoke(factoryAddressOrFail, "burn", [lpAssetAmountToBurn], nil), invoke(factoryAddressOrFail, "integerEntry", [keyWithdrawal(), 0], nil), invoke(factoryAddressOrFail, "integerEntry", [keyInvested(unit), newInvestAmount], nil)]
327- $Tuple2(actions, factoryActions)
328- }
329- else throw("Strict value is not equal to itself.")
330- }
331- else throw("Strict value is not equal to itself.")
332- }
333- else throw("Strict value is not equal to itself.")
334- }
273+func integerEntry (key,val) = if (onlyCalculator(i))
274+ then $Tuple2([IntegerEntry(key, val)], key)
275+ else $Tuple2(nil, unit)
335276
336277
337278
338279 @Callable(i)
339-func invest (userAddressBytes) = {
340- let checkCaller = onlyFactory(i)
341- if ((checkCaller == checkCaller))
342- then {
343- let userAddress = Address(userAddressBytes)
344- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
345- let currentPriceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(currentPeriodOrFail)), wrapErr("invalid price"))
346- let payment = if ((size(i.payments) == 1))
347- then i.payments[0]
348- else throwErr("invalid payments")
349- let $t01124611423 = if (if ((payment.assetId == unit))
350- then (payment.amount > 0)
351- else false)
352- then $Tuple2(payment.amount, payment.assetId)
353- else throwErr("invalid payment amount")
354- let paymentAmount = $t01124611423._1
355- let paymentAssetId = $t01124611423._2
356- let lpAssetAmount = if ((currentPriceOrFail > 0))
357- then fraction(paymentAmount, SCALE8, currentPriceOrFail)
358- else 0
359- let invested = valueOrElse(getInteger(factoryAddressOrFail, keyInvested(unit)), 0)
360- let actions = [ScriptTransfer(featureTreasuryAddressOrFail, paymentAmount, paymentAssetId)]
361- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyInvested(unit), (invested + paymentAmount)], nil), invoke(factoryAddressOrFail, "reissue", [lpAssetAmount], nil), invoke(factoryAddressOrFail, "transferAsset", [userAddressBytes, lpAssetAmount, lpAssetIdOrFail], nil)]
362- $Tuple2(actions, factoryActions)
363- }
364- else throw("Strict value is not equal to itself.")
365- }
280+func booleanEntry (key,val) = if (onlyCalculator(i))
281+ then $Tuple2([BooleanEntry(key, val)], key)
282+ else $Tuple2(nil, unit)
366283
367284
368285
369286 @Callable(i)
370-func withdraw (userAddressBytes) = {
371- let checkCaller = onlyFactory(i)
372- if ((checkCaller == checkCaller))
373- then {
374- let userAddress = Address(userAddressBytes)
375- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
376- let payment = if ((size(i.payments) == 1))
377- then i.payments[0]
378- else throwErr(wrapErr("invalid payments"))
379- let paymentAssetId = if ((payment.assetId == lpAssetIdOrFail))
380- then lpAssetIdOrFail
381- else throwErr("invalid payment asset")
382- let paymentAmount = if ((payment.amount > 0))
383- then payment.amount
384- else throwErr("invalid payment amount")
385- let withdrawal = valueOrElse(getInteger(factoryAddressOrFail, keyWithdrawal()), 0)
386- let actions = [ScriptTransfer(factoryAddressOrFail, paymentAmount, paymentAssetId)]
387- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyWithdrawal(), (withdrawal + paymentAmount)], nil), invoke(factoryAddressOrFail, "stringEntry", [keyWithdrawalRequest(userAddress, i.transactionId), valueWithdrawalRequest(PENDING, paymentAmount, (currentPeriodOrFail + 1), unit)], nil)]
388- if ((factoryActions == factoryActions))
389- then $Tuple2(actions, factoryActions)
390- else throw("Strict value is not equal to itself.")
391- }
392- else throw("Strict value is not equal to itself.")
393- }
287+func binaryEntry (key,val) = if (onlyCalculator(i))
288+ then $Tuple2([BinaryEntry(key, val)], key)
289+ else $Tuple2(nil, unit)
394290
395291
396292
397293 @Callable(i)
398-func cancelWithdraw (userAddressBytes,txId) = {
399- let checkCaller = onlyFactory(i)
400- if ((checkCaller == checkCaller))
401- then {
402- let userAddress = Address(userAddressBytes)
403- let withdrawalRequestOption = valueOrErrorMessage(getString(factoryAddressOrFail, keyWithdrawalRequest(userAddress, txId)), wrapErr("invalid withdrawal request"))
404- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
405- let $t01383313946 = parseWithdrawalRequestValueOrFail(withdrawalRequestOption)
406- let status = $t01383313946._1
407- let lpAssetAmount = $t01383313946._2
408- let targetPeriod = $t01383313946._3
409- let claimTxId = $t01383313946._4
410- let checks = [if ((status == PENDING))
411- then true
412- else throwErr("invalid withdrawal request status"), if ((targetPeriod > currentPeriodOrFail))
413- then true
414- else throwErr("invalid withdrawal request period")]
415- if ((checks == checks))
416- then {
417- let withdrawal = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyWithdrawal()), wrapErr("invalid total withdrawal amount"))
418- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyWithdrawal(), if ((withdrawal >= lpAssetAmount))
419- then (withdrawal - lpAssetAmount)
420- else throwErr("invalid withdrawal amount")], nil), invoke(factoryAddressOrFail, "deleteEntry", [keyWithdrawalRequest(userAddress, txId)], nil), invoke(factoryAddressOrFail, "transferAsset", [userAddressBytes, lpAssetAmount, lpAssetIdOrFail], nil)]
421- if ((factoryActions == factoryActions))
422- then $Tuple2(nil, factoryActions)
423- else throw("Strict value is not equal to itself.")
424- }
425- else throw("Strict value is not equal to itself.")
426- }
427- else throw("Strict value is not equal to itself.")
428- }
294+func deleteEntry (key) = if (onlyCalculator(i))
295+ then $Tuple2([DeleteEntry(key)], key)
296+ else $Tuple2(nil, unit)
429297
430298
431299
432300 @Callable(i)
433-func claimWaves (userAddressBytes,txId) = {
434- let checkCaller = onlyFactory(i)
435- if ((checkCaller == checkCaller))
436- then {
437- let userAddress = Address(userAddressBytes)
438- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
439- let withdrawalRequestOption = valueOrErrorMessage(getString(factoryAddressOrFail, keyWithdrawalRequest(userAddress, txId)), wrapErr("invalid withdrawal request"))
440- let $t01527815391 = parseWithdrawalRequestValueOrFail(withdrawalRequestOption)
441- let status = $t01527815391._1
442- let lpAssetAmount = $t01527815391._2
443- let targetPeriod = $t01527815391._3
444- let claimTxId = $t01527815391._4
445- if ((status == FINISHED))
446- then throwErr("invalid withdrawal request status")
447- else if ((targetPeriod > currentPeriodOrFail))
448- then throwErr("invalid withdrawal request period")
449- else {
450- let priceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(targetPeriod)), wrapErr("invalid price"))
451- let amount = if ((priceOrFail > 0))
452- then fraction(lpAssetAmount, priceOrFail, SCALE8)
453- else 0
454- let factoryActions = [invoke(factoryAddressOrFail, "stringEntry", [keyWithdrawalRequest(userAddress, txId), valueWithdrawalRequest(FINISHED, lpAssetAmount, targetPeriod, i.transactionId)], nil), invoke(factoryAddressOrFail, "transferWaves", [userAddressBytes, amount], nil)]
455- $Tuple2(nil, factoryActions)
456- }
457- }
458- else throw("Strict value is not equal to itself.")
459- }
301+func reissue (amount) = if (onlyCalculator(i))
302+ then $Tuple2([Reissue(lpAssetIdOrFail, amount, true)], amount)
303+ else $Tuple2(nil, unit)
460304
461305
462306
463307 @Callable(i)
464-func processBlocks (userAddressBytes) = {
465- let checkCaller = onlyFactory(i)
466- if ((checkCaller == checkCaller))
467- then {
468- let userAddress = Address(userAddressBytes)
469- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
470- let periodLength = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPeriodLength()), wrapErr("invalid period length"))
471- let currentStartHeight = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyStartHeight(currentPeriodOrFail)), wrapErr("invalid start height"))
472- let currentPriceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(currentPeriodOrFail)), wrapErr("invalid price"))
473- let nextBlockToProcess = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyNextBlockToProcess()), wrapErr("invalid next block to process"))
474- let periodEndHeight = ((currentStartHeight + periodLength) - 1)
475- let blocksProcessingBatchSizeMax = 40
476- let blocksProcessingBatchSize = if (if (if ((height >= nextBlockToProcess))
477- then if ((nextBlockToProcess >= currentStartHeight))
478- then true
479- else (currentPeriodOrFail == 0)
480- else false)
481- then (periodEndHeight >= nextBlockToProcess)
482- else false)
483- then min([((periodEndHeight - nextBlockToProcess) + 1), blocksProcessingBatchSizeMax])
484- else throwErr(wrapErr("invalid target block"))
485- let blockProcessingReward = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyBlockProcessingReward()), wrapErr("invalid block processing reward"))
486- let blockProcessingRewardByGenerator = (blockProcessingReward / blocksProcessingBatchSize)
487- let blockProcessingRewardByGeneratorRemainder = (blockProcessingReward - (blockProcessingRewardByGenerator * blocksProcessingBatchSize))
488- func map (acc,inc) = if ((inc >= blocksProcessingBatchSize))
489- then acc
490- else {
491- let targetBlockHeight = (nextBlockToProcess + inc)
492- let targetBlockInfo = valueOrErrorMessage(blockInfoByHeight(targetBlockHeight), wrapErr("invalid block info"))
493- let treasuryRewardOrFail = valueOrErrorMessage(rewardForOption(targetBlockInfo.rewards, proxyTreasuryAddressOrFail), wrapErr(("invalid treasury reward for height " + toString(targetBlockHeight))))
494- let generator = targetBlockInfo.generator
495- let available = valueOrElse(getInteger(factoryAddressOrFail, keyAvailable(generator)), 0)
496- let callerReward = if ((inc == (blocksProcessingBatchSize - 1)))
497- then (blockProcessingRewardByGenerator + blockProcessingRewardByGeneratorRemainder)
498- else blockProcessingRewardByGenerator
499- let lpAssetAmount = if ((currentPriceOrFail > 0))
500- then fraction((treasuryRewardOrFail - callerReward), SCALE8, currentPriceOrFail)
501- else 0
502- let factoryActionsSingle = [invoke(factoryAddressOrFail, "stringEntry", [keyBlockProcessed(targetBlockHeight), makeString([toBase58String(i.transactionId), toString(currentPeriodOrFail), toString(generator), toBase58String(userAddressBytes), toString(treasuryRewardOrFail), toString(callerReward), toString(lpAssetAmount)], SEP)], nil), invoke(factoryAddressOrFail, "integerEntry", [keyAvailable(generator), (available + lpAssetAmount)], nil)]
503- if ((factoryActionsSingle == factoryActionsSingle))
504- then {
505- let $t01962719660 = acc
506- let lpAssetAcc = $t01962719660._1
507- let rewardAcc = $t01962719660._2
508- $Tuple2((lpAssetAcc + lpAssetAmount), (rewardAcc + treasuryRewardOrFail))
509- }
510- else throw("Strict value is not equal to itself.")
511- }
308+func burn (amount) = if (onlyCalculator(i))
309+ then $Tuple2([Burn(lpAssetIdOrFail, amount)], amount)
310+ else $Tuple2(nil, unit)
512311
513- let list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
514- let $t01992720003 = {
515- let $l = list
516- let $s = size($l)
517- let $acc0 = $Tuple2(0, 0)
518- func $f0_1 ($a,$i) = if (($i >= $s))
519- then $a
520- else map($a, $l[$i])
521312
522- func $f0_2 ($a,$i) = if (($i >= $s))
523- then $a
524- else throw("List size exceeds 40")
525313
526- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40)
527- }
528- if (($t01992720003 == $t01992720003))
529- then {
530- let rewardAmountTotal = $t01992720003._2
531- let lpAssetAmountTotal = $t01992720003._1
532- let rewardToMainTreasuryAmount = (rewardAmountTotal - blockProcessingReward)
533- let invested = valueOrElse(getInteger(factoryAddressOrFail, keyInvested(unit)), 0)
534- let actions = [invoke(factoryAddressOrFail, "reissue", [lpAssetAmountTotal], nil), invoke(factoryAddressOrFail, "integerEntry", [keyNextBlockToProcess(), (nextBlockToProcess + blocksProcessingBatchSize)], nil), invoke(factoryAddressOrFail, "transferFromProxyTreasury", [featureTreasuryAddressOrFail.bytes, rewardToMainTreasuryAmount], nil), invoke(factoryAddressOrFail, "transferFromProxyTreasury", [userAddressBytes, blockProcessingReward], nil), invoke(factoryAddressOrFail, "integerEntry", [keyInvested(unit), (invested + rewardToMainTreasuryAmount)], nil)]
535- if ((actions == actions))
536- then $Tuple2(nil, unit)
537- else throw("Strict value is not equal to itself.")
538- }
539- else throw("Strict value is not equal to itself.")
540- }
314+@Callable(i)
315+func transferAsset (recepientBytes,amount,assetId) = if (onlyCalculator(i))
316+ then $Tuple2([ScriptTransfer(Address(recepientBytes), amount, assetId)], amount)
317+ else $Tuple2(nil, unit)
318+
319+
320+
321+@Callable(i)
322+func transferWaves (recepientBytes,amount) = if (onlyCalculator(i))
323+ then $Tuple2([ScriptTransfer(Address(recepientBytes), amount, unit)], amount)
324+ else $Tuple2(nil, unit)
325+
326+
327+
328+@Callable(i)
329+func transferFromProxyTreasury (recipientBytes,rewardsAmount) = if (onlyCalculator(i))
330+ then $Tuple2(nil, invoke(proxyTreasuryAddressOrFail, "transferWaves", [recipientBytes, rewardsAmount], nil))
331+ else $Tuple2(nil, unit)
332+
333+
334+
335+@Callable(i)
336+func finalize (newTreasuryVolumeInWaves,pwrManagersBonusInWaves,treasuryVolumeDiffAllocationCoef) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "finalize", [i.caller.bytes, newTreasuryVolumeInWaves, pwrManagersBonusInWaves, treasuryVolumeDiffAllocationCoef], i.payments))
337+
338+
339+
340+@Callable(i)
341+func claimLP () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "claimLP", [i.caller.bytes], i.payments))
342+
343+
344+
345+@Callable(i)
346+func claimWaves (txIdStr) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "claimWaves", [i.caller.bytes, fromBase58String(txIdStr)], i.payments))
347+
348+
349+
350+@Callable(i)
351+func invest () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "invest", [i.caller.bytes], i.payments))
352+
353+
354+
355+@Callable(i)
356+func withdraw () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "withdraw", [i.caller.bytes], i.payments))
357+
358+
359+
360+@Callable(i)
361+func cancelWithdraw (txIdStr) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "cancelWithdraw", [i.caller.bytes, fromBase58String(txIdStr)], i.payments))
362+
363+
364+
365+@Callable(i)
366+func processBlocks () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "processBlocks", [i.caller.bytes], i.payments))
367+
368+
369+
370+@Callable(i)
371+func voteForTxId (txId) = {
372+ let callerAddressString = toBase58String(i.caller.bytes)
373+ let keyPrefix = keyAllowedTxIdVotePrefix(txId)
374+ let result = [StringEntry(keyAllowedTxId(), txId)]
375+ let allowedTxIdOption = getString(this, keyAllowedTxId())
376+ let err = [if ((size(fromBase58String(txId)) == TXID_BYTES_LENGTH))
377+ then true
378+ else throwErr((txId + " is not valid txId")), if (if ((allowedTxIdOption == unit))
379+ then true
380+ else (value(allowedTxIdOption) != txId))
381+ then true
382+ else throwErr((txId + " is already allowed"))]
383+ if ((err == err))
384+ then voteINTERNAL(callerAddressString, keyPrefix, QUORUM, result)
541385 else throw("Strict value is not equal to itself.")
542386 }
543387
544388
545389 @Verifier(tx)
546390 func verify () = {
547- let publicKey = match getManagerPublicKeyOrUnit() {
548- case pub: ByteVector =>
549- pub
391+ let byProposal = match votingResultAddressOption {
392+ case proposalAddress: Address =>
393+ valueOrElse(getBoolean(proposalAddress, keyProposalAllowBroadcast(this, tx.id)), false)
550394 case _ =>
551- tx.senderPublicKey
395+ false
552396 }
553- sigVerify(tx.bodyBytes, tx.proofs[0], publicKey)
397+ let byAdmins = (tx.id == fromBase58String(valueOrElse(getString(this, keyAllowedTxId()), "")))
398+ let byOwner = if ((size(getAdminsList()) >= QUORUM))
399+ then false
400+ else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
401+ if (if (byProposal)
402+ then true
403+ else byAdmins)
404+ then true
405+ else byOwner
554406 }
555407
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 7 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let SEP = "__"
55
6-let CONTRACT_NAME = "calculator.ride"
6+let contractFilename = "factory.ride"
77
8-let SCALE8 = 100000000
9-
10-let PENDING = "PENDING"
11-
12-let FINISHED = "FINISHED"
13-
14-let WAVES = "WAVES"
15-
16-func wrapErr (s) = ((CONTRACT_NAME + ": ") + s)
8+func wrapErr (s) = ((contractFilename + ": ") + s)
179
1810
1911 func throwErr (s) = throw(wrapErr(s))
2012
2113
22-func assetIdToString (assetId) = match assetId {
23- case b: ByteVector =>
24- toBase58String(b)
25- case _: Unit =>
26- WAVES
14+let ADMIN_LIST_SIZE = 5
15+
16+let QUORUM = 3
17+
18+let TXID_BYTES_LENGTH = 32
19+
20+func keyAllowedTxIdVotePrefix (txId) = makeString(["%s%s%s", "allowTxId", txId], SEP)
21+
22+
23+func keyFullAdminVote (prefix,adminAddress) = makeString([prefix, adminAddress], SEP)
24+
25+
26+func keyAdminAddressList () = makeString(["%s", "adminAddressList"], SEP)
27+
28+
29+func keyAllowedTxId () = makeString(["%s", "txId"], SEP)
30+
31+
32+func getAdminVote (prefix,admin) = {
33+ let voteKey = keyFullAdminVote(prefix, admin)
34+ valueOrElse(getInteger(voteKey), 0)
35+ }
36+
37+
38+func getAdminsList () = match getString(this, keyAdminAddressList()) {
39+ case s: String =>
40+ split(s, SEP)
2741 case _ =>
28- throw("Match error")
42+ nil
2943 }
3044
3145
32-func abs (n) = if ((0 > n))
33- then -(n)
34- else n
46+func isInAdminList (address) = containsElement(getAdminsList(), address)
3547
3648
37-func keyFactoryAddress () = makeString(["%s", "factory"], SEP)
49+func genVotesKeysHelper (a,adminAddress) = {
50+ let $t012621286 = a
51+ let result = $t012621286._1
52+ let prefix = $t012621286._2
53+ $Tuple2((result :+ keyFullAdminVote(prefix, adminAddress)), prefix)
54+ }
3855
3956
40-func keyManagerPublicKey () = makeString(["%s", "managerPublicKey"], SEP)
57+func genVotesKeys (keyPrefix) = {
58+ let adminList = keyAdminAddressList()
59+ let $t014331517 = {
60+ let $l = getAdminsList()
61+ let $s = size($l)
62+ let $acc0 = $Tuple2(nil, keyPrefix)
63+ func $f0_1 ($a,$i) = if (($i >= $s))
64+ then $a
65+ else genVotesKeysHelper($a, $l[$i])
66+
67+ func $f0_2 ($a,$i) = if (($i >= $s))
68+ then $a
69+ else throw("List size exceeds 5")
70+
71+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
72+ }
73+ let result = $t014331517._1
74+ let prefix = $t014331517._2
75+ result
76+ }
4177
4278
43-func keyLpAssetId () = makeString(["%s", "lpAssetId"], SEP)
79+func countVotesHelper (result,voteKey) = (result + valueOrElse(getInteger(voteKey), 0))
4480
4581
46-func keyProxyTreasuryAddress () = makeString(["%s", "proxyTreasury"], SEP)
82+func countVotes (prefix) = {
83+ let votes = genVotesKeys(prefix)
84+ let $l = votes
85+ let $s = size($l)
86+ let $acc0 = 0
87+ func $f0_1 ($a,$i) = if (($i >= $s))
88+ then $a
89+ else countVotesHelper($a, $l[$i])
90+
91+ func $f0_2 ($a,$i) = if (($i >= $s))
92+ then $a
93+ else throw("List size exceeds 5")
94+
95+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
96+ }
4797
4898
49-func keyMainTreasuryAddress () = makeString(["%s", "mainTreasury"], SEP)
99+func clearVotesHelper (result,key) = (result :+ DeleteEntry(key))
50100
51101
52-func keyInvested (assetId) = makeString(["%s%s", "invested", assetIdToString(assetId)], SEP)
102+func getClearVoteEntries (prefix) = {
103+ let votes = genVotesKeys(prefix)
104+ let $l = votes
105+ let $s = size($l)
106+ let $acc0 = nil
107+ func $f0_1 ($a,$i) = if (($i >= $s))
108+ then $a
109+ else clearVotesHelper($a, $l[$i])
110+
111+ func $f0_2 ($a,$i) = if (($i >= $s))
112+ then $a
113+ else throw("List size exceeds 5")
114+
115+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
116+ }
53117
54118
55-func keyDonated (assetId) = makeString(["%s%s", "donated", assetIdToString(assetId)], SEP)
119+func voteINTERNAL (callerAddressString,keyPrefix,minVotes,voteResult) = {
120+ let voteKey = keyFullAdminVote(keyPrefix, callerAddressString)
121+ let adminCurrentVote = getAdminVote(keyPrefix, callerAddressString)
122+ let err = if (!(isInAdminList(callerAddressString)))
123+ then throwErr((("Address: " + callerAddressString) + " not in Admin list"))
124+ else if ((adminCurrentVote == 1))
125+ then throwErr((voteKey + " you already voted"))
126+ else unit
127+ if ((err == err))
128+ then {
129+ let votes = countVotes(keyPrefix)
130+ if (((votes + 1) >= minVotes))
131+ then {
132+ let clearVoteEntries = getClearVoteEntries(keyPrefix)
133+ (clearVoteEntries ++ voteResult)
134+ }
135+ else [IntegerEntry(voteKey, 1)]
136+ }
137+ else throw("Strict value is not equal to itself.")
138+ }
56139
57140
58-func keyAvailable (userAddress) = makeString(["%s%s", "available", toString(userAddress)], SEP)
141+func keyCalculatorAddress () = "%s__calculator"
59142
60143
61-func keyClaimed (userAddress) = makeString(["%s%s", "claimed", toString(userAddress)], SEP)
144+func keyProxyTreasuryAddress () = "%s__proxyTreasury"
62145
63146
64-func keyCurrentPeriod () = makeString(["%s", "currentPeriod"], SEP)
65-
66-
67-func keyPriceForPeriod (period) = makeString(["%s%d", "price", toString(period)], SEP)
68-
69-
70-func keyStartHeight (period) = makeString(["%s%d", "startHeight", toString(period)], SEP)
71-
72-
73-func keyPeriodLength () = "%s__periodLength"
147+func keyChildAddress () = "%s__child"
74148
75149
76150 func keyBlockProcessingReward () = "%s__blockProcessingReward"
77151
78152
79153 func keyNextBlockToProcess () = "%s__nextBlockToProcess"
80154
81155
82-func keyBlockProcessed (height) = makeString(["%s%d", "blockProcessed", toString(height)], SEP)
156+func keyLpAssetId () = "%s__lpAssetId"
83157
84158
85-func keyWithdrawal () = "%s__withdrawal"
86-
87-
88-func keyWithdrawalRequest (userAddress,txId) = makeString(["%s%s%s", "withdrawal", toString(userAddress), toBase58String(txId)], SEP)
89-
90-
91-func valueWithdrawalRequest (status,lpAssetAmount,targetPeriod,claimTxId) = {
92- let claimTxIdStr = match claimTxId {
93- case b: ByteVector =>
94- toBase58String(b)
95- case _: Unit =>
96- "SOON"
97- case _ =>
98- throw("Match error")
99- }
100- makeString(["%s%d%d%s", status, toString(lpAssetAmount), toString(targetPeriod), claimTxIdStr], SEP)
101- }
102-
103-
104-func parseWithdrawalRequestValueOrFail (s) = {
105- let parts = split(s, SEP)
106- if ((size(parts) == 5))
107- then {
108- let status = parts[1]
109- let lpAssetAmount = valueOrErrorMessage(parseInt(parts[2]), wrapErr("invalid lpAssetAmount"))
110- let targetPeriod = valueOrErrorMessage(parseInt(parts[3]), wrapErr("invalid targetPeriod"))
111- let claimTxId = parts[4]
112- $Tuple4(status, lpAssetAmount, targetPeriod, claimTxId)
113- }
114- else throwErr("invalid withdrawal request value")
115- }
116-
117-
118-let factoryAddressOption = match getString(this, keyFactoryAddress()) {
159+let calculatorAddressOption = match getString(this, keyCalculatorAddress()) {
119160 case s: String =>
120161 addressFromString(s)
121162 case _: Unit =>
122163 unit
123164 case _ =>
124165 throw("Match error")
125166 }
126167
127-let factoryAddressOrFail = valueOrErrorMessage(factoryAddressOption, wrapErr("invalid factory address"))
168+let calculatorAddressOrFail = valueOrErrorMessage(calculatorAddressOption, wrapErr("invalid calculator address"))
128169
129-let lpAssetIdOption = match factoryAddressOption {
130- case a: Address =>
131- match getString(a, keyLpAssetId()) {
132- case s: String =>
133- fromBase58String(s)
134- case _: Unit =>
135- unit
136- case _ =>
137- throw("Match error")
138- }
170+let proxyTreasuryAddressOption = match getString(this, keyProxyTreasuryAddress()) {
171+ case s: String =>
172+ addressFromString(s)
139173 case _: Unit =>
140174 unit
141175 case _ =>
142176 throw("Match error")
143177 }
144178
145-let lpAssetIdOrFail = valueOrErrorMessage(lpAssetIdOption, wrapErr("invalid lpAssetId"))
179+let proxyTreasuryAddressOrFail = valueOrErrorMessage(proxyTreasuryAddressOption, wrapErr("invalid proxy treasury address"))
146180
147-let proxyTreasuryAddressOption = match factoryAddressOption {
181+func keyConfigAddress () = "%s__config"
182+
183+
184+func keyChildrenAddress () = "contract_children"
185+
186+
187+func keyVotingResultAddress () = "contract_voting_result"
188+
189+
190+func keyProposalAllowBroadcast (address,txId) = ((("proposal_allow_broadcast_" + toString(address)) + "_") + toBase58String(txId))
191+
192+
193+func keyInvestedByUser (childAddress,userAddress) = makeString(["investor", toString(childAddress), toString(userAddress)], "_")
194+
195+
196+let configAddressOption = match getString(this, keyConfigAddress()) {
197+ case s: String =>
198+ addressFromString(s)
199+ case _: Unit =>
200+ unit
201+ case _ =>
202+ throw("Match error")
203+}
204+
205+let configAddressOrFail = valueOrErrorMessage(configAddressOption, wrapErr("invalid config address"))
206+
207+let votingResultAddressOption = match configAddressOption {
148208 case a: Address =>
149- match getString(a, keyProxyTreasuryAddress()) {
209+ match getString(a, keyVotingResultAddress()) {
150210 case s: String =>
151211 addressFromString(s)
152212 case _: Unit =>
153213 unit
154214 case _ =>
155215 throw("Match error")
156216 }
157217 case _: Unit =>
158218 unit
159219 case _ =>
160220 throw("Match error")
161221 }
162222
163-let proxyTreasuryAddressOrFail = valueOrErrorMessage(proxyTreasuryAddressOption, wrapErr("invalid proxy treasury address"))
223+let votingResultAddressOrFail = valueOrErrorMessage(votingResultAddressOption, wrapErr("invalid voting result address"))
164224
165-let featureTreasuryAddressOption = match factoryAddressOption {
225+let childrenAddressOption = match configAddressOption {
166226 case a: Address =>
167- match getString(a, keyMainTreasuryAddress()) {
227+ match getString(a, keyChildrenAddress()) {
168228 case s: String =>
169229 addressFromString(s)
170230 case _: Unit =>
171231 unit
172232 case _ =>
173233 throw("Match error")
174234 }
175235 case _: Unit =>
176236 unit
177237 case _ =>
178238 throw("Match error")
179239 }
180240
181-let featureTreasuryAddressOrFail = valueOrErrorMessage(featureTreasuryAddressOption, wrapErr("invalid feature treasury address"))
241+let childrenAddressOrFail = valueOrErrorMessage(childrenAddressOption, wrapErr("invalid children address"))
182242
183-func getManagerPublicKeyOrUnit () = match factoryAddressOption {
184- case fa: Address =>
185- match getString(fa, keyManagerPublicKey()) {
186- case pub: String =>
187- fromBase58String(pub)
188- case _ =>
189- unit
190- }
243+let lpAssetIdOption = match getString(this, keyLpAssetId()) {
244+ case s: String =>
245+ fromBase58String(s)
246+ case _: Unit =>
247+ unit
191248 case _ =>
192- unit
249+ throw("Match error")
193250 }
194251
252+let lpAssetIdOrFail = valueOrErrorMessage(lpAssetIdOption, wrapErr("invalid lpAssetId"))
195253
196254 func onlyAddress (i,address) = if ((i.caller == address))
197255 then true
198256 else throwErr("permission denied")
199257
200258
201-func onlyFactory (i) = onlyAddress(i, factoryAddressOrFail)
259+func onlyThis (i) = onlyAddress(i, this)
202260
203261
204-func rewardForOption (rewards,target) = {
205- let s = size(rewards)
206- let $t046414666 = rewards[0]
207- let a0 = $t046414666._1
208- let r0 = $t046414666._2
209- let $t046694694 = rewards[1]
210- let a1 = $t046694694._1
211- let r1 = $t046694694._2
212- let $t046974722 = rewards[2]
213- let a2 = $t046974722._1
214- let r2 = $t046974722._2
215- if (if ((s > 0))
216- then (a0 == target)
217- else false)
218- then r0
219- else if (if ((s > 1))
220- then (a1 == target)
221- else false)
222- then r1
223- else if (if ((s > 2))
224- then (a2 == target)
225- else false)
226- then r2
227- else unit
228- }
262+func onlyCalculator (i) = onlyAddress(i, calculatorAddressOrFail)
229263
230264
231265 @Callable(i)
232-func claimLP (userAddressBytes) = {
233- let checkCaller = onlyFactory(i)
234- if ((checkCaller == checkCaller))
235- then {
236- let userAddress = Address(userAddressBytes)
237- let available = valueOrElse(getInteger(factoryAddressOrFail, keyAvailable(userAddress)), 0)
238- let claimed = valueOrElse(getInteger(factoryAddressOrFail, keyClaimed(userAddress)), 0)
239- let factoryActions = if ((available > 0))
240- then [invoke(factoryAddressOrFail, "transferAsset", [userAddressBytes, available, lpAssetIdOrFail], nil), invoke(factoryAddressOrFail, "integerEntry", [keyAvailable(userAddress), 0], nil), invoke(factoryAddressOrFail, "integerEntry", [keyClaimed(userAddress), (claimed + available)], nil)]
241- else throwErr("nothing to claim")
242- $Tuple2(nil, factoryActions)
243- }
244- else throw("Strict value is not equal to itself.")
245- }
266+func stringEntry (key,val) = if (onlyCalculator(i))
267+ then $Tuple2([StringEntry(key, val)], key)
268+ else $Tuple2(nil, unit)
246269
247270
248271
249272 @Callable(i)
250-func finalize (userAddressBytes,newTreasuryVolumeInWaves,pwrManagersBonusInWaves,treasuryVolumeDiffAllocationCoef) = {
251- let checkCaller = onlyFactory(i)
252- if ((checkCaller == checkCaller))
253- then {
254- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
255- let periodLength = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPeriodLength()), wrapErr("invalid period length"))
256- let currentStartHeight = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyStartHeight(currentPeriodOrFail)), wrapErr("invalid start height"))
257- let currentPriceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(currentPeriodOrFail)), wrapErr("invalid price"))
258- let nextBlockToProcess = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyNextBlockToProcess()), wrapErr("invalid next block to process"))
259- let periodEndHeight = ((currentStartHeight + periodLength) - 1)
260- let checks = [if ((i.originCaller == featureTreasuryAddressOrFail))
261- then true
262- else throwErr("permission denied"), if ((nextBlockToProcess > periodEndHeight))
263- then true
264- else throwErr("unprocessed blocks"), if ((newTreasuryVolumeInWaves >= 0))
265- then true
266- else throwErr("invalid new treasury volume"), if ((pwrManagersBonusInWaves >= 0))
267- then true
268- else throwErr("invalid PWR managers bonus"), if (if ((treasuryVolumeDiffAllocationCoef >= -(SCALE8)))
269- then (SCALE8 >= treasuryVolumeDiffAllocationCoef)
270- else false)
271- then true
272- else throwErr("invalid treasury volume diff allocation coefficient")]
273- if ((checks == checks))
274- then {
275- let donatedWavesAmount = valueOrElse(getInteger(factoryAddressOrFail, keyDonated(unit)), 0)
276- let investedWavesAmount = valueOrElse(getInteger(factoryAddressOrFail, keyInvested(unit)), 0)
277- let currentTreasuryVolumeInWaves = (donatedWavesAmount + investedWavesAmount)
278- let profitRaw = (newTreasuryVolumeInWaves - currentTreasuryVolumeInWaves)
279- let pwrManagersBonusAmount = if (if ((profitRaw > 0))
280- then (profitRaw >= pwrManagersBonusInWaves)
281- else false)
282- then pwrManagersBonusInWaves
283- else 0
284- let profit = (profitRaw - pwrManagersBonusAmount)
285- let donationPart = if ((currentTreasuryVolumeInWaves > 0))
286- then fraction(donatedWavesAmount, SCALE8, currentTreasuryVolumeInWaves)
287- else 0
288- let donationProfitPartRaw = fraction(profit, donationPart, SCALE8)
289- let investmentProfitPartRaw = (profit - donationProfitPartRaw)
290- let treasuryVolumeDiffAllocationCoefAbs = abs(treasuryVolumeDiffAllocationCoef)
291- let amountToDonation = fraction(investmentProfitPartRaw, if ((0 > treasuryVolumeDiffAllocationCoef))
292- then treasuryVolumeDiffAllocationCoefAbs
293- else 0, SCALE8)
294- let amountToInvestment = fraction(donationProfitPartRaw, if ((treasuryVolumeDiffAllocationCoef > 0))
295- then treasuryVolumeDiffAllocationCoefAbs
296- else 0, SCALE8)
297- let donationProfitPart = ((donationProfitPartRaw - amountToInvestment) + amountToDonation)
298- let investmentProfitPart = ((investmentProfitPartRaw - amountToDonation) + amountToInvestment)
299- let investedWavesAmountNew = (investedWavesAmount + investmentProfitPart)
300- let newPeriod = (currentPeriodOrFail + 1)
301- let lpAssetQuantity = valueOrErrorMessage(assetInfo(lpAssetIdOrFail), wrapErr("invalid lpAsset info")).quantity
302- let newPrice = fraction(investedWavesAmountNew, SCALE8, lpAssetQuantity)
303- let lpAssetAmountToBurn = valueOrElse(getInteger(factoryAddressOrFail, keyWithdrawal()), 0)
304- let newLpAmount = (lpAssetQuantity - lpAssetAmountToBurn)
305- let newInvestAmount = max([0, fraction(newLpAmount, newPrice, SCALE8)])
306- let paymentAmountMin = max([0, fraction(lpAssetAmountToBurn, newPrice, SCALE8)])
307- let paymentOption = if ((size(i.payments) > 0))
308- then i.payments[0]
309- else unit
310- let paymentAmount = value(paymentOption).amount
311- let paymentAssetId = value(paymentOption).assetId
312- let checkPayment = if (if ((paymentAmountMin == 0))
313- then true
314- else if (if ((paymentOption != unit))
315- then (paymentAssetId == unit)
316- else false)
317- then (paymentAmount >= paymentAmountMin)
318- else false)
319- then true
320- else throwErr(("invalid payments, payment amount min: " + toString(paymentAmountMin)))
321- if ((checkPayment == checkPayment))
322- then {
323- let actions = if ((paymentOption != unit))
324- then [ScriptTransfer(factoryAddressOrFail, paymentAmount, paymentAssetId)]
325- else nil
326- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyCurrentPeriod(), newPeriod], nil), invoke(factoryAddressOrFail, "integerEntry", [keyPriceForPeriod(newPeriod), newPrice], nil), invoke(factoryAddressOrFail, "integerEntry", [keyStartHeight(newPeriod), (periodEndHeight + 1)], nil), invoke(factoryAddressOrFail, "burn", [lpAssetAmountToBurn], nil), invoke(factoryAddressOrFail, "integerEntry", [keyWithdrawal(), 0], nil), invoke(factoryAddressOrFail, "integerEntry", [keyInvested(unit), newInvestAmount], nil)]
327- $Tuple2(actions, factoryActions)
328- }
329- else throw("Strict value is not equal to itself.")
330- }
331- else throw("Strict value is not equal to itself.")
332- }
333- else throw("Strict value is not equal to itself.")
334- }
273+func integerEntry (key,val) = if (onlyCalculator(i))
274+ then $Tuple2([IntegerEntry(key, val)], key)
275+ else $Tuple2(nil, unit)
335276
336277
337278
338279 @Callable(i)
339-func invest (userAddressBytes) = {
340- let checkCaller = onlyFactory(i)
341- if ((checkCaller == checkCaller))
342- then {
343- let userAddress = Address(userAddressBytes)
344- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
345- let currentPriceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(currentPeriodOrFail)), wrapErr("invalid price"))
346- let payment = if ((size(i.payments) == 1))
347- then i.payments[0]
348- else throwErr("invalid payments")
349- let $t01124611423 = if (if ((payment.assetId == unit))
350- then (payment.amount > 0)
351- else false)
352- then $Tuple2(payment.amount, payment.assetId)
353- else throwErr("invalid payment amount")
354- let paymentAmount = $t01124611423._1
355- let paymentAssetId = $t01124611423._2
356- let lpAssetAmount = if ((currentPriceOrFail > 0))
357- then fraction(paymentAmount, SCALE8, currentPriceOrFail)
358- else 0
359- let invested = valueOrElse(getInteger(factoryAddressOrFail, keyInvested(unit)), 0)
360- let actions = [ScriptTransfer(featureTreasuryAddressOrFail, paymentAmount, paymentAssetId)]
361- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyInvested(unit), (invested + paymentAmount)], nil), invoke(factoryAddressOrFail, "reissue", [lpAssetAmount], nil), invoke(factoryAddressOrFail, "transferAsset", [userAddressBytes, lpAssetAmount, lpAssetIdOrFail], nil)]
362- $Tuple2(actions, factoryActions)
363- }
364- else throw("Strict value is not equal to itself.")
365- }
280+func booleanEntry (key,val) = if (onlyCalculator(i))
281+ then $Tuple2([BooleanEntry(key, val)], key)
282+ else $Tuple2(nil, unit)
366283
367284
368285
369286 @Callable(i)
370-func withdraw (userAddressBytes) = {
371- let checkCaller = onlyFactory(i)
372- if ((checkCaller == checkCaller))
373- then {
374- let userAddress = Address(userAddressBytes)
375- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
376- let payment = if ((size(i.payments) == 1))
377- then i.payments[0]
378- else throwErr(wrapErr("invalid payments"))
379- let paymentAssetId = if ((payment.assetId == lpAssetIdOrFail))
380- then lpAssetIdOrFail
381- else throwErr("invalid payment asset")
382- let paymentAmount = if ((payment.amount > 0))
383- then payment.amount
384- else throwErr("invalid payment amount")
385- let withdrawal = valueOrElse(getInteger(factoryAddressOrFail, keyWithdrawal()), 0)
386- let actions = [ScriptTransfer(factoryAddressOrFail, paymentAmount, paymentAssetId)]
387- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyWithdrawal(), (withdrawal + paymentAmount)], nil), invoke(factoryAddressOrFail, "stringEntry", [keyWithdrawalRequest(userAddress, i.transactionId), valueWithdrawalRequest(PENDING, paymentAmount, (currentPeriodOrFail + 1), unit)], nil)]
388- if ((factoryActions == factoryActions))
389- then $Tuple2(actions, factoryActions)
390- else throw("Strict value is not equal to itself.")
391- }
392- else throw("Strict value is not equal to itself.")
393- }
287+func binaryEntry (key,val) = if (onlyCalculator(i))
288+ then $Tuple2([BinaryEntry(key, val)], key)
289+ else $Tuple2(nil, unit)
394290
395291
396292
397293 @Callable(i)
398-func cancelWithdraw (userAddressBytes,txId) = {
399- let checkCaller = onlyFactory(i)
400- if ((checkCaller == checkCaller))
401- then {
402- let userAddress = Address(userAddressBytes)
403- let withdrawalRequestOption = valueOrErrorMessage(getString(factoryAddressOrFail, keyWithdrawalRequest(userAddress, txId)), wrapErr("invalid withdrawal request"))
404- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
405- let $t01383313946 = parseWithdrawalRequestValueOrFail(withdrawalRequestOption)
406- let status = $t01383313946._1
407- let lpAssetAmount = $t01383313946._2
408- let targetPeriod = $t01383313946._3
409- let claimTxId = $t01383313946._4
410- let checks = [if ((status == PENDING))
411- then true
412- else throwErr("invalid withdrawal request status"), if ((targetPeriod > currentPeriodOrFail))
413- then true
414- else throwErr("invalid withdrawal request period")]
415- if ((checks == checks))
416- then {
417- let withdrawal = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyWithdrawal()), wrapErr("invalid total withdrawal amount"))
418- let factoryActions = [invoke(factoryAddressOrFail, "integerEntry", [keyWithdrawal(), if ((withdrawal >= lpAssetAmount))
419- then (withdrawal - lpAssetAmount)
420- else throwErr("invalid withdrawal amount")], nil), invoke(factoryAddressOrFail, "deleteEntry", [keyWithdrawalRequest(userAddress, txId)], nil), invoke(factoryAddressOrFail, "transferAsset", [userAddressBytes, lpAssetAmount, lpAssetIdOrFail], nil)]
421- if ((factoryActions == factoryActions))
422- then $Tuple2(nil, factoryActions)
423- else throw("Strict value is not equal to itself.")
424- }
425- else throw("Strict value is not equal to itself.")
426- }
427- else throw("Strict value is not equal to itself.")
428- }
294+func deleteEntry (key) = if (onlyCalculator(i))
295+ then $Tuple2([DeleteEntry(key)], key)
296+ else $Tuple2(nil, unit)
429297
430298
431299
432300 @Callable(i)
433-func claimWaves (userAddressBytes,txId) = {
434- let checkCaller = onlyFactory(i)
435- if ((checkCaller == checkCaller))
436- then {
437- let userAddress = Address(userAddressBytes)
438- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
439- let withdrawalRequestOption = valueOrErrorMessage(getString(factoryAddressOrFail, keyWithdrawalRequest(userAddress, txId)), wrapErr("invalid withdrawal request"))
440- let $t01527815391 = parseWithdrawalRequestValueOrFail(withdrawalRequestOption)
441- let status = $t01527815391._1
442- let lpAssetAmount = $t01527815391._2
443- let targetPeriod = $t01527815391._3
444- let claimTxId = $t01527815391._4
445- if ((status == FINISHED))
446- then throwErr("invalid withdrawal request status")
447- else if ((targetPeriod > currentPeriodOrFail))
448- then throwErr("invalid withdrawal request period")
449- else {
450- let priceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(targetPeriod)), wrapErr("invalid price"))
451- let amount = if ((priceOrFail > 0))
452- then fraction(lpAssetAmount, priceOrFail, SCALE8)
453- else 0
454- let factoryActions = [invoke(factoryAddressOrFail, "stringEntry", [keyWithdrawalRequest(userAddress, txId), valueWithdrawalRequest(FINISHED, lpAssetAmount, targetPeriod, i.transactionId)], nil), invoke(factoryAddressOrFail, "transferWaves", [userAddressBytes, amount], nil)]
455- $Tuple2(nil, factoryActions)
456- }
457- }
458- else throw("Strict value is not equal to itself.")
459- }
301+func reissue (amount) = if (onlyCalculator(i))
302+ then $Tuple2([Reissue(lpAssetIdOrFail, amount, true)], amount)
303+ else $Tuple2(nil, unit)
460304
461305
462306
463307 @Callable(i)
464-func processBlocks (userAddressBytes) = {
465- let checkCaller = onlyFactory(i)
466- if ((checkCaller == checkCaller))
467- then {
468- let userAddress = Address(userAddressBytes)
469- let currentPeriodOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyCurrentPeriod()), wrapErr("invalid period"))
470- let periodLength = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPeriodLength()), wrapErr("invalid period length"))
471- let currentStartHeight = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyStartHeight(currentPeriodOrFail)), wrapErr("invalid start height"))
472- let currentPriceOrFail = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyPriceForPeriod(currentPeriodOrFail)), wrapErr("invalid price"))
473- let nextBlockToProcess = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyNextBlockToProcess()), wrapErr("invalid next block to process"))
474- let periodEndHeight = ((currentStartHeight + periodLength) - 1)
475- let blocksProcessingBatchSizeMax = 40
476- let blocksProcessingBatchSize = if (if (if ((height >= nextBlockToProcess))
477- then if ((nextBlockToProcess >= currentStartHeight))
478- then true
479- else (currentPeriodOrFail == 0)
480- else false)
481- then (periodEndHeight >= nextBlockToProcess)
482- else false)
483- then min([((periodEndHeight - nextBlockToProcess) + 1), blocksProcessingBatchSizeMax])
484- else throwErr(wrapErr("invalid target block"))
485- let blockProcessingReward = valueOrErrorMessage(getInteger(factoryAddressOrFail, keyBlockProcessingReward()), wrapErr("invalid block processing reward"))
486- let blockProcessingRewardByGenerator = (blockProcessingReward / blocksProcessingBatchSize)
487- let blockProcessingRewardByGeneratorRemainder = (blockProcessingReward - (blockProcessingRewardByGenerator * blocksProcessingBatchSize))
488- func map (acc,inc) = if ((inc >= blocksProcessingBatchSize))
489- then acc
490- else {
491- let targetBlockHeight = (nextBlockToProcess + inc)
492- let targetBlockInfo = valueOrErrorMessage(blockInfoByHeight(targetBlockHeight), wrapErr("invalid block info"))
493- let treasuryRewardOrFail = valueOrErrorMessage(rewardForOption(targetBlockInfo.rewards, proxyTreasuryAddressOrFail), wrapErr(("invalid treasury reward for height " + toString(targetBlockHeight))))
494- let generator = targetBlockInfo.generator
495- let available = valueOrElse(getInteger(factoryAddressOrFail, keyAvailable(generator)), 0)
496- let callerReward = if ((inc == (blocksProcessingBatchSize - 1)))
497- then (blockProcessingRewardByGenerator + blockProcessingRewardByGeneratorRemainder)
498- else blockProcessingRewardByGenerator
499- let lpAssetAmount = if ((currentPriceOrFail > 0))
500- then fraction((treasuryRewardOrFail - callerReward), SCALE8, currentPriceOrFail)
501- else 0
502- let factoryActionsSingle = [invoke(factoryAddressOrFail, "stringEntry", [keyBlockProcessed(targetBlockHeight), makeString([toBase58String(i.transactionId), toString(currentPeriodOrFail), toString(generator), toBase58String(userAddressBytes), toString(treasuryRewardOrFail), toString(callerReward), toString(lpAssetAmount)], SEP)], nil), invoke(factoryAddressOrFail, "integerEntry", [keyAvailable(generator), (available + lpAssetAmount)], nil)]
503- if ((factoryActionsSingle == factoryActionsSingle))
504- then {
505- let $t01962719660 = acc
506- let lpAssetAcc = $t01962719660._1
507- let rewardAcc = $t01962719660._2
508- $Tuple2((lpAssetAcc + lpAssetAmount), (rewardAcc + treasuryRewardOrFail))
509- }
510- else throw("Strict value is not equal to itself.")
511- }
308+func burn (amount) = if (onlyCalculator(i))
309+ then $Tuple2([Burn(lpAssetIdOrFail, amount)], amount)
310+ else $Tuple2(nil, unit)
512311
513- let list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
514- let $t01992720003 = {
515- let $l = list
516- let $s = size($l)
517- let $acc0 = $Tuple2(0, 0)
518- func $f0_1 ($a,$i) = if (($i >= $s))
519- then $a
520- else map($a, $l[$i])
521312
522- func $f0_2 ($a,$i) = if (($i >= $s))
523- then $a
524- else throw("List size exceeds 40")
525313
526- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40)
527- }
528- if (($t01992720003 == $t01992720003))
529- then {
530- let rewardAmountTotal = $t01992720003._2
531- let lpAssetAmountTotal = $t01992720003._1
532- let rewardToMainTreasuryAmount = (rewardAmountTotal - blockProcessingReward)
533- let invested = valueOrElse(getInteger(factoryAddressOrFail, keyInvested(unit)), 0)
534- let actions = [invoke(factoryAddressOrFail, "reissue", [lpAssetAmountTotal], nil), invoke(factoryAddressOrFail, "integerEntry", [keyNextBlockToProcess(), (nextBlockToProcess + blocksProcessingBatchSize)], nil), invoke(factoryAddressOrFail, "transferFromProxyTreasury", [featureTreasuryAddressOrFail.bytes, rewardToMainTreasuryAmount], nil), invoke(factoryAddressOrFail, "transferFromProxyTreasury", [userAddressBytes, blockProcessingReward], nil), invoke(factoryAddressOrFail, "integerEntry", [keyInvested(unit), (invested + rewardToMainTreasuryAmount)], nil)]
535- if ((actions == actions))
536- then $Tuple2(nil, unit)
537- else throw("Strict value is not equal to itself.")
538- }
539- else throw("Strict value is not equal to itself.")
540- }
314+@Callable(i)
315+func transferAsset (recepientBytes,amount,assetId) = if (onlyCalculator(i))
316+ then $Tuple2([ScriptTransfer(Address(recepientBytes), amount, assetId)], amount)
317+ else $Tuple2(nil, unit)
318+
319+
320+
321+@Callable(i)
322+func transferWaves (recepientBytes,amount) = if (onlyCalculator(i))
323+ then $Tuple2([ScriptTransfer(Address(recepientBytes), amount, unit)], amount)
324+ else $Tuple2(nil, unit)
325+
326+
327+
328+@Callable(i)
329+func transferFromProxyTreasury (recipientBytes,rewardsAmount) = if (onlyCalculator(i))
330+ then $Tuple2(nil, invoke(proxyTreasuryAddressOrFail, "transferWaves", [recipientBytes, rewardsAmount], nil))
331+ else $Tuple2(nil, unit)
332+
333+
334+
335+@Callable(i)
336+func finalize (newTreasuryVolumeInWaves,pwrManagersBonusInWaves,treasuryVolumeDiffAllocationCoef) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "finalize", [i.caller.bytes, newTreasuryVolumeInWaves, pwrManagersBonusInWaves, treasuryVolumeDiffAllocationCoef], i.payments))
337+
338+
339+
340+@Callable(i)
341+func claimLP () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "claimLP", [i.caller.bytes], i.payments))
342+
343+
344+
345+@Callable(i)
346+func claimWaves (txIdStr) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "claimWaves", [i.caller.bytes, fromBase58String(txIdStr)], i.payments))
347+
348+
349+
350+@Callable(i)
351+func invest () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "invest", [i.caller.bytes], i.payments))
352+
353+
354+
355+@Callable(i)
356+func withdraw () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "withdraw", [i.caller.bytes], i.payments))
357+
358+
359+
360+@Callable(i)
361+func cancelWithdraw (txIdStr) = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "cancelWithdraw", [i.caller.bytes, fromBase58String(txIdStr)], i.payments))
362+
363+
364+
365+@Callable(i)
366+func processBlocks () = $Tuple2(nil, reentrantInvoke(calculatorAddressOrFail, "processBlocks", [i.caller.bytes], i.payments))
367+
368+
369+
370+@Callable(i)
371+func voteForTxId (txId) = {
372+ let callerAddressString = toBase58String(i.caller.bytes)
373+ let keyPrefix = keyAllowedTxIdVotePrefix(txId)
374+ let result = [StringEntry(keyAllowedTxId(), txId)]
375+ let allowedTxIdOption = getString(this, keyAllowedTxId())
376+ let err = [if ((size(fromBase58String(txId)) == TXID_BYTES_LENGTH))
377+ then true
378+ else throwErr((txId + " is not valid txId")), if (if ((allowedTxIdOption == unit))
379+ then true
380+ else (value(allowedTxIdOption) != txId))
381+ then true
382+ else throwErr((txId + " is already allowed"))]
383+ if ((err == err))
384+ then voteINTERNAL(callerAddressString, keyPrefix, QUORUM, result)
541385 else throw("Strict value is not equal to itself.")
542386 }
543387
544388
545389 @Verifier(tx)
546390 func verify () = {
547- let publicKey = match getManagerPublicKeyOrUnit() {
548- case pub: ByteVector =>
549- pub
391+ let byProposal = match votingResultAddressOption {
392+ case proposalAddress: Address =>
393+ valueOrElse(getBoolean(proposalAddress, keyProposalAllowBroadcast(this, tx.id)), false)
550394 case _ =>
551- tx.senderPublicKey
395+ false
552396 }
553- sigVerify(tx.bodyBytes, tx.proofs[0], publicKey)
397+ let byAdmins = (tx.id == fromBase58String(valueOrElse(getString(this, keyAllowedTxId()), "")))
398+ let byOwner = if ((size(getAdminsList()) >= QUORUM))
399+ then false
400+ else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
401+ if (if (byProposal)
402+ then true
403+ else byAdmins)
404+ then true
405+ else byOwner
554406 }
555407

github/deemru/w8io/3ef1775 
753.94 ms