tx · 6ND9ykKyWKsCGdYNDgBiRGcZXqFvF1bgxVnRjD8mb8zE 3PLY8LKHGeQHLSsC7L28wmb8kg7xyBcunhd: -0.01400000 Waves 2021.11.15 11:04 [2856891] smart account 3PLY8LKHGeQHLSsC7L28wmb8kg7xyBcunhd > SELF 0.00000000 Waves
{ "type": 13, "id": "6ND9ykKyWKsCGdYNDgBiRGcZXqFvF1bgxVnRjD8mb8zE", "fee": 1400000, "feeAssetId": null, "timestamp": 1636963502303, "version": 2, "chainId": 87, "sender": "3PLY8LKHGeQHLSsC7L28wmb8kg7xyBcunhd", "senderPublicKey": "2bn9a9G5PhubvfS6p8sMM6Tzjhq5kGtpdjRvKofouKnF", "proofs": [ "5hvBy8qukbRRFxcW3YAJeqnZTbCLAYe8RjW7f8yLz74ugvo5RADBC3KjfBXd3yfvseW5jycVg4oFuxvaB4UsRXde" ], "script": "base64:AAIFAAAAAAAAACYIAhIAEgMKAQgSBgoEGBgYERIGCgQICAEBEgASAwoBCBIECgIIAQAAACEAAAAACmRlcG9zaXRGZWUAAAAAAAAAA+gAAAAADWNvbnRyb2xsZXJGZWUAAAAAAAAAJxAAAAAAC3BsYXRmb3JtRmVlAAAAAAAAACcQAAAAAAxhZG1pblB1YktleTEBAAAAIOCQyHczaalTfTlcrvLlv0n70L2bvJxGEHtjaHwP5DMaAAAAAAxhZG1pblB1YktleTIBAAAAIOCQyHczaalTfTlcrvLlv0n70L2bvJxGEHtjaHwP5DMaAAAAAAxhZG1pblB1YktleTMBAAAAIOCQyHczaalTfTlcrvLlv0n70L2bvJxGEHtjaHwP5DMaAAAAABRrZXlTaGFyZVRva2Vuc0xvY2tlZAIAAAAaX3RvdGFsX3NoYXJlX3Rva2Vuc19sb2NrZWQAAAAAD2tleUxhc3RJbnRlcmVzdAIAAAAOX2xhc3RfaW50ZXJlc3QAAAAAFWtleUxhc3RJbnRlcmVzdEhlaWdodAIAAAAVX2xhc3RfaW50ZXJlc3RfaGVpZ2h0AAAAABVrZXlSZXdhcmRVcGRhdGVIZWlnaHQCAAAAFHJld2FyZF91cGRhdGVfaGVpZ2h0AAAAABFnb3Zlcm5hbmNlQWRkcmVzcwkBAAAAB0FkZHJlc3MAAAABAQAAABoBV8lXnLdvepYMywgiOQ98homAomzcs7cW7QAAAAAOZmFybWluZ0FkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVc4DeZLRuf+UBcj/qBUTcgH5R4tWRCTmkoAAAAAHGtleVVzZXJTV09QTGFzdENsYWltZWRBbW91bnQCAAAAGV9TV09QX2xhc3RfY2xhaW1lZF9hbW91bnQAAAAAEGtleUF2YWlsYWJsZVNXT1ACAAAAD19hdmFpbGFibGVfU1dPUAAAAAATa2V5VXNlckxhc3RJbnRlcmVzdAIAAAAOX2xhc3RfaW50ZXJlc3QAAAAACWtleVNXT1BpZAIAAAAHU1dPUF9pZAAAAAAYa2V5VXNlclNXT1BDbGFpbWVkQW1vdW50AgAAABRfU1dPUF9jbGFpbWVkX2Ftb3VudAAAAAAda2V5VG90YWxSZXdhcmRQZXJCbG9ja0N1cnJlbnQCAAAAHnRvdGFsX3Jld2FyZF9wZXJfYmxvY2tfY3VycmVudAAAAAAea2V5VG90YWxSZXdhcmRQZXJCbG9ja1ByZXZpb3VzAgAAAB90b3RhbF9yZXdhcmRfcGVyX2Jsb2NrX3ByZXZpb3VzAAAAABxrZXlSZXdhcmRQb29sRnJhY3Rpb25DdXJyZW50AgAAAB1fY3VycmVudF9wb29sX2ZyYWN0aW9uX3Jld2FyZAAAAAAda2V5UmV3YXJkUG9vbEZyYWN0aW9uUHJldmlvdXMCAAAAHl9wcmV2aW91c19wb29sX2ZyYWN0aW9uX3Jld2FyZAAAAAAOdG90YWxWb3RlU2hhcmUAAAAAAlQL5AAAAAAAFWtleUhlaWdodFBvb2xGcmFjdGlvbgIAAAAaX3Bvb2xfcmV3YXJkX3VwZGF0ZV9oZWlnaHQAAAAAGGtleVVzZXJTaGFyZVRva2Vuc0xvY2tlZAIAAAAUX3NoYXJlX3Rva2Vuc19sb2NrZWQAAAAABFNXT1AJAAJZAAAAAQkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAOZmFybWluZ0FkZHJlc3MFAAAACWtleVNXT1BpZAEAAAAYZ2V0VG90YWxTaGFyZVRva2VuTG9ja2VkAAAAAQAAAARwb29sCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAOZmFybWluZ0FkZHJlc3MJAAEsAAAAAgUAAAAEcG9vbAUAAAAUa2V5U2hhcmVUb2tlbnNMb2NrZWQJAAEsAAAAAgkAASwAAAACAgAAABRObyBkYXRhIG9uIHRoZSBrZXk6IAUAAAAEcG9vbAUAAAAUa2V5U2hhcmVUb2tlbnNMb2NrZWQBAAAAD2dldFNoYXJlQXNzZXRJZAAAAAEAAAAEcG9vbAkAAlkAAAABCQEAAAARQGV4dHJOYXRpdmUoMTA1MykAAAACCQEAAAAFdmFsdWUAAAABCQAEJgAAAAEFAAAABHBvb2wCAAAADnNoYXJlX2Fzc2V0X2lkAQAAABNnZXRMYXN0SW50ZXJlc3RJbmZvAAAAAQAAAARwb29sBAAAAAxsYXN0SW50ZXJlc3QJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA5mYXJtaW5nQWRkcmVzcwkAASwAAAACBQAAAARwb29sBQAAAA9rZXlMYXN0SW50ZXJlc3QJAAEsAAAAAgkAASwAAAACAgAAABRObyBkYXRhIG9uIHRoZSBrZXk6IAUAAAAEcG9vbAUAAAAPa2V5TGFzdEludGVyZXN0BAAAABJsYXN0SW50ZXJlc3RIZWlnaHQJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAOZmFybWluZ0FkZHJlc3MJAAEsAAAAAgUAAAAEcG9vbAUAAAAVa2V5TGFzdEludGVyZXN0SGVpZ2h0BQAAAAZoZWlnaHQJAAUUAAAAAgUAAAASbGFzdEludGVyZXN0SGVpZ2h0BQAAAAxsYXN0SW50ZXJlc3QBAAAACnJld2FyZEluZm8AAAABAAAABHBvb2wEAAAAGnRvdGFsUmV3YXJkUGVyQmxvY2tDdXJyZW50CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAARZ292ZXJuYW5jZUFkZHJlc3MFAAAAHWtleVRvdGFsUmV3YXJkUGVyQmxvY2tDdXJyZW50CQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABRObyBkYXRhIG9uIHRoZSBrZXk6IAUAAAAda2V5VG90YWxSZXdhcmRQZXJCbG9ja0N1cnJlbnQCAAAADCBhdCBhZGRyZXNzIAkABCUAAAABBQAAABFnb3Zlcm5hbmNlQWRkcmVzcwQAAAAbdG90YWxSZXdhcmRQZXJCbG9ja1ByZXZpb3VzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAARZ292ZXJuYW5jZUFkZHJlc3MFAAAAHmtleVRvdGFsUmV3YXJkUGVyQmxvY2tQcmV2aW91cwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAUTm8gZGF0YSBvbiB0aGUga2V5OiAFAAAAHmtleVRvdGFsUmV3YXJkUGVyQmxvY2tQcmV2aW91cwIAAAAMIGF0IGFkZHJlc3MgCQAEJQAAAAEFAAAAEWdvdmVybmFuY2VBZGRyZXNzBAAAABlyZXdhcmRQb29sRnJhY3Rpb25DdXJyZW50CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAARZ292ZXJuYW5jZUFkZHJlc3MJAAEsAAAAAgUAAAAEcG9vbAUAAAAca2V5UmV3YXJkUG9vbEZyYWN0aW9uQ3VycmVudAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABRObyBkYXRhIG9uIHRoZSBrZXk6IAUAAAAEcG9vbAUAAAAca2V5UmV3YXJkUG9vbEZyYWN0aW9uQ3VycmVudAIAAAAMIGF0IGFkZHJlc3MgCQAEJQAAAAEFAAAAEWdvdmVybmFuY2VBZGRyZXNzBAAAABJyZXdhcmRVcGRhdGVIZWlnaHQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAABFnb3Zlcm5hbmNlQWRkcmVzcwUAAAAVa2V5UmV3YXJkVXBkYXRlSGVpZ2h0CQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABRObyBkYXRhIG9uIHRoZSBrZXk6IAUAAAAVa2V5UmV3YXJkVXBkYXRlSGVpZ2h0AgAAAAwgYXQgYWRkcmVzcyAJAAQlAAAAAQUAAAARZ292ZXJuYW5jZUFkZHJlc3MEAAAAFnBvb2xSZXdhcmRVcGRhdGVIZWlnaHQJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAARZ292ZXJuYW5jZUFkZHJlc3MJAAEsAAAAAgUAAAAEcG9vbAUAAAAVa2V5SGVpZ2h0UG9vbEZyYWN0aW9uAAAAAAAAAAAABAAAABpyZXdhcmRQb29sRnJhY3Rpb25QcmV2aW91cwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAAEWdvdmVybmFuY2VBZGRyZXNzCQABLAAAAAIFAAAABHBvb2wFAAAAHWtleVJld2FyZFBvb2xGcmFjdGlvblByZXZpb3VzCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAFE5vIGRhdGEgb24gdGhlIGtleTogBQAAAARwb29sBQAAAB1rZXlSZXdhcmRQb29sRnJhY3Rpb25QcmV2aW91cwIAAAAMIGF0IGFkZHJlc3MgCQAEJQAAAAEFAAAAEWdvdmVybmFuY2VBZGRyZXNzBAAAABFyZXdhcmRQb29sQ3VycmVudAkAAGsAAAADBQAAABp0b3RhbFJld2FyZFBlckJsb2NrQ3VycmVudAUAAAAZcmV3YXJkUG9vbEZyYWN0aW9uQ3VycmVudAUAAAAOdG90YWxWb3RlU2hhcmUEAAAAEnJld2FyZFBvb2xQcmV2aW91cwkAAGsAAAADBQAAABt0b3RhbFJld2FyZFBlckJsb2NrUHJldmlvdXMFAAAAGnJld2FyZFBvb2xGcmFjdGlvblByZXZpb3VzBQAAAA50b3RhbFZvdGVTaGFyZQMDCQAAZgAAAAIFAAAAEXJld2FyZFBvb2xDdXJyZW50BQAAABp0b3RhbFJld2FyZFBlckJsb2NrQ3VycmVudAYJAABmAAAAAgUAAAAScmV3YXJkUG9vbFByZXZpb3VzBQAAABt0b3RhbFJld2FyZFBlckJsb2NrUHJldmlvdXMJAAACAAAAAQIAAABicmV3YXJkUG9vbEN1cnJlbnQgPiB0b3RhbFJld2FyZFBlckJsb2NrQ3VycmVudCBvciByZXdhcmRQb29sUHJldmlvdXMgPiB0b3RhbFJld2FyZFBlckJsb2NrUHJldmlvdXMJAAUWAAAABAUAAAARcmV3YXJkUG9vbEN1cnJlbnQFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAUAAAAScmV3YXJkUG9vbFByZXZpb3VzBQAAABZwb29sUmV3YXJkVXBkYXRlSGVpZ2h0AQAAAA5jYWxjU2NhbGVWYWx1ZQAAAAIAAAAIYXNzZXRJZDEAAAAIYXNzZXRJZDIEAAAAEGFzc2V0SWQxRGVjaW1hbHMICQEAAAAFdmFsdWUAAAABCQAD7AAAAAEFAAAACGFzc2V0SWQxAAAACGRlY2ltYWxzBAAAABBhc3NldElkMkRlY2ltYWxzCAkBAAAABXZhbHVlAAAAAQkAA+wAAAABBQAAAAhhc3NldElkMgAAAAhkZWNpbWFscwQAAAALc2NhbGVEaWdpdHMJAABkAAAAAgkAAGUAAAACBQAAABBhc3NldElkMkRlY2ltYWxzBQAAABBhc3NldElkMURlY2ltYWxzAAAAAAAAAAAICQAAbAAAAAYAAAAAAAAAAAoAAAAAAAAAAAAFAAAAC3NjYWxlRGlnaXRzAAAAAAAAAAAAAAAAAAAAAAAABQAAAAZIQUxGVVABAAAAE2dldFVzZXJJbnRlcmVzdEluZm8AAAACAAAABHBvb2wAAAALdXNlckFkZHJlc3MEAAAAEHVzZXJMYXN0SW50ZXJlc3QJAAQaAAAAAgUAAAAOZmFybWluZ0FkZHJlc3MJAAEsAAAAAgkAASwAAAACCQABLAAAAAIFAAAABHBvb2wCAAAAAV8JAAQlAAAAAQUAAAALdXNlckFkZHJlc3MFAAAAE2tleVVzZXJMYXN0SW50ZXJlc3QEAAAACXVzZXJTaGFyZQkABBoAAAACBQAAAA5mYXJtaW5nQWRkcmVzcwkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAEcG9vbAIAAAABXwkABCUAAAABBQAAAAt1c2VyQWRkcmVzcwUAAAAYa2V5VXNlclNoYXJlVG9rZW5zTG9ja2VkBAAAAAxsYXN0SW50ZXJlc3QJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAA5mYXJtaW5nQWRkcmVzcwkAASwAAAACBQAAAARwb29sBQAAAA9rZXlMYXN0SW50ZXJlc3QJAAEsAAAAAgkAASwAAAACAgAAABRObyBkYXRhIG9uIHRoZSBrZXk6IAUAAAAEcG9vbAUAAAAPa2V5TGFzdEludGVyZXN0BAAAABV1c2VyTGFzdEludGVyZXN0VmFsdWUEAAAAByRtYXRjaDAFAAAAEHVzZXJMYXN0SW50ZXJlc3QDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAQdXNlckxhc3RJbnRlcmVzdAUAAAAHJG1hdGNoMAUAAAAQdXNlckxhc3RJbnRlcmVzdAUAAAAMbGFzdEludGVyZXN0BAAAABV1c2VyU2hhcmVUb2tlbnNBbW91bnQEAAAAByRtYXRjaDAFAAAACXVzZXJTaGFyZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAl1c2VyU2hhcmUFAAAAByRtYXRjaDAFAAAACXVzZXJTaGFyZQAAAAAAAAAAAAkABRQAAAACBQAAABV1c2VyTGFzdEludGVyZXN0VmFsdWUFAAAAFXVzZXJTaGFyZVRva2Vuc0Ftb3VudAEAAAAMY2FsY0ludGVyZXN0AAAACgAAABJsYXN0SW50ZXJlc3RIZWlnaHQAAAAScmV3YXJkVXBkYXRlSGVpZ2h0AAAAFnBvb2xSZXdhcmRVcGRhdGVIZWlnaHQAAAAMbGFzdEludGVyZXN0AAAAFWN1cnJlbnRSZXdhcmRQZXJCbG9jawAAABBzaGFyZVRva2VuTG9ja2VkAAAAFnByZXZpb3VzUmV3YXJkUGVyQmxvY2sAAAAMc2hhcmVBc3NldElkAAAACnNjYWxlVmFsdWUAAAAJcG10QW1vdW50AwkAAAAAAAACBQAAABBzaGFyZVRva2VuTG9ja2VkAAAAAAAAAAAAAAAAAAAAAAAAAwkBAAAAAiE9AAAAAgUAAAAWcG9vbFJld2FyZFVwZGF0ZUhlaWdodAAAAAAAAAAAAAMDCQAAZgAAAAIFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAUAAAAGaGVpZ2h0CQAAAAAAAAIFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAUAAAAWcG9vbFJld2FyZFVwZGF0ZUhlaWdodAcEAAAABnJld2FyZAkAAGgAAAACBQAAABZwcmV2aW91c1Jld2FyZFBlckJsb2NrCQAAZQAAAAIFAAAABmhlaWdodAUAAAASbGFzdEludGVyZXN0SGVpZ2h0CQAAZAAAAAIFAAAADGxhc3RJbnRlcmVzdAkAAGsAAAADBQAAAAZyZXdhcmQFAAAACnNjYWxlVmFsdWUFAAAAEHNoYXJlVG9rZW5Mb2NrZWQDAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAkBAAAAAiE9AAAAAgUAAAAScmV3YXJkVXBkYXRlSGVpZ2h0BQAAABZwb29sUmV3YXJkVXBkYXRlSGVpZ2h0BwQAAAAGcmV3YXJkCQAAaAAAAAIFAAAAFnByZXZpb3VzUmV3YXJkUGVyQmxvY2sJAABlAAAAAgUAAAAGaGVpZ2h0BQAAABJsYXN0SW50ZXJlc3RIZWlnaHQJAABkAAAAAgUAAAAMbGFzdEludGVyZXN0CQAAawAAAAMFAAAABnJld2FyZAUAAAAKc2NhbGVWYWx1ZQUAAAAQc2hhcmVUb2tlbkxvY2tlZAMDAwkAAGYAAAACBQAAAAZoZWlnaHQFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAkAAAAAAAACBQAAABJyZXdhcmRVcGRhdGVIZWlnaHQFAAAAFnBvb2xSZXdhcmRVcGRhdGVIZWlnaHQHCQAAZgAAAAIFAAAAEmxhc3RJbnRlcmVzdEhlaWdodAUAAAAScmV3YXJkVXBkYXRlSGVpZ2h0BwQAAAAGcmV3YXJkCQAAaAAAAAIFAAAAFWN1cnJlbnRSZXdhcmRQZXJCbG9jawkAAGUAAAACBQAAAAZoZWlnaHQFAAAAEmxhc3RJbnRlcmVzdEhlaWdodAkAAGQAAAACBQAAAAxsYXN0SW50ZXJlc3QJAABrAAAAAwUAAAAGcmV3YXJkBQAAAApzY2FsZVZhbHVlBQAAABBzaGFyZVRva2VuTG9ja2VkBAAAACpyZXdhcmRBZnRlckxhc3RJbnRlcmVzdEJlZm9yZVJlYXdhcmRVcGRhdGUJAABoAAAAAgUAAAAWcHJldmlvdXNSZXdhcmRQZXJCbG9jawkAAGUAAAACBQAAABJyZXdhcmRVcGRhdGVIZWlnaHQFAAAAEmxhc3RJbnRlcmVzdEhlaWdodAQAAAATaW50ZXJlc3RBZnRlclVwZGF0ZQkAAGQAAAACBQAAAAxsYXN0SW50ZXJlc3QJAABrAAAAAwUAAAAqcmV3YXJkQWZ0ZXJMYXN0SW50ZXJlc3RCZWZvcmVSZWF3YXJkVXBkYXRlBQAAAApzY2FsZVZhbHVlBQAAABBzaGFyZVRva2VuTG9ja2VkBAAAAAZyZXdhcmQJAABoAAAAAgUAAAAVY3VycmVudFJld2FyZFBlckJsb2NrCQAAZQAAAAIFAAAABmhlaWdodAUAAAAScmV3YXJkVXBkYXRlSGVpZ2h0CQAAZAAAAAIFAAAAE2ludGVyZXN0QWZ0ZXJVcGRhdGUJAABrAAAAAwUAAAAGcmV3YXJkBQAAAApzY2FsZVZhbHVlBQAAABBzaGFyZVRva2VuTG9ja2VkAwkAAGYAAAACBQAAABJyZXdhcmRVcGRhdGVIZWlnaHQFAAAABmhlaWdodAQAAAAGcmV3YXJkCQAAaAAAAAIFAAAAFnByZXZpb3VzUmV3YXJkUGVyQmxvY2sJAABlAAAAAgUAAAAGaGVpZ2h0BQAAABJsYXN0SW50ZXJlc3RIZWlnaHQJAABkAAAAAgUAAAAMbGFzdEludGVyZXN0CQAAawAAAAMFAAAABnJld2FyZAUAAAAKc2NhbGVWYWx1ZQUAAAAQc2hhcmVUb2tlbkxvY2tlZAMJAABmAAAAAgUAAAASbGFzdEludGVyZXN0SGVpZ2h0BQAAABJyZXdhcmRVcGRhdGVIZWlnaHQEAAAABnJld2FyZAkAAGgAAAACBQAAABVjdXJyZW50UmV3YXJkUGVyQmxvY2sJAABlAAAAAgUAAAAGaGVpZ2h0BQAAABJsYXN0SW50ZXJlc3RIZWlnaHQJAABkAAAAAgUAAAAMbGFzdEludGVyZXN0CQAAawAAAAMFAAAABnJld2FyZAUAAAAKc2NhbGVWYWx1ZQUAAAAQc2hhcmVUb2tlbkxvY2tlZAQAAAAqcmV3YXJkQWZ0ZXJMYXN0SW50ZXJlc3RCZWZvcmVSZWF3YXJkVXBkYXRlCQAAaAAAAAIFAAAAFnByZXZpb3VzUmV3YXJkUGVyQmxvY2sJAABlAAAAAgUAAAAScmV3YXJkVXBkYXRlSGVpZ2h0BQAAABJsYXN0SW50ZXJlc3RIZWlnaHQEAAAAE2ludGVyZXN0QWZ0ZXJVcGRhdGUJAABkAAAAAgUAAAAMbGFzdEludGVyZXN0CQAAawAAAAMFAAAAKnJld2FyZEFmdGVyTGFzdEludGVyZXN0QmVmb3JlUmVhd2FyZFVwZGF0ZQUAAAAKc2NhbGVWYWx1ZQUAAAAQc2hhcmVUb2tlbkxvY2tlZAQAAAAGcmV3YXJkCQAAaAAAAAIFAAAAFWN1cnJlbnRSZXdhcmRQZXJCbG9jawkAAGUAAAACBQAAAAZoZWlnaHQFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAkAAGQAAAACBQAAABNpbnRlcmVzdEFmdGVyVXBkYXRlCQAAawAAAAMFAAAABnJld2FyZAUAAAAKc2NhbGVWYWx1ZQUAAAAQc2hhcmVUb2tlbkxvY2tlZAEAAAAJY2xhaW1DYWxjAAAAAwAAAARwb29sAAAABmNhbGxlcgAAAAlwbXRBbW91bnQEAAAADHNoYXJlQXNzZXRJZAkBAAAAD2dldFNoYXJlQXNzZXRJZAAAAAEFAAAABHBvb2wEAAAACnNjYWxlVmFsdWUJAQAAAA5jYWxjU2NhbGVWYWx1ZQAAAAIFAAAABFNXT1AFAAAADHNoYXJlQXNzZXRJZAQAAAAQc2hhcmVUb2tlbkxvY2tlZAkBAAAAGGdldFRvdGFsU2hhcmVUb2tlbkxvY2tlZAAAAAEFAAAABHBvb2wEAAAACyR0MDg2Njg4NzMzCQEAAAATZ2V0TGFzdEludGVyZXN0SW5mbwAAAAEFAAAABHBvb2wEAAAAEmxhc3RJbnRlcmVzdEhlaWdodAgFAAAACyR0MDg2Njg4NzMzAAAAAl8xBAAAAAxsYXN0SW50ZXJlc3QIBQAAAAskdDA4NjY4ODczMwAAAAJfMgQAAAALJHQwODczODg4NTAJAQAAAApyZXdhcmRJbmZvAAAAAQUAAAAEcG9vbAQAAAAVY3VycmVudFJld2FyZFBlckJsb2NrCAUAAAALJHQwODczODg4NTAAAAACXzEEAAAAEnJld2FyZFVwZGF0ZUhlaWdodAgFAAAACyR0MDg3Mzg4ODUwAAAAAl8yBAAAABZwcmV2aW91c1Jld2FyZFBlckJsb2NrCAUAAAALJHQwODczODg4NTAAAAACXzMEAAAAFnBvb2xSZXdhcmRVcGRhdGVIZWlnaHQIBQAAAAskdDA4NzM4ODg1MAAAAAJfNAQAAAALJHQwODg1NTg5MzQJAQAAABNnZXRVc2VySW50ZXJlc3RJbmZvAAAAAgUAAAAEcG9vbAUAAAAGY2FsbGVyBAAAABB1c2VyTGFzdEludGVyZXN0CAUAAAALJHQwODg1NTg5MzQAAAACXzEEAAAAFXVzZXJTaGFyZVRva2Vuc0Ftb3VudAgFAAAACyR0MDg4NTU4OTM0AAAAAl8yBAAAAA9jdXJyZW50SW50ZXJlc3QJAQAAAAxjYWxjSW50ZXJlc3QAAAAKBQAAABJsYXN0SW50ZXJlc3RIZWlnaHQFAAAAEnJld2FyZFVwZGF0ZUhlaWdodAUAAAAWcG9vbFJld2FyZFVwZGF0ZUhlaWdodAUAAAAMbGFzdEludGVyZXN0BQAAABVjdXJyZW50UmV3YXJkUGVyQmxvY2sFAAAAEHNoYXJlVG9rZW5Mb2NrZWQFAAAAFnByZXZpb3VzUmV3YXJkUGVyQmxvY2sFAAAADHNoYXJlQXNzZXRJZAUAAAAKc2NhbGVWYWx1ZQUAAAAJcG10QW1vdW50BAAAAAtjbGFpbUFtb3VudAkAAGsAAAADBQAAABV1c2VyU2hhcmVUb2tlbnNBbW91bnQJAABlAAAAAgUAAAAPY3VycmVudEludGVyZXN0BQAAABB1c2VyTGFzdEludGVyZXN0BQAAAApzY2FsZVZhbHVlBAAAAA91c2VyTmV3SW50ZXJlc3QFAAAAD2N1cnJlbnRJbnRlcmVzdAkABRYAAAAEBQAAAA91c2VyTmV3SW50ZXJlc3QFAAAAD2N1cnJlbnRJbnRlcmVzdAUAAAALY2xhaW1BbW91bnQFAAAAFXVzZXJTaGFyZVRva2Vuc0Ftb3VudAAAAAcAAAACYTgBAAAABGluaXQAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAADEzUFBIN3g3aXFvYlc1eml5aVJDaWMxOXJRcUtyNm5QWWFLMV9hc3NldF9iYWxhbmNlAAAAAAAAbdStBQAAAANuaWwAAAABaQEAAAAFY2xhaW0AAAABAAAABHBvb2wEAAAADXNoYXJlVG9rZW5zSWQJAAJZAAAAAQkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgkBAAAABXZhbHVlAAAAAQkABCYAAAABBQAAAARwb29sAgAAAA5zaGFyZV9hc3NldF9pZAQAAAAQc2hhcmVUb2tlbkxvY2tlZAkBAAAAGGdldFRvdGFsU2hhcmVUb2tlbkxvY2tlZAAAAAEFAAAABHBvb2wEAAAADSR0MDEwMjk0MTAzNTkJAQAAABNnZXRMYXN0SW50ZXJlc3RJbmZvAAAAAQUAAAAEcG9vbAQAAAASbGFzdEludGVyZXN0SGVpZ2h0CAUAAAANJHQwMTAyOTQxMDM1OQAAAAJfMQQAAAAMbGFzdEludGVyZXN0CAUAAAANJHQwMTAyOTQxMDM1OQAAAAJfMgQAAAANJHQwMTAzNjQxMDQ3NgkBAAAACnJld2FyZEluZm8AAAABBQAAAARwb29sBAAAABVjdXJyZW50UmV3YXJkUGVyQmxvY2sIBQAAAA0kdDAxMDM2NDEwNDc2AAAAAl8xBAAAABJyZXdhcmRVcGRhdGVIZWlnaHQIBQAAAA0kdDAxMDM2NDEwNDc2AAAAAl8yBAAAABZwcmV2aW91c1Jld2FyZFBlckJsb2NrCAUAAAANJHQwMTAzNjQxMDQ3NgAAAAJfMwQAAAAWcG9vbFJld2FyZFVwZGF0ZUhlaWdodAgFAAAADSR0MDEwMzY0MTA0NzYAAAACXzQEAAAADSR0MDEwNDgxMTA1ODEJAQAAAAljbGFpbUNhbGMAAAADBQAAAARwb29sCAUAAAABaQAAAAZjYWxsZXIAAAAAAAAAAAEEAAAAD3VzZXJOZXdJbnRlcmVzdAgFAAAADSR0MDEwNDgxMTA1ODEAAAACXzEEAAAAD2N1cnJlbnRJbnRlcmVzdAgFAAAADSR0MDEwNDgxMTA1ODEAAAACXzIEAAAAC2NsYWltQW1vdW50CAUAAAANJHQwMTA0ODExMDU4MQAAAAJfMwQAAAAVdXNlclNoYXJlVG9rZW5zQW1vdW50CAUAAAANJHQwMTA0ODExMDU4MQAAAAJfNAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAEcG9vbAIAAAABXwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIFAAAAE2tleVVzZXJMYXN0SW50ZXJlc3QFAAAAD3VzZXJOZXdJbnRlcmVzdAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACBQAAAARwb29sBQAAAA9rZXlMYXN0SW50ZXJlc3QFAAAAD2N1cnJlbnRJbnRlcmVzdAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACBQAAAARwb29sBQAAABVrZXlMYXN0SW50ZXJlc3RIZWlnaHQFAAAABmhlaWdodAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAEcG9vbAIAAAABXwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIFAAAAEGtleUF2YWlsYWJsZVNXT1AFAAAAC2NsYWltQW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACBQAAAARwb29sAgAAAAFfCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgUAAAAca2V5VXNlclNXT1BMYXN0Q2xhaW1lZEFtb3VudAUAAAALY2xhaW1BbW91bnQFAAAAA25pbAAAAAFpAQAAAAhhZGRQb29scwAAAAQAAAAFcG9vbHMAAAAPbGlxdWlkaXR5VG9rZW5zAAAADXNlcnZpY2VUb2tlbnMAAAAWbGlxdWlkaXR5VG9rZW5EZWNpbWFscwMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACCQAETAAAAAIFAAAADGFkbWluUHViS2V5MQkABEwAAAACBQAAAAxhZG1pblB1YktleTIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkzBQAAAANuaWwIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQoBAAAAEGdlbmVyYXRlUG9vbEtleXMAAAACAAAAC2FjY3VtdWxhdGVkAAAABHBvb2wJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgUAAAAEcG9vbAIAAAAOX2Fzc2V0X2JhbGFuY2UAAAAAAAAAAAAFAAAAC2FjY3VtdWxhdGVkCgEAAAAeZ2VuZXJhdGVQb29sTGlxdWlkaXR5VG9rZW5LZXlzAAAAAgAAAAthY2N1bXVsYXRlZAAAAARwb29sBAAAAAlwb29sSW5kZXgJAQAAAAV2YWx1ZQAAAAEJAARPAAAAAgUAAAAFcG9vbHMFAAAABHBvb2wEAAAADmxpcXVpZGl0eVRva2VuCQABkQAAAAIFAAAAD2xpcXVpZGl0eVRva2VucwUAAAAJcG9vbEluZGV4CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAAEsAAAAAgUAAAAEcG9vbAIAAAAQX2xpcXVpZGl0eV90b2tlbgUAAAAObGlxdWlkaXR5VG9rZW4FAAAAC2FjY3VtdWxhdGVkCgEAAAAcZ2VuZXJhdGVQb29sU2VydmljZVRva2VuS2V5cwAAAAIAAAALYWNjdW11bGF0ZWQAAAAEcG9vbAQAAAAJcG9vbEluZGV4CQEAAAAFdmFsdWUAAAABCQAETwAAAAIFAAAABXBvb2xzBQAAAARwb29sBAAAAA5saXF1aWRpdHlUb2tlbgkAAZEAAAACBQAAAA1zZXJ2aWNlVG9rZW5zBQAAAAlwb29sSW5kZXgJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkAASwAAAACBQAAAARwb29sAgAAAA5fc2VydmljZV90b2tlbgUAAAAObGlxdWlkaXR5VG9rZW4FAAAAC2FjY3VtdWxhdGVkCgEAAAAlZ2VuZXJhdGVQb29sTGlxdWlkaXR5VG9rZW5EZWNpbWFsS2V5cwAAAAIAAAALYWNjdW11bGF0ZWQAAAAEcG9vbAQAAAAJcG9vbEluZGV4CQEAAAAFdmFsdWUAAAABCQAETwAAAAIFAAAABXBvb2xzBQAAAARwb29sBAAAAA5saXF1aWRp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MAAAAAAAAAAAAAQAAAAVbGlxdWlkdXR5QXNzZXRBZGRyZXNzCQEAAAARQGV4dHJOYXRpdmUoMTA1MykAAAACBQAAAAR0aGlzCQABLAAAAAIFAAAABHBvb2wCAAAAEF9saXF1aWRpdHlfdG9rZW4EAAAAFWxpcXVpZGl0eVRva2VuRGVjaW1hbAQAAAAHJG1hdGNoMAkAA+wAAAABCQACWQAAAAEFAAAAFWxpcXVpZHV0eUFzc2V0QWRkcmVzcwMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAFQXNzZXQEAAAABWFzc2V0BQAAAAckbWF0Y2gwCAUAAAAFYXNzZXQAAAAIZGVjaW1hbHMJAAACAAAAAQIAAAAQQ2FuJ3QgZmluZCBhc3NldAQAAAAPdXNlckVhcm5lZFRvdGFsCQAAZAAAAAIFAAAACnVzZXJFYXJuZWQFAAAAEHVzZXJFYXJuZWRCZWZvcmUEAAAAEGFtb3VudFdpdGhvdXRGZWUJAABlAAAAAgkAAGUAAAACBQAAAAZhbW91bnQJAQAAAAhmcmFjdGlvbgAAAAQFAAAABmFtb3VudAAAAAAAAAAAAQUAAAALcGxhdGZvcm1GZWUFAAAABkhBTEZVUAkBAAAACGZyYWN0aW9uAAAABAUAAAAGYW1vdW50AAAAAAAAAAABBQAAAA1jb250cm9sbGVyRmVlBQAAAAZIQUxGVVAEAAAADW5ld1Bvb2xBbW91bnQJAABlAAAAAgUAAAAKcG9vbEFtb3VudAUAAAAQYW1vdW50V2l0aG91dEZlZQMJAABnAAAAAgUAAAAKdXNlckFtb3VudAUAAAAGYW1vdW50BAAAABFuZXdVc2VyUG9vbEFtb3VudAkAAGUAAAACBQAAAAp1c2VyQW1vdW50BQAAABBhbW91bnRXaXRob3V0RmVlCQAETAAAAAIJAQAAAARCdXJuAAAAAgkAAlkAAAABBQAAABBkQXBwQXNzZXRBZGRyZXNzBQAAABBhbW91bnRXaXRob3V0RmVlCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAQYW1vdW50V2l0aG91dEZlZQkAAlkAAAABBQAAABVsaXF1aWR1dHlBc3NldEFkZHJlc3MJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADXBvb2xBbW91bnRLZXkFAAAADW5ld1Bvb2xBbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEXVzZXJQb29sQW1vdW50S2V5BQAAABFuZXdVc2VyUG9vbEFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARdXNlclBvb2xFYXJuZWRLZXkFAAAAD3VzZXJFYXJuZWRUb3RhbAUAAAADbmlsCQAAAgAAAAECAAAAJllvdSBoYXZlIG5vdCBzdWNoIGJhbGFuY2UgZm9yIHdpdGhkcmF3AAAAAQAAAAJiNgEAAAACYjcAAAAACQAB9AAAAAMIBQAAAAJiNgAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAmI2AAAABnByb29mcwAAAAAAAAAAAAgFAAAAAmI2AAAAD3NlbmRlclB1YmxpY0tlecswq50=", "height": 2856891, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: Dth4buRvFQSXeeJV6uaP7LSsoy2b7e6ccPsmxfueh3Hj Next: E2nwQ5EN3ak81NyP44Vdq9FwhR4hUUtWdGWotPJHM91 Diff:
Old | New | Differences | |
---|---|---|---|
7 | 7 | ||
8 | 8 | let platformFee = 10000 | |
9 | 9 | ||
10 | - | let adminPubKey1 = base58' | |
10 | + | let adminPubKey1 = base58'G7cNXePvAHUHmZfXa1eHnvFeH6DuykPC5wm9v9djTKgD' | |
11 | 11 | ||
12 | - | let adminPubKey2 = base58' | |
12 | + | let adminPubKey2 = base58'G7cNXePvAHUHmZfXa1eHnvFeH6DuykPC5wm9v9djTKgD' | |
13 | 13 | ||
14 | - | let adminPubKey3 = base58'68Po1k24uP6goKr7RDmXPg4QkMiKuyTMEirao14rif8s' | |
14 | + | let adminPubKey3 = base58'G7cNXePvAHUHmZfXa1eHnvFeH6DuykPC5wm9v9djTKgD' | |
15 | + | ||
16 | + | let keyShareTokensLocked = "_total_share_tokens_locked" | |
17 | + | ||
18 | + | let keyLastInterest = "_last_interest" | |
19 | + | ||
20 | + | let keyLastInterestHeight = "_last_interest_height" | |
21 | + | ||
22 | + | let keyRewardUpdateHeight = "reward_update_height" | |
23 | + | ||
24 | + | let governanceAddress = Address(base58'3PLHVWCqA9DJPDbadUofTohnCULLauiDWhS') | |
25 | + | ||
26 | + | let farmingAddress = Address(base58'3P73HDkPqG15nLXevjCbmXtazHYTZbpPoPw') | |
27 | + | ||
28 | + | let keyUserSWOPLastClaimedAmount = "_SWOP_last_claimed_amount" | |
29 | + | ||
30 | + | let keyAvailableSWOP = "_available_SWOP" | |
31 | + | ||
32 | + | let keyUserLastInterest = "_last_interest" | |
33 | + | ||
34 | + | let keySWOPid = "SWOP_id" | |
35 | + | ||
36 | + | let keyUserSWOPClaimedAmount = "_SWOP_claimed_amount" | |
37 | + | ||
38 | + | let keyTotalRewardPerBlockCurrent = "total_reward_per_block_current" | |
39 | + | ||
40 | + | let keyTotalRewardPerBlockPrevious = "total_reward_per_block_previous" | |
41 | + | ||
42 | + | let keyRewardPoolFractionCurrent = "_current_pool_fraction_reward" | |
43 | + | ||
44 | + | let keyRewardPoolFractionPrevious = "_previous_pool_fraction_reward" | |
45 | + | ||
46 | + | let totalVoteShare = 10000000000 | |
47 | + | ||
48 | + | let keyHeightPoolFraction = "_pool_reward_update_height" | |
49 | + | ||
50 | + | let keyUserShareTokensLocked = "_share_tokens_locked" | |
51 | + | ||
52 | + | let SWOP = fromBase58String(getStringValue(farmingAddress, keySWOPid)) | |
53 | + | ||
54 | + | func getTotalShareTokenLocked (pool) = valueOrErrorMessage(getInteger(farmingAddress, (pool + keyShareTokensLocked)), (("No data on the key: " + pool) + keyShareTokensLocked)) | |
55 | + | ||
56 | + | ||
57 | + | func getShareAssetId (pool) = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id")) | |
58 | + | ||
59 | + | ||
60 | + | func getLastInterestInfo (pool) = { | |
61 | + | let lastInterest = valueOrErrorMessage(getInteger(farmingAddress, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest)) | |
62 | + | let lastInterestHeight = valueOrElse(getInteger(farmingAddress, (pool + keyLastInterestHeight)), height) | |
63 | + | $Tuple2(lastInterestHeight, lastInterest) | |
64 | + | } | |
65 | + | ||
66 | + | ||
67 | + | func rewardInfo (pool) = { | |
68 | + | let totalRewardPerBlockCurrent = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockCurrent), ((("No data on the key: " + keyTotalRewardPerBlockCurrent) + " at address ") + toString(governanceAddress))) | |
69 | + | let totalRewardPerBlockPrevious = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockPrevious), ((("No data on the key: " + keyTotalRewardPerBlockPrevious) + " at address ") + toString(governanceAddress))) | |
70 | + | let rewardPoolFractionCurrent = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionCurrent)), (((("No data on the key: " + pool) + keyRewardPoolFractionCurrent) + " at address ") + toString(governanceAddress))) | |
71 | + | let rewardUpdateHeight = valueOrErrorMessage(getInteger(governanceAddress, keyRewardUpdateHeight), ((("No data on the key: " + keyRewardUpdateHeight) + " at address ") + toString(governanceAddress))) | |
72 | + | let poolRewardUpdateHeight = valueOrElse(getInteger(governanceAddress, (pool + keyHeightPoolFraction)), 0) | |
73 | + | let rewardPoolFractionPrevious = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionPrevious)), (((("No data on the key: " + pool) + keyRewardPoolFractionPrevious) + " at address ") + toString(governanceAddress))) | |
74 | + | let rewardPoolCurrent = fraction(totalRewardPerBlockCurrent, rewardPoolFractionCurrent, totalVoteShare) | |
75 | + | let rewardPoolPrevious = fraction(totalRewardPerBlockPrevious, rewardPoolFractionPrevious, totalVoteShare) | |
76 | + | if (if ((rewardPoolCurrent > totalRewardPerBlockCurrent)) | |
77 | + | then true | |
78 | + | else (rewardPoolPrevious > totalRewardPerBlockPrevious)) | |
79 | + | then throw("rewardPoolCurrent > totalRewardPerBlockCurrent or rewardPoolPrevious > totalRewardPerBlockPrevious") | |
80 | + | else $Tuple4(rewardPoolCurrent, rewardUpdateHeight, rewardPoolPrevious, poolRewardUpdateHeight) | |
81 | + | } | |
82 | + | ||
83 | + | ||
84 | + | func calcScaleValue (assetId1,assetId2) = { | |
85 | + | let assetId1Decimals = value(assetInfo(assetId1)).decimals | |
86 | + | let assetId2Decimals = value(assetInfo(assetId2)).decimals | |
87 | + | let scaleDigits = ((assetId2Decimals - assetId1Decimals) + 8) | |
88 | + | pow(10, 0, scaleDigits, 0, 0, HALFUP) | |
89 | + | } | |
90 | + | ||
91 | + | ||
92 | + | func getUserInterestInfo (pool,userAddress) = { | |
93 | + | let userLastInterest = getInteger(farmingAddress, (((pool + "_") + toString(userAddress)) + keyUserLastInterest)) | |
94 | + | let userShare = getInteger(farmingAddress, (((pool + "_") + toString(userAddress)) + keyUserShareTokensLocked)) | |
95 | + | let lastInterest = valueOrErrorMessage(getInteger(farmingAddress, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest)) | |
96 | + | let userLastInterestValue = match userLastInterest { | |
97 | + | case userLastInterest: Int => | |
98 | + | userLastInterest | |
99 | + | case _ => | |
100 | + | lastInterest | |
101 | + | } | |
102 | + | let userShareTokensAmount = match userShare { | |
103 | + | case userShare: Int => | |
104 | + | userShare | |
105 | + | case _ => | |
106 | + | 0 | |
107 | + | } | |
108 | + | $Tuple2(userLastInterestValue, userShareTokensAmount) | |
109 | + | } | |
110 | + | ||
111 | + | ||
112 | + | func calcInterest (lastInterestHeight,rewardUpdateHeight,poolRewardUpdateHeight,lastInterest,currentRewardPerBlock,shareTokenLocked,previousRewardPerBlock,shareAssetId,scaleValue,pmtAmount) = if ((shareTokenLocked == 0)) | |
113 | + | then 0 | |
114 | + | else if ((poolRewardUpdateHeight != 0)) | |
115 | + | then if (if ((rewardUpdateHeight > height)) | |
116 | + | then (rewardUpdateHeight == poolRewardUpdateHeight) | |
117 | + | else false) | |
118 | + | then { | |
119 | + | let reward = (previousRewardPerBlock * (height - lastInterestHeight)) | |
120 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
121 | + | } | |
122 | + | else if (if ((height > rewardUpdateHeight)) | |
123 | + | then (rewardUpdateHeight != poolRewardUpdateHeight) | |
124 | + | else false) | |
125 | + | then { | |
126 | + | let reward = (previousRewardPerBlock * (height - lastInterestHeight)) | |
127 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
128 | + | } | |
129 | + | else if (if (if ((height > rewardUpdateHeight)) | |
130 | + | then (rewardUpdateHeight == poolRewardUpdateHeight) | |
131 | + | else false) | |
132 | + | then (lastInterestHeight > rewardUpdateHeight) | |
133 | + | else false) | |
134 | + | then { | |
135 | + | let reward = (currentRewardPerBlock * (height - lastInterestHeight)) | |
136 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
137 | + | } | |
138 | + | else { | |
139 | + | let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight)) | |
140 | + | let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked)) | |
141 | + | let reward = (currentRewardPerBlock * (height - rewardUpdateHeight)) | |
142 | + | (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked)) | |
143 | + | } | |
144 | + | else if ((rewardUpdateHeight > height)) | |
145 | + | then { | |
146 | + | let reward = (previousRewardPerBlock * (height - lastInterestHeight)) | |
147 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
148 | + | } | |
149 | + | else if ((lastInterestHeight > rewardUpdateHeight)) | |
150 | + | then { | |
151 | + | let reward = (currentRewardPerBlock * (height - lastInterestHeight)) | |
152 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
153 | + | } | |
154 | + | else { | |
155 | + | let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight)) | |
156 | + | let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked)) | |
157 | + | let reward = (currentRewardPerBlock * (height - rewardUpdateHeight)) | |
158 | + | (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked)) | |
159 | + | } | |
160 | + | ||
161 | + | ||
162 | + | func claimCalc (pool,caller,pmtAmount) = { | |
163 | + | let shareAssetId = getShareAssetId(pool) | |
164 | + | let scaleValue = calcScaleValue(SWOP, shareAssetId) | |
165 | + | let shareTokenLocked = getTotalShareTokenLocked(pool) | |
166 | + | let $t086688733 = getLastInterestInfo(pool) | |
167 | + | let lastInterestHeight = $t086688733._1 | |
168 | + | let lastInterest = $t086688733._2 | |
169 | + | let $t087388850 = rewardInfo(pool) | |
170 | + | let currentRewardPerBlock = $t087388850._1 | |
171 | + | let rewardUpdateHeight = $t087388850._2 | |
172 | + | let previousRewardPerBlock = $t087388850._3 | |
173 | + | let poolRewardUpdateHeight = $t087388850._4 | |
174 | + | let $t088558934 = getUserInterestInfo(pool, caller) | |
175 | + | let userLastInterest = $t088558934._1 | |
176 | + | let userShareTokensAmount = $t088558934._2 | |
177 | + | let currentInterest = calcInterest(lastInterestHeight, rewardUpdateHeight, poolRewardUpdateHeight, lastInterest, currentRewardPerBlock, shareTokenLocked, previousRewardPerBlock, shareAssetId, scaleValue, pmtAmount) | |
178 | + | let claimAmount = fraction(userShareTokensAmount, (currentInterest - userLastInterest), scaleValue) | |
179 | + | let userNewInterest = currentInterest | |
180 | + | $Tuple4(userNewInterest, currentInterest, claimAmount, userShareTokensAmount) | |
181 | + | } | |
182 | + | ||
183 | + | ||
184 | + | @Callable(a8) | |
185 | + | func init () = [IntegerEntry("3PPH7x7iqobW5ziyiRCic19rQqKr6nPYaK1_asset_balance", 7197869)] | |
186 | + | ||
187 | + | ||
188 | + | ||
189 | + | @Callable(i) | |
190 | + | func claim (pool) = { | |
191 | + | let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id")) | |
192 | + | let shareTokenLocked = getTotalShareTokenLocked(pool) | |
193 | + | let $t01029410359 = getLastInterestInfo(pool) | |
194 | + | let lastInterestHeight = $t01029410359._1 | |
195 | + | let lastInterest = $t01029410359._2 | |
196 | + | let $t01036410476 = rewardInfo(pool) | |
197 | + | let currentRewardPerBlock = $t01036410476._1 | |
198 | + | let rewardUpdateHeight = $t01036410476._2 | |
199 | + | let previousRewardPerBlock = $t01036410476._3 | |
200 | + | let poolRewardUpdateHeight = $t01036410476._4 | |
201 | + | let $t01048110581 = claimCalc(pool, i.caller, 1) | |
202 | + | let userNewInterest = $t01048110581._1 | |
203 | + | let currentInterest = $t01048110581._2 | |
204 | + | let claimAmount = $t01048110581._3 | |
205 | + | let userShareTokensAmount = $t01048110581._4 | |
206 | + | [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), claimAmount), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount)] | |
207 | + | } | |
208 | + | ||
209 | + | ||
15 | 210 | ||
16 | 211 | @Callable(i) | |
17 | 212 | func addPools (pools,liquidityTokens,serviceTokens,liquidityTokenDecimals) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)) | |
123 | 318 | ||
124 | 319 | @Callable(a8) | |
125 | 320 | func call () = { | |
126 | - | let pmtAmountA = 10 | |
127 | - | let pmtAmountB = 1 | |
128 | - | let pmtDecimalsA = 8 | |
129 | - | let pmtDecimalsB = 6 | |
130 | - | let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2) | |
131 | - | let a9 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN) | |
132 | - | let a10 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN) | |
133 | - | let third = pow(10, 0, shareDecimals, 0, 0, DOWN) | |
134 | - | let fouth = fraction(a9, a10, third) | |
135 | - | [IntegerEntry("fisrt", a9), IntegerEntry("second", a10), IntegerEntry("third", third), IntegerEntry("fouth", fouth)] | |
321 | + | let a9 = Issue("Asset107112021", "Asset from dApp 1", 100000, 2, true, unit, 0) | |
322 | + | let a10 = Issue("Asset207112021", "Asset from dApp 2", 100000, 2, true, unit, 0) | |
323 | + | [a10, a9] | |
136 | 324 | } | |
137 | 325 | ||
138 | 326 | ||
139 | 327 | ||
140 | 328 | @Callable(i) | |
141 | - | func deposit (pool) = if ((size(i.payments) != 1)) | |
142 | - | then throw("One attached payment expected") | |
143 | - | else { | |
144 | - | let amount = i.payments[0].amount | |
145 | - | let assetId = i.payments[0].assetId | |
146 | - | let assetIdString = match assetId { | |
147 | - | case id: ByteVector => | |
148 | - | toBase58String(id) | |
149 | - | case _ => | |
150 | - | throw("Match error") | |
151 | - | } | |
152 | - | if ((0 >= amount)) | |
153 | - | then throw(("Deposit amount must be positive. Actual: " + toString(amount))) | |
154 | - | else { | |
155 | - | let poolAmountKey = (pool + "_asset_balance") | |
156 | - | let userAddress = toString(i.caller) | |
157 | - | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
158 | - | let liquidutyAssetAddress = match getString((pool + "_liquidity_token")) { | |
159 | - | case string: String => | |
160 | - | string | |
161 | - | case nothing => | |
162 | - | throw("You try to deposit on unsupported pool") | |
163 | - | } | |
164 | - | let liquidityTokenDecimal = match assetInfo(fromBase58String(liquidutyAssetAddress)) { | |
165 | - | case asset: Asset => | |
166 | - | asset.decimals | |
167 | - | case _ => | |
168 | - | throw("Can't find asset") | |
169 | - | } | |
170 | - | if ((liquidutyAssetAddress != assetIdString)) | |
171 | - | then throw("You attached wrong liquidity token from Swop.fi") | |
172 | - | else { | |
173 | - | let poolAmount = getIntegerValue(this, poolAmountKey) | |
174 | - | let userAmount = match getInteger(userPoolAmountKey) { | |
175 | - | case int: Int => | |
176 | - | int | |
177 | - | case nothing => | |
178 | - | 0 | |
179 | - | } | |
180 | - | let newPoolAmount = (poolAmount + amount) | |
181 | - | let userAmountWithoutFee = ((amount - fraction(amount, 1, depositFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
182 | - | let newUserPoolAmount = (userAmount + userAmountWithoutFee) | |
183 | - | [IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount)] | |
184 | - | } | |
185 | - | } | |
186 | - | } | |
329 | + | func deposit (pool) = { | |
330 | + | let amount = i.payments[0].amount | |
331 | + | let assetId = i.payments[0].assetId | |
332 | + | let poolAmountKey = (pool + "_asset_balance") | |
333 | + | let userAddress = toString(i.caller) | |
334 | + | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
335 | + | let dAppAssetAddress = match getString((pool + "_service_token")) { | |
336 | + | case string: String => | |
337 | + | string | |
338 | + | case nothing => | |
339 | + | throw("You try to exchange on unsupported pool") | |
340 | + | } | |
341 | + | let poolAmount = getIntegerValue(this, poolAmountKey) | |
342 | + | let userAmount = match getInteger(userPoolAmountKey) { | |
343 | + | case int: Int => | |
344 | + | int | |
345 | + | case nothing => | |
346 | + | 0 | |
347 | + | } | |
348 | + | let newPoolAmount = (poolAmount + amount) | |
349 | + | let userAmountWithoutFee = ((amount - fraction(amount, 1, depositFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
350 | + | let newUserPoolAmount = (userAmount + userAmountWithoutFee) | |
351 | + | [Reissue(fromBase58String(dAppAssetAddress), userAmountWithoutFee, true), ScriptTransfer(i.caller, userAmountWithoutFee, fromBase58String(dAppAssetAddress)), IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount)] | |
352 | + | } | |
187 | 353 | ||
188 | 354 | ||
189 | 355 | ||
190 | 356 | @Callable(i) | |
191 | - | func withdraw (pool,amount) = if ((0 >= amount)) | |
192 | - | then throw(("Deposit amount must be positive. Actual: " + toString(amount))) | |
193 | - | else { | |
194 | - | let poolAmountKey = (pool + "_asset_balance") | |
195 | - | let userAddress = toString(i.caller) | |
196 | - | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
197 | - | let liquidutyAssetAddress = match getString((pool + "_liquidity_token")) { | |
198 | - | case string: String => | |
199 | - | string | |
200 | - | case nothing => | |
201 | - | throw("You try to withdraw from unsupported pool") | |
202 | - | } | |
203 | - | let poolAmount = getIntegerValue(this, poolAmountKey) | |
204 | - | let userAmount = match getInteger(userPoolAmountKey) { | |
205 | - | case int: Int => | |
206 | - | int | |
207 | - | case nothing => | |
208 | - | 0 | |
209 | - | } | |
210 | - | let amountWithoutFee = ((amount - fraction(amount, 1, platformFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
211 | - | let newPoolAmount = (poolAmount - amountWithoutFee) | |
212 | - | if ((userAmount >= amount)) | |
213 | - | then { | |
214 | - | let newUserPoolAmount = (userAmount - amount) | |
215 | - | [ScriptTransfer(i.caller, amountWithoutFee, fromBase58String(liquidutyAssetAddress)), IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount)] | |
216 | - | } | |
217 | - | else throw("You have not such balance for withdraw") | |
218 | - | } | |
357 | + | func withdraw (pool,userEarned) = { | |
358 | + | let amount = i.payments[0].amount | |
359 | + | let assetId = i.payments[0].assetId | |
360 | + | if ((size(i.payments) != 1)) | |
361 | + | then throw("One attached payment expected") | |
362 | + | else { | |
363 | + | let poolAmountKey = (pool + "_asset_balance") | |
364 | + | let userAddress = toString(i.caller) | |
365 | + | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
366 | + | let userPoolEarnedKey = (((pool + "_") + userAddress) + "_earned") | |
367 | + | let dAppAssetAddress = match getString((pool + "_service_token")) { | |
368 | + | case string: String => | |
369 | + | string | |
370 | + | case nothing => | |
371 | + | throw("You try to exchange on unsupported pool") | |
372 | + | } | |
373 | + | let poolAmount = getIntegerValue(this, poolAmountKey) | |
374 | + | let userAmount = match getInteger(userPoolAmountKey) { | |
375 | + | case int: Int => | |
376 | + | int | |
377 | + | case nothing => | |
378 | + | 0 | |
379 | + | } | |
380 | + | let userEarnedBefore = match getInteger(userPoolEarnedKey) { | |
381 | + | case int: Int => | |
382 | + | int | |
383 | + | case nothing => | |
384 | + | 0 | |
385 | + | } | |
386 | + | let liquidutyAssetAddress = getStringValue(this, (pool + "_liquidity_token")) | |
387 | + | let liquidityTokenDecimal = match assetInfo(fromBase58String(liquidutyAssetAddress)) { | |
388 | + | case asset: Asset => | |
389 | + | asset.decimals | |
390 | + | case _ => | |
391 | + | throw("Can't find asset") | |
392 | + | } | |
393 | + | let userEarnedTotal = (userEarned + userEarnedBefore) | |
394 | + | let amountWithoutFee = ((amount - fraction(amount, 1, platformFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
395 | + | let newPoolAmount = (poolAmount - amountWithoutFee) | |
396 | + | if ((userAmount >= amount)) | |
397 | + | then { | |
398 | + | let newUserPoolAmount = (userAmount - amountWithoutFee) | |
399 | + | [Burn(fromBase58String(dAppAssetAddress), amountWithoutFee), ScriptTransfer(i.caller, amountWithoutFee, fromBase58String(liquidutyAssetAddress)), IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount), IntegerEntry(userPoolEarnedKey, userEarnedTotal)] | |
400 | + | } | |
401 | + | else throw("You have not such balance for withdraw") | |
402 | + | } | |
403 | + | } | |
219 | 404 | ||
220 | 405 | ||
221 | 406 | @Verifier(b6) |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let depositFee = 1000 | |
5 | 5 | ||
6 | 6 | let controllerFee = 10000 | |
7 | 7 | ||
8 | 8 | let platformFee = 10000 | |
9 | 9 | ||
10 | - | let adminPubKey1 = base58' | |
10 | + | let adminPubKey1 = base58'G7cNXePvAHUHmZfXa1eHnvFeH6DuykPC5wm9v9djTKgD' | |
11 | 11 | ||
12 | - | let adminPubKey2 = base58' | |
12 | + | let adminPubKey2 = base58'G7cNXePvAHUHmZfXa1eHnvFeH6DuykPC5wm9v9djTKgD' | |
13 | 13 | ||
14 | - | let adminPubKey3 = base58'68Po1k24uP6goKr7RDmXPg4QkMiKuyTMEirao14rif8s' | |
14 | + | let adminPubKey3 = base58'G7cNXePvAHUHmZfXa1eHnvFeH6DuykPC5wm9v9djTKgD' | |
15 | + | ||
16 | + | let keyShareTokensLocked = "_total_share_tokens_locked" | |
17 | + | ||
18 | + | let keyLastInterest = "_last_interest" | |
19 | + | ||
20 | + | let keyLastInterestHeight = "_last_interest_height" | |
21 | + | ||
22 | + | let keyRewardUpdateHeight = "reward_update_height" | |
23 | + | ||
24 | + | let governanceAddress = Address(base58'3PLHVWCqA9DJPDbadUofTohnCULLauiDWhS') | |
25 | + | ||
26 | + | let farmingAddress = Address(base58'3P73HDkPqG15nLXevjCbmXtazHYTZbpPoPw') | |
27 | + | ||
28 | + | let keyUserSWOPLastClaimedAmount = "_SWOP_last_claimed_amount" | |
29 | + | ||
30 | + | let keyAvailableSWOP = "_available_SWOP" | |
31 | + | ||
32 | + | let keyUserLastInterest = "_last_interest" | |
33 | + | ||
34 | + | let keySWOPid = "SWOP_id" | |
35 | + | ||
36 | + | let keyUserSWOPClaimedAmount = "_SWOP_claimed_amount" | |
37 | + | ||
38 | + | let keyTotalRewardPerBlockCurrent = "total_reward_per_block_current" | |
39 | + | ||
40 | + | let keyTotalRewardPerBlockPrevious = "total_reward_per_block_previous" | |
41 | + | ||
42 | + | let keyRewardPoolFractionCurrent = "_current_pool_fraction_reward" | |
43 | + | ||
44 | + | let keyRewardPoolFractionPrevious = "_previous_pool_fraction_reward" | |
45 | + | ||
46 | + | let totalVoteShare = 10000000000 | |
47 | + | ||
48 | + | let keyHeightPoolFraction = "_pool_reward_update_height" | |
49 | + | ||
50 | + | let keyUserShareTokensLocked = "_share_tokens_locked" | |
51 | + | ||
52 | + | let SWOP = fromBase58String(getStringValue(farmingAddress, keySWOPid)) | |
53 | + | ||
54 | + | func getTotalShareTokenLocked (pool) = valueOrErrorMessage(getInteger(farmingAddress, (pool + keyShareTokensLocked)), (("No data on the key: " + pool) + keyShareTokensLocked)) | |
55 | + | ||
56 | + | ||
57 | + | func getShareAssetId (pool) = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id")) | |
58 | + | ||
59 | + | ||
60 | + | func getLastInterestInfo (pool) = { | |
61 | + | let lastInterest = valueOrErrorMessage(getInteger(farmingAddress, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest)) | |
62 | + | let lastInterestHeight = valueOrElse(getInteger(farmingAddress, (pool + keyLastInterestHeight)), height) | |
63 | + | $Tuple2(lastInterestHeight, lastInterest) | |
64 | + | } | |
65 | + | ||
66 | + | ||
67 | + | func rewardInfo (pool) = { | |
68 | + | let totalRewardPerBlockCurrent = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockCurrent), ((("No data on the key: " + keyTotalRewardPerBlockCurrent) + " at address ") + toString(governanceAddress))) | |
69 | + | let totalRewardPerBlockPrevious = valueOrErrorMessage(getInteger(governanceAddress, keyTotalRewardPerBlockPrevious), ((("No data on the key: " + keyTotalRewardPerBlockPrevious) + " at address ") + toString(governanceAddress))) | |
70 | + | let rewardPoolFractionCurrent = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionCurrent)), (((("No data on the key: " + pool) + keyRewardPoolFractionCurrent) + " at address ") + toString(governanceAddress))) | |
71 | + | let rewardUpdateHeight = valueOrErrorMessage(getInteger(governanceAddress, keyRewardUpdateHeight), ((("No data on the key: " + keyRewardUpdateHeight) + " at address ") + toString(governanceAddress))) | |
72 | + | let poolRewardUpdateHeight = valueOrElse(getInteger(governanceAddress, (pool + keyHeightPoolFraction)), 0) | |
73 | + | let rewardPoolFractionPrevious = valueOrErrorMessage(getInteger(governanceAddress, (pool + keyRewardPoolFractionPrevious)), (((("No data on the key: " + pool) + keyRewardPoolFractionPrevious) + " at address ") + toString(governanceAddress))) | |
74 | + | let rewardPoolCurrent = fraction(totalRewardPerBlockCurrent, rewardPoolFractionCurrent, totalVoteShare) | |
75 | + | let rewardPoolPrevious = fraction(totalRewardPerBlockPrevious, rewardPoolFractionPrevious, totalVoteShare) | |
76 | + | if (if ((rewardPoolCurrent > totalRewardPerBlockCurrent)) | |
77 | + | then true | |
78 | + | else (rewardPoolPrevious > totalRewardPerBlockPrevious)) | |
79 | + | then throw("rewardPoolCurrent > totalRewardPerBlockCurrent or rewardPoolPrevious > totalRewardPerBlockPrevious") | |
80 | + | else $Tuple4(rewardPoolCurrent, rewardUpdateHeight, rewardPoolPrevious, poolRewardUpdateHeight) | |
81 | + | } | |
82 | + | ||
83 | + | ||
84 | + | func calcScaleValue (assetId1,assetId2) = { | |
85 | + | let assetId1Decimals = value(assetInfo(assetId1)).decimals | |
86 | + | let assetId2Decimals = value(assetInfo(assetId2)).decimals | |
87 | + | let scaleDigits = ((assetId2Decimals - assetId1Decimals) + 8) | |
88 | + | pow(10, 0, scaleDigits, 0, 0, HALFUP) | |
89 | + | } | |
90 | + | ||
91 | + | ||
92 | + | func getUserInterestInfo (pool,userAddress) = { | |
93 | + | let userLastInterest = getInteger(farmingAddress, (((pool + "_") + toString(userAddress)) + keyUserLastInterest)) | |
94 | + | let userShare = getInteger(farmingAddress, (((pool + "_") + toString(userAddress)) + keyUserShareTokensLocked)) | |
95 | + | let lastInterest = valueOrErrorMessage(getInteger(farmingAddress, (pool + keyLastInterest)), (("No data on the key: " + pool) + keyLastInterest)) | |
96 | + | let userLastInterestValue = match userLastInterest { | |
97 | + | case userLastInterest: Int => | |
98 | + | userLastInterest | |
99 | + | case _ => | |
100 | + | lastInterest | |
101 | + | } | |
102 | + | let userShareTokensAmount = match userShare { | |
103 | + | case userShare: Int => | |
104 | + | userShare | |
105 | + | case _ => | |
106 | + | 0 | |
107 | + | } | |
108 | + | $Tuple2(userLastInterestValue, userShareTokensAmount) | |
109 | + | } | |
110 | + | ||
111 | + | ||
112 | + | func calcInterest (lastInterestHeight,rewardUpdateHeight,poolRewardUpdateHeight,lastInterest,currentRewardPerBlock,shareTokenLocked,previousRewardPerBlock,shareAssetId,scaleValue,pmtAmount) = if ((shareTokenLocked == 0)) | |
113 | + | then 0 | |
114 | + | else if ((poolRewardUpdateHeight != 0)) | |
115 | + | then if (if ((rewardUpdateHeight > height)) | |
116 | + | then (rewardUpdateHeight == poolRewardUpdateHeight) | |
117 | + | else false) | |
118 | + | then { | |
119 | + | let reward = (previousRewardPerBlock * (height - lastInterestHeight)) | |
120 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
121 | + | } | |
122 | + | else if (if ((height > rewardUpdateHeight)) | |
123 | + | then (rewardUpdateHeight != poolRewardUpdateHeight) | |
124 | + | else false) | |
125 | + | then { | |
126 | + | let reward = (previousRewardPerBlock * (height - lastInterestHeight)) | |
127 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
128 | + | } | |
129 | + | else if (if (if ((height > rewardUpdateHeight)) | |
130 | + | then (rewardUpdateHeight == poolRewardUpdateHeight) | |
131 | + | else false) | |
132 | + | then (lastInterestHeight > rewardUpdateHeight) | |
133 | + | else false) | |
134 | + | then { | |
135 | + | let reward = (currentRewardPerBlock * (height - lastInterestHeight)) | |
136 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
137 | + | } | |
138 | + | else { | |
139 | + | let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight)) | |
140 | + | let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked)) | |
141 | + | let reward = (currentRewardPerBlock * (height - rewardUpdateHeight)) | |
142 | + | (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked)) | |
143 | + | } | |
144 | + | else if ((rewardUpdateHeight > height)) | |
145 | + | then { | |
146 | + | let reward = (previousRewardPerBlock * (height - lastInterestHeight)) | |
147 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
148 | + | } | |
149 | + | else if ((lastInterestHeight > rewardUpdateHeight)) | |
150 | + | then { | |
151 | + | let reward = (currentRewardPerBlock * (height - lastInterestHeight)) | |
152 | + | (lastInterest + fraction(reward, scaleValue, shareTokenLocked)) | |
153 | + | } | |
154 | + | else { | |
155 | + | let rewardAfterLastInterestBeforeReawardUpdate = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight)) | |
156 | + | let interestAfterUpdate = (lastInterest + fraction(rewardAfterLastInterestBeforeReawardUpdate, scaleValue, shareTokenLocked)) | |
157 | + | let reward = (currentRewardPerBlock * (height - rewardUpdateHeight)) | |
158 | + | (interestAfterUpdate + fraction(reward, scaleValue, shareTokenLocked)) | |
159 | + | } | |
160 | + | ||
161 | + | ||
162 | + | func claimCalc (pool,caller,pmtAmount) = { | |
163 | + | let shareAssetId = getShareAssetId(pool) | |
164 | + | let scaleValue = calcScaleValue(SWOP, shareAssetId) | |
165 | + | let shareTokenLocked = getTotalShareTokenLocked(pool) | |
166 | + | let $t086688733 = getLastInterestInfo(pool) | |
167 | + | let lastInterestHeight = $t086688733._1 | |
168 | + | let lastInterest = $t086688733._2 | |
169 | + | let $t087388850 = rewardInfo(pool) | |
170 | + | let currentRewardPerBlock = $t087388850._1 | |
171 | + | let rewardUpdateHeight = $t087388850._2 | |
172 | + | let previousRewardPerBlock = $t087388850._3 | |
173 | + | let poolRewardUpdateHeight = $t087388850._4 | |
174 | + | let $t088558934 = getUserInterestInfo(pool, caller) | |
175 | + | let userLastInterest = $t088558934._1 | |
176 | + | let userShareTokensAmount = $t088558934._2 | |
177 | + | let currentInterest = calcInterest(lastInterestHeight, rewardUpdateHeight, poolRewardUpdateHeight, lastInterest, currentRewardPerBlock, shareTokenLocked, previousRewardPerBlock, shareAssetId, scaleValue, pmtAmount) | |
178 | + | let claimAmount = fraction(userShareTokensAmount, (currentInterest - userLastInterest), scaleValue) | |
179 | + | let userNewInterest = currentInterest | |
180 | + | $Tuple4(userNewInterest, currentInterest, claimAmount, userShareTokensAmount) | |
181 | + | } | |
182 | + | ||
183 | + | ||
184 | + | @Callable(a8) | |
185 | + | func init () = [IntegerEntry("3PPH7x7iqobW5ziyiRCic19rQqKr6nPYaK1_asset_balance", 7197869)] | |
186 | + | ||
187 | + | ||
188 | + | ||
189 | + | @Callable(i) | |
190 | + | func claim (pool) = { | |
191 | + | let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id")) | |
192 | + | let shareTokenLocked = getTotalShareTokenLocked(pool) | |
193 | + | let $t01029410359 = getLastInterestInfo(pool) | |
194 | + | let lastInterestHeight = $t01029410359._1 | |
195 | + | let lastInterest = $t01029410359._2 | |
196 | + | let $t01036410476 = rewardInfo(pool) | |
197 | + | let currentRewardPerBlock = $t01036410476._1 | |
198 | + | let rewardUpdateHeight = $t01036410476._2 | |
199 | + | let previousRewardPerBlock = $t01036410476._3 | |
200 | + | let poolRewardUpdateHeight = $t01036410476._4 | |
201 | + | let $t01048110581 = claimCalc(pool, i.caller, 1) | |
202 | + | let userNewInterest = $t01048110581._1 | |
203 | + | let currentInterest = $t01048110581._2 | |
204 | + | let claimAmount = $t01048110581._3 | |
205 | + | let userShareTokensAmount = $t01048110581._4 | |
206 | + | [IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserLastInterest), userNewInterest), IntegerEntry((pool + keyLastInterest), currentInterest), IntegerEntry((pool + keyLastInterestHeight), height), IntegerEntry((((pool + "_") + toString(i.caller)) + keyAvailableSWOP), claimAmount), IntegerEntry((((pool + "_") + toString(i.caller)) + keyUserSWOPLastClaimedAmount), claimAmount)] | |
207 | + | } | |
208 | + | ||
209 | + | ||
15 | 210 | ||
16 | 211 | @Callable(i) | |
17 | 212 | func addPools (pools,liquidityTokens,serviceTokens,liquidityTokenDecimals) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)) | |
18 | 213 | then { | |
19 | 214 | func generatePoolKeys (accumulated,pool) = IntegerEntry((pool + "_asset_balance"), 0) :: accumulated | |
20 | 215 | ||
21 | 216 | func generatePoolLiquidityTokenKeys (accumulated,pool) = { | |
22 | 217 | let poolIndex = value(indexOf(pools, pool)) | |
23 | 218 | let liquidityToken = liquidityTokens[poolIndex] | |
24 | 219 | StringEntry((pool + "_liquidity_token"), liquidityToken) :: accumulated | |
25 | 220 | } | |
26 | 221 | ||
27 | 222 | func generatePoolServiceTokenKeys (accumulated,pool) = { | |
28 | 223 | let poolIndex = value(indexOf(pools, pool)) | |
29 | 224 | let liquidityToken = serviceTokens[poolIndex] | |
30 | 225 | StringEntry((pool + "_service_token"), liquidityToken) :: accumulated | |
31 | 226 | } | |
32 | 227 | ||
33 | 228 | func generatePoolLiquidityTokenDecimalKeys (accumulated,pool) = { | |
34 | 229 | let poolIndex = value(indexOf(pools, pool)) | |
35 | 230 | let liquidityToken = liquidityTokenDecimals[poolIndex] | |
36 | 231 | IntegerEntry((pool + "_service_token"), liquidityToken) :: accumulated | |
37 | 232 | } | |
38 | 233 | ||
39 | 234 | func generatePoolActiveKeys (accumulated,pool) = BooleanEntry((pool + "_active"), true) :: accumulated | |
40 | 235 | ||
41 | 236 | let poolBalanceKeys = { | |
42 | 237 | let $l = pools | |
43 | 238 | let $s = size($l) | |
44 | 239 | let $acc0 = nil | |
45 | 240 | func 1 ($a,$i) = if (($i >= $s)) | |
46 | 241 | then $a | |
47 | 242 | else generatePoolKeys($a, $l[$i]) | |
48 | 243 | ||
49 | 244 | func 2 ($a,$i) = if (($i >= $s)) | |
50 | 245 | then $a | |
51 | 246 | else throw("List size exceeds 20") | |
52 | 247 | ||
53 | 248 | 2(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20) | |
54 | 249 | } | |
55 | 250 | let poolLiquidityTokenKeys = { | |
56 | 251 | let $l = pools | |
57 | 252 | let $s = size($l) | |
58 | 253 | let $acc0 = nil | |
59 | 254 | func 1 ($a,$i) = if (($i >= $s)) | |
60 | 255 | then $a | |
61 | 256 | else generatePoolLiquidityTokenKeys($a, $l[$i]) | |
62 | 257 | ||
63 | 258 | func 2 ($a,$i) = if (($i >= $s)) | |
64 | 259 | then $a | |
65 | 260 | else throw("List size exceeds 20") | |
66 | 261 | ||
67 | 262 | 2(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20) | |
68 | 263 | } | |
69 | 264 | let poolServiceTokenKeys = { | |
70 | 265 | let $l = pools | |
71 | 266 | let $s = size($l) | |
72 | 267 | let $acc0 = nil | |
73 | 268 | func 1 ($a,$i) = if (($i >= $s)) | |
74 | 269 | then $a | |
75 | 270 | else generatePoolServiceTokenKeys($a, $l[$i]) | |
76 | 271 | ||
77 | 272 | func 2 ($a,$i) = if (($i >= $s)) | |
78 | 273 | then $a | |
79 | 274 | else throw("List size exceeds 20") | |
80 | 275 | ||
81 | 276 | 2(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20) | |
82 | 277 | } | |
83 | 278 | let poolLiquidityTokenDecimalKeys = { | |
84 | 279 | let $l = pools | |
85 | 280 | let $s = size($l) | |
86 | 281 | let $acc0 = nil | |
87 | 282 | func 1 ($a,$i) = if (($i >= $s)) | |
88 | 283 | then $a | |
89 | 284 | else generatePoolLiquidityTokenDecimalKeys($a, $l[$i]) | |
90 | 285 | ||
91 | 286 | func 2 ($a,$i) = if (($i >= $s)) | |
92 | 287 | then $a | |
93 | 288 | else throw("List size exceeds 20") | |
94 | 289 | ||
95 | 290 | 2(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20) | |
96 | 291 | } | |
97 | 292 | let poolActiveKeys = { | |
98 | 293 | let $l = pools | |
99 | 294 | let $s = size($l) | |
100 | 295 | let $acc0 = nil | |
101 | 296 | func 1 ($a,$i) = if (($i >= $s)) | |
102 | 297 | then $a | |
103 | 298 | else generatePoolActiveKeys($a, $l[$i]) | |
104 | 299 | ||
105 | 300 | func 2 ($a,$i) = if (($i >= $s)) | |
106 | 301 | then $a | |
107 | 302 | else throw("List size exceeds 20") | |
108 | 303 | ||
109 | 304 | 2(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1(1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20) | |
110 | 305 | } | |
111 | 306 | ((((poolBalanceKeys ++ poolLiquidityTokenKeys) ++ poolServiceTokenKeys) ++ poolLiquidityTokenDecimalKeys) ++ poolActiveKeys) | |
112 | 307 | } | |
113 | 308 | else throw("Only admin can call this function") | |
114 | 309 | ||
115 | 310 | ||
116 | 311 | ||
117 | 312 | @Callable(i) | |
118 | 313 | func issueToken (name,description,quantity,decimals) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey)) | |
119 | 314 | then [Issue(name, description, quantity, decimals, true, unit, 0)] | |
120 | 315 | else throw("Only admin can call this function") | |
121 | 316 | ||
122 | 317 | ||
123 | 318 | ||
124 | 319 | @Callable(a8) | |
125 | 320 | func call () = { | |
126 | - | let pmtAmountA = 10 | |
127 | - | let pmtAmountB = 1 | |
128 | - | let pmtDecimalsA = 8 | |
129 | - | let pmtDecimalsB = 6 | |
130 | - | let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2) | |
131 | - | let a9 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN) | |
132 | - | let a10 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN) | |
133 | - | let third = pow(10, 0, shareDecimals, 0, 0, DOWN) | |
134 | - | let fouth = fraction(a9, a10, third) | |
135 | - | [IntegerEntry("fisrt", a9), IntegerEntry("second", a10), IntegerEntry("third", third), IntegerEntry("fouth", fouth)] | |
321 | + | let a9 = Issue("Asset107112021", "Asset from dApp 1", 100000, 2, true, unit, 0) | |
322 | + | let a10 = Issue("Asset207112021", "Asset from dApp 2", 100000, 2, true, unit, 0) | |
323 | + | [a10, a9] | |
136 | 324 | } | |
137 | 325 | ||
138 | 326 | ||
139 | 327 | ||
140 | 328 | @Callable(i) | |
141 | - | func deposit (pool) = if ((size(i.payments) != 1)) | |
142 | - | then throw("One attached payment expected") | |
143 | - | else { | |
144 | - | let amount = i.payments[0].amount | |
145 | - | let assetId = i.payments[0].assetId | |
146 | - | let assetIdString = match assetId { | |
147 | - | case id: ByteVector => | |
148 | - | toBase58String(id) | |
149 | - | case _ => | |
150 | - | throw("Match error") | |
151 | - | } | |
152 | - | if ((0 >= amount)) | |
153 | - | then throw(("Deposit amount must be positive. Actual: " + toString(amount))) | |
154 | - | else { | |
155 | - | let poolAmountKey = (pool + "_asset_balance") | |
156 | - | let userAddress = toString(i.caller) | |
157 | - | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
158 | - | let liquidutyAssetAddress = match getString((pool + "_liquidity_token")) { | |
159 | - | case string: String => | |
160 | - | string | |
161 | - | case nothing => | |
162 | - | throw("You try to deposit on unsupported pool") | |
163 | - | } | |
164 | - | let liquidityTokenDecimal = match assetInfo(fromBase58String(liquidutyAssetAddress)) { | |
165 | - | case asset: Asset => | |
166 | - | asset.decimals | |
167 | - | case _ => | |
168 | - | throw("Can't find asset") | |
169 | - | } | |
170 | - | if ((liquidutyAssetAddress != assetIdString)) | |
171 | - | then throw("You attached wrong liquidity token from Swop.fi") | |
172 | - | else { | |
173 | - | let poolAmount = getIntegerValue(this, poolAmountKey) | |
174 | - | let userAmount = match getInteger(userPoolAmountKey) { | |
175 | - | case int: Int => | |
176 | - | int | |
177 | - | case nothing => | |
178 | - | 0 | |
179 | - | } | |
180 | - | let newPoolAmount = (poolAmount + amount) | |
181 | - | let userAmountWithoutFee = ((amount - fraction(amount, 1, depositFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
182 | - | let newUserPoolAmount = (userAmount + userAmountWithoutFee) | |
183 | - | [IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount)] | |
184 | - | } | |
185 | - | } | |
186 | - | } | |
329 | + | func deposit (pool) = { | |
330 | + | let amount = i.payments[0].amount | |
331 | + | let assetId = i.payments[0].assetId | |
332 | + | let poolAmountKey = (pool + "_asset_balance") | |
333 | + | let userAddress = toString(i.caller) | |
334 | + | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
335 | + | let dAppAssetAddress = match getString((pool + "_service_token")) { | |
336 | + | case string: String => | |
337 | + | string | |
338 | + | case nothing => | |
339 | + | throw("You try to exchange on unsupported pool") | |
340 | + | } | |
341 | + | let poolAmount = getIntegerValue(this, poolAmountKey) | |
342 | + | let userAmount = match getInteger(userPoolAmountKey) { | |
343 | + | case int: Int => | |
344 | + | int | |
345 | + | case nothing => | |
346 | + | 0 | |
347 | + | } | |
348 | + | let newPoolAmount = (poolAmount + amount) | |
349 | + | let userAmountWithoutFee = ((amount - fraction(amount, 1, depositFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
350 | + | let newUserPoolAmount = (userAmount + userAmountWithoutFee) | |
351 | + | [Reissue(fromBase58String(dAppAssetAddress), userAmountWithoutFee, true), ScriptTransfer(i.caller, userAmountWithoutFee, fromBase58String(dAppAssetAddress)), IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount)] | |
352 | + | } | |
187 | 353 | ||
188 | 354 | ||
189 | 355 | ||
190 | 356 | @Callable(i) | |
191 | - | func withdraw (pool,amount) = if ((0 >= amount)) | |
192 | - | then throw(("Deposit amount must be positive. Actual: " + toString(amount))) | |
193 | - | else { | |
194 | - | let poolAmountKey = (pool + "_asset_balance") | |
195 | - | let userAddress = toString(i.caller) | |
196 | - | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
197 | - | let liquidutyAssetAddress = match getString((pool + "_liquidity_token")) { | |
198 | - | case string: String => | |
199 | - | string | |
200 | - | case nothing => | |
201 | - | throw("You try to withdraw from unsupported pool") | |
202 | - | } | |
203 | - | let poolAmount = getIntegerValue(this, poolAmountKey) | |
204 | - | let userAmount = match getInteger(userPoolAmountKey) { | |
205 | - | case int: Int => | |
206 | - | int | |
207 | - | case nothing => | |
208 | - | 0 | |
209 | - | } | |
210 | - | let amountWithoutFee = ((amount - fraction(amount, 1, platformFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
211 | - | let newPoolAmount = (poolAmount - amountWithoutFee) | |
212 | - | if ((userAmount >= amount)) | |
213 | - | then { | |
214 | - | let newUserPoolAmount = (userAmount - amount) | |
215 | - | [ScriptTransfer(i.caller, amountWithoutFee, fromBase58String(liquidutyAssetAddress)), IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount)] | |
216 | - | } | |
217 | - | else throw("You have not such balance for withdraw") | |
218 | - | } | |
357 | + | func withdraw (pool,userEarned) = { | |
358 | + | let amount = i.payments[0].amount | |
359 | + | let assetId = i.payments[0].assetId | |
360 | + | if ((size(i.payments) != 1)) | |
361 | + | then throw("One attached payment expected") | |
362 | + | else { | |
363 | + | let poolAmountKey = (pool + "_asset_balance") | |
364 | + | let userAddress = toString(i.caller) | |
365 | + | let userPoolAmountKey = (((pool + "_") + userAddress) + "_asset_balance") | |
366 | + | let userPoolEarnedKey = (((pool + "_") + userAddress) + "_earned") | |
367 | + | let dAppAssetAddress = match getString((pool + "_service_token")) { | |
368 | + | case string: String => | |
369 | + | string | |
370 | + | case nothing => | |
371 | + | throw("You try to exchange on unsupported pool") | |
372 | + | } | |
373 | + | let poolAmount = getIntegerValue(this, poolAmountKey) | |
374 | + | let userAmount = match getInteger(userPoolAmountKey) { | |
375 | + | case int: Int => | |
376 | + | int | |
377 | + | case nothing => | |
378 | + | 0 | |
379 | + | } | |
380 | + | let userEarnedBefore = match getInteger(userPoolEarnedKey) { | |
381 | + | case int: Int => | |
382 | + | int | |
383 | + | case nothing => | |
384 | + | 0 | |
385 | + | } | |
386 | + | let liquidutyAssetAddress = getStringValue(this, (pool + "_liquidity_token")) | |
387 | + | let liquidityTokenDecimal = match assetInfo(fromBase58String(liquidutyAssetAddress)) { | |
388 | + | case asset: Asset => | |
389 | + | asset.decimals | |
390 | + | case _ => | |
391 | + | throw("Can't find asset") | |
392 | + | } | |
393 | + | let userEarnedTotal = (userEarned + userEarnedBefore) | |
394 | + | let amountWithoutFee = ((amount - fraction(amount, 1, platformFee, HALFUP)) - fraction(amount, 1, controllerFee, HALFUP)) | |
395 | + | let newPoolAmount = (poolAmount - amountWithoutFee) | |
396 | + | if ((userAmount >= amount)) | |
397 | + | then { | |
398 | + | let newUserPoolAmount = (userAmount - amountWithoutFee) | |
399 | + | [Burn(fromBase58String(dAppAssetAddress), amountWithoutFee), ScriptTransfer(i.caller, amountWithoutFee, fromBase58String(liquidutyAssetAddress)), IntegerEntry(poolAmountKey, newPoolAmount), IntegerEntry(userPoolAmountKey, newUserPoolAmount), IntegerEntry(userPoolEarnedKey, userEarnedTotal)] | |
400 | + | } | |
401 | + | else throw("You have not such balance for withdraw") | |
402 | + | } | |
403 | + | } | |
219 | 404 | ||
220 | 405 | ||
221 | 406 | @Verifier(b6) | |
222 | 407 | func b7 () = sigVerify(b6.bodyBytes, b6.proofs[0], b6.senderPublicKey) | |
223 | 408 |
github/deemru/w8io/3ef1775 68.41 ms ◑