tx · FsB89Pp8n6eSv2e2e2TKbPvR7MhkiF46SfS7yh7Tycor 3N74cvawpTtuuCbAasBo7oMJYrohgZYFCTj: -0.01400000 Waves 2021.11.18 17:36 [1796609] smart account 3N74cvawpTtuuCbAasBo7oMJYrohgZYFCTj > SELF 0.00000000 Waves
{ "type": 13, "id": "FsB89Pp8n6eSv2e2e2TKbPvR7MhkiF46SfS7yh7Tycor", "fee": 1400000, "feeAssetId": null, "timestamp": 1637246246540, "version": 1, "sender": "3N74cvawpTtuuCbAasBo7oMJYrohgZYFCTj", "senderPublicKey": "BgnyKECwUvFW1ThWpgKbmHMmJXJRgg5K56jKHZwVMbXL", "proofs": [ "2TbpkHGaMtfQQBerDha3eFjvs2zvwHuQKBLXuHWBGznVyMywwmsTDYnCm5euQvjMpa96EzSNg7JTAf2xYowqL2UG" ], "script": "base64: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AAAABAUAAAAHYWN0aW9ucwgFAAAAAXIAAAACXzEIBQAAAAFyAAAAAl8yCAUAAAABcgAAAAJfMwkAAAIAAAABAgAAABdJbmNvcnJlY3QgaW52b2tlIHJlc3VsdAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAAAAFWNoZWNrTGFzdFBhcnRPZlBlcmlvZAAAAAYAAAAQYm9vc3RpbmdDb250cmFjdAAAAA1jdXJyZW50UGVyaW9kAAAADGxhdGVzdFBlcmlvZAAAAAVkZXB0aAAAAA50b3RhbFdlaWdodEtleQAAAAZ3ZWlnaHQDCQAAZwAAAAIFAAAADGxhdGVzdFBlcmlvZAkAAGQAAAACBQAAAA1jdXJyZW50UGVyaW9kAAAAAAAAAAABCQEAAAANaW52b2tlUHJvY2VzcwAAAAYFAAAAEGJvb3N0aW5nQ29udHJhY3QJAABkAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQAAAAAAAAAAAAkAAGUAAAACBQAAAAVkZXB0aAAAAAAAAAAAAQAAAAAAAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAOdG90YWxXZWlnaHRLZXkFAAAABndlaWdodAUAAAADbmlsCQAFFgAAAAQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAADnRvdGFsV2VpZ2h0S2V5BQAAAAZ3ZWlnaHQFAAAAA25pbAkAAGQAAAACBQAAAA1jdXJyZW50UGVyaW9kAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAABhwcm9jZXNzTmV4dEJhdGNoSW50ZXJuYWwAAAAFAAAAEGJvb3N0aW5nQ29udHJhY3QAAAANY3VycmVudFBlcmlvZAAAAAtjdXJyZW50VXNlcgAAAAVkZXB0aAAAAAt0b3RhbFdlaWdodAQAAAAXYm9vc3RpbmdDb250cmFjdEFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQUAAAAQYm9vc3RpbmdDb250cmFjdAQAAAAMbGF0ZXN0UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAPa2V5TGF0ZXN0UGVyaW9kAAAAAAQAAAAKdXNlcnNDb3VudAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwkBAAAADWtleVVzZXJzQ291bnQAAAAAAAAAAAAAAAAABAAAAA50b3RhbFdlaWdodEtleQkBAAAAF2tleVRvdGFsV2VpZ2h0Rm9yUGVyaW9kAAAAAQUAAAANY3VycmVudFBlcmlvZAQAAAAPaGVpZ2h0Rm9yUGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAASa2V5SGVpZ2h0Rm9yUGVyaW9kAAAAAQUAAAANY3VycmVudFBlcmlvZAMDCQAAZgAAAAIFAAAABWRlcHRoAAAAAAAAAAAACQAAZwAAAAIFAAAADGxhdGVzdFBlcmlvZAUAAAANY3VycmVudFBlcmlvZAcEAAAACyR0MDYwODQ2MTg2CQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kBQAAAAtjdXJyZW50VXNlcgQAAAACdzAIBQAAAAskdDA2MDg0NjE4NgAAAAJfMQQAAAAFc2F2ZTAIBQAAAAskdDA2MDg0NjE4NgAAAAJfMgQAAAAHd2VpZ2h0MAkAAGQAAAACBQAAAAt0b3RhbFdlaWdodAUAAAACdzADCQAAZgAAAAIFAAAACnVzZXJzQ291bnQJAABkAAAAAgUAAAALY3VycmVudFVzZXIAAAAAAAAAAAEEAAAACyR0MDYyNzM2Mzg0CQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAAC2N1cnJlbnRVc2VyAAAAAAAAAAABBAAAAAd3ZWlnaHQxCAUAAAALJHQwNjI3MzYzODQAAAACXzEEAAAABXNhdmUxCAUAAAALJHQwNjI3MzYzODQAAAACXzIDCQAAZgAAAAIFAAAACnVzZXJzQ291bnQJAABkAAAAAgUAAAALY3VycmVudFVzZXIAAAAAAAAAAAIEAAAACyR0MDY0NDA2NTUxCQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAAC2N1cnJlbnRVc2VyAAAAAAAAAAACBAAAAAd3ZWlnaHQyCAUAAAALJHQwNjQ0MDY1NTEAAAACXzEEAAAABXNhdmUyCAUAAAALJHQwNjQ0MDY1NTEAAAACXzIDCQAAZgAAAAIFAAAACnVzZXJzQ291bnQJAABkAAAAAgUAAAALY3VycmVudFVzZXIAAAAAAAAAAAMEAAAACyR0MDY2MTE2NzIyCQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAAC2N1cnJlbnRVc2VyAAAAAAAAAAADBAAAAAd3ZWlnaHQzCAUAAAALJHQwNjYxMTY3MjIAAAACXzEEAAAABXNhdmUzCAUAAAALJHQwNjYxMTY3MjIAAAACXzIDCQAAZgAAAAIFAAAACnVzZXJzQ291bnQJAABkAAAAAgUAAAALY3VycmVudFVzZXIAAAAAAAAAAAQEAAAACyR0MDY3ODY2ODk3CQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAAC2N1cnJlbnRVc2VyAAAAAAAAAAAEBAAAAAd3ZWlnaHQ0CAUAAAALJHQwNjc4NjY4OTcAAAACXzEEAAAABXNhdmU0CAUAAAALJHQwNjc4NjY4OTcAAAACXzIDCQAAZgAAAAIFAAAACnVzZXJzQ291bnQJAABkAAAAAgUAAAALY3VycmVudFVzZXIAAAAAAAAAAAUEAAAACyR0MDY5NjU3MDc2CQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAAC2N1cnJlbnRVc2VyAAAAAAAAAAAF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SW50LCBJbnQpBAAAAAFyBQAAAAckbWF0Y2gwBQAAAAFyCQAAAgAAAAECAAAAF0luY29ycmVjdCBpbnZva2UgcmVzdWx0CQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEAAAANY2xhaW1JbnRlcm5hbAAAAAUAAAAQYm9vc3RpbmdDb250cmFjdAAAAA1jdXJyZW50UGVyaW9kAAAAC2N1cnJlbnRVc2VyAAAABWRlcHRoAAAAD3VzZXJBY2N1bXVsYXRlZAQAAAAXYm9vc3RpbmdDb250cmFjdEFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQUAAAAQYm9vc3RpbmdDb250cmFjdAQAAAAMbGF0ZXN0UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAWa2V5TmV4dFByb2Nlc3NlZFBlcmlvZAAAAAAEAAAAC3RvdGFsV2VpZ2h0CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAXa2V5VG90YWxXZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kBAAAAA9oZWlnaHRGb3JQZXJpb2QJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABJrZXlIZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kBAAAAA0kdDAxMDIyNDEwMzM2CQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kBQAAAAtjdXJyZW50VXNlcgQAAAAKdXNlcldlaWdodAgFAAAADSR0MDEwMjI0MTAzMzYAAAACXzEEAAAAB2lnbm9yZWQIBQAAAA0kdDAxMDIyNDEwMzM2AAAAAl8yBAAAABN1c2VyQW1vdW5kRm9yUGVyaW9kCQAAawAAAAMJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABdrZXlUb3RhbEFtb3VudEZvclBlcmlvZAAAAAEFAAAADWN1cnJlbnRQZXJpb2QFAAAACnVzZXJXZWlnaHQFAAAAC3RvdGFsV2VpZ2h0AwMJAABnAAAAAgAAAAAAAAAAAAUAAAAFZGVwdGgGCQAAZwAAAAIJAABkAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQUAAAAMbGF0ZXN0UGVyaW9kCQAFFAAAAAIJAABkAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQkAAGQAAAACBQAAAA91c2VyQWNjdW11bGF0ZWQFAAAAE3VzZXJBbW91bmRGb3JQZXJpb2QJAQAAAAtpbnZva2VDbGFpbQAAAAUFAAAAEGJvb3N0aW5nQ29udHJhY3QJAABkAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQUAAAALY3VycmVudFVzZXIJAABlAAAAAgUAAAAFZGVwdGgAAAAAAAAAAAEJAABkAAAAAgUAAAAPdXNlckFjY3VtdWxhdGVkBQAAABN1c2VyQW1vdW5kRm9yUGVyaW9kAQAAABFjb21tb25DbGFpbVJld2FyZAAAAAEAAAALdXNlckFkZHJlc3MEAAAACGNmZ0FycmF5CQEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAQAAAAHdXNlcklkeAkBAAAAFWdldFVzZXJJbmRleEJ5QWRkcmVzcwAAAAIJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAFklkeENmZ0Jvb3N0aW5nQ29udHJhY3QFAAAAC3VzZXJBZGRyZXNzBAAAAA1jdXJyZW50UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAba2V5TmV4dFVubGFpbWVkUGVyaW9kT2ZVc2VyAAAAAQUAAAAHdXNlcklkeAMJAABnAAAAAgUAAAANY3VycmVudFBlcmlvZAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAFmtleU5leHRQcm9jZXNzZWRQZXJpb2QAAAAACQAAAgAAAAECAAAAEE5vdGhpbmcgdG8gY2xhaW0EAAAAEGJvb3N0aW5nQ29udHJhY3QJAAJZAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAAWSWR4Q2ZnQm9vc3RpbmdDb250cmFjdAkABRUAAAADCQEAAAANY2xhaW1JbnRlcm5hbAAAAAUFAAAAEGJvb3N0aW5nQ29udHJhY3QFAAAADWN1cnJlbnRQZXJpb2QFAAAAB3VzZXJJZHgFAAAACVVTRVJERVBUSAAAAAAAAAAAAAUAAAAHdXNlcklkeAUAAAAIY2ZnQXJyYXkAAAAIAAAAAWkBAAAAEHByb2Nlc3NOZXh0QmF0Y2gAAAAFAAAAEGJvb3N0aW5nQ29udHJhY3QAAAANY3VycmVudFBlcmlvZAAAAAtjdXJyZW50VXNlcgAAAAVkZXB0aAAAAAt0b3RhbFdlaWdodAMJAQAAAAIhPQAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAEdGhpcwkAAAIAAAABAgAAACRTaG91bGQgYmUgY2FsbGVkIGJ5IHRoaXMgc2NyaXB0IG9ubHkEAAAAA3RwbAkBAAAAGHByb2Nlc3NOZXh0QmF0Y2hJbnRlcm5hbAAAAAUFAAAAEGJvb3N0aW5nQ29udHJhY3QFAAAADWN1cnJlbnRQZXJpb2QFAAAAC2N1cnJlbnRVc2VyBQAAAAVkZXB0aAUAAAALdG90YWxXZWlnaHQJAAUUAAAAAggFAAAAA3RwbAAAAAJfMQkABRUAAAADCAUAAAADdHBsAAAAAl8yCAUAAAADdHBsAAAAAl8zCAUAAAADdHBsAAAAAl80AAAAAWkBAAAAHXByb2Nlc3NQZW5kaW5nUGVyaW9kc0FuZFVzZXJzAAAAAQAAAAVkZXB0aAMJAABmAAAAAgUAAAAFZGVwdGgFAAAACE1BWERFUFRICQAAAgAAAAECAAAAFkRlcHRoIGV4Y2VlZHMgTUFYREVQVEgEAAAADWN1cnJlbnRQZXJpb2QJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABZrZXlOZXh0UHJvY2Vzc2VkUGVyaW9kAAAAAAMJAABmAAAAAgUAAAANY3VycmVudFBlcmlvZAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAD2tleUxhdGVzdFBlcmlvZAAAAAAJAAACAAAAAQIAAAASTm90aGluZyB0byBwcm9jZXNzBAAAABBib29zdGluZ0NvbnRyYWN0CQACWQAAAAEJAAGRAAAAAgkBAAAAFXJlYWRDb25maWdBcnJheU9yRmFpbAAAAAAFAAAAFklkeENmZ0Jvb3N0aW5nQ29udHJhY3QEAAAAC2N1cnJlbnRVc2VyCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAUa2V5TmV4dFByb2Nlc3NlZFVzZXIAAAAABAAAAAt0b3RhbFdlaWdodAkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAF2tleVRvdGFsV2VpZ2h0Rm9yUGVyaW9kAAAAAQUAAAANY3VycmVudFBlcmlvZAQAAAABcgkBAAAAGHByb2Nlc3NOZXh0QmF0Y2hJbnRlcm5hbAAAAAUFAAAAEGJvb3N0aW5nQ29udHJhY3QFAAAADWN1cnJlbnRQZXJpb2QFAAAAC2N1cnJlbnRVc2VyBQAAAAVkZXB0aAUAAAALdG90YWxXZWlnaHQJAARNAAAAAgkABE0AAAACCAUAAAABcgAAAAJfMQkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABZrZXlOZXh0UHJvY2Vzc2VkUGVyaW9kAAAAAAgFAAAAAXIAAAACXzIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAUa2V5TmV4dFByb2Nlc3NlZFVzZXIAAAAACAUAAAABcgAAAAJfMwAAAAFpAQAAAAdkZXBvc2l0AAAAAAQAAAAIY2ZnQXJyYXkJAQAAABVyZWFkQ29uZmlnQXJyYXlPckZhaWwAAAAABAAAAAdhc3NldElkCQEAAAAFdmFsdWUAAAABCAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkAwkBAAAAAiE9AAAAAgUAAAAHYXNzZXRJZAkAAlkAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAAA1JZHhDZmdBc3NldElkCQAAAgAAAAECAAAAE1dyb25nIHBheW1lbnQgYXNzZXQEAAAABnBlcmlvZAkBAAAACm5leHRQZXJpb2QAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAPa2V5TGF0ZXN0UGVyaW9kAAAAAAUAAAAGcGVyaW9kCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAASa2V5SGVpZ2h0Rm9yUGVyaW9kAAAAAQUAAAAGcGVyaW9kBQAAAAZoZWlnaHQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABdrZXlUb3RhbEFtb3VudEZvclBlcmlvZAAAAAEFAAAABnBlcmlvZAgJAQAAAAV2YWx1ZQAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAANa2V5TmV4dFBlcmlvZAAAAAAJAABkAAAAAgUAAAAGcGVyaW9kAAAAAAAAAAABBQAAAANuaWwAAAABaQEAAAAOY2xhaW1OZXh0QmF0Y2gAAAAFAAAAEGJvb3N0aW5nQ29udHJhY3QAAAANY3VycmVudFBlcmlvZAAAAAtjdXJyZW50VXNlcgAAAAVkZXB0aAAAAAt0b3RhbFdlaWdodAMJAQAAAAIhPQAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAEdGhpcwkAAAIAAAABAgAAACRTaG91bGQgYmUgY2FsbGVkIGJ5IHRoaXMgc2NyaXB0IG9ubHkEAAAADnBlcmlvZEFuZFRvdGFsCQEAAAANY2xhaW1JbnRlcm5hbAAAAAUFAAAAEGJvb3N0aW5nQ29udHJhY3QFAAAADWN1cnJlbnRQZXJpb2QFAAAAC2N1cnJlbnRVc2VyBQAAAAVkZXB0aAUAAAALdG90YWxXZWlnaHQJAAUUAAAAAgUAAAADbmlsBQAAAA5wZXJpb2RBbmRUb3RhbAAAAAFpAQAAAAtjbGFpbVJld2FyZAAAAAAEAAAAB2FkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAA1jb21tb25SZXN1bHRzCQEAAAARY29tbW9uQ2xhaW1SZXdhcmQAAAABBQAAAAdhZGRyZXNzBAAAAAFyCAUAAAANY29tbW9uUmVzdWx0cwAAAAJfMQQAAAAHdXNlcklkeAgFAAAADWNvbW1vblJlc3VsdHMAAAACXzIEAAAACGNmZ0FycmF5CAUAAAANY29tbW9uUmVzdWx0cwAAAAJfMwkABRQAAAACCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAba2V5TmV4dFVubGFpbWVkUGVyaW9kT2ZVc2VyAAAAAQUAAAAHdXNlcklkeAgFAAAAAXIAAAACXzEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyCAUAAAABcgAAAAJfMgkAAlkAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAAA1JZHhDZmdBc3NldElkBQAAAANuaWwIBQAAAAFyAAAAAl8yAAAAAWkBAAAAE2NsYWltUmV3YXJkUkVBRE9OTFkAAAABAAAAC3VzZXJBZGRyZXNzBAAAAA1jb21tb25SZXN1bHRzCQEAAAARY29tbW9uQ2xhaW1SZXdhcmQAAAABBQAAAAt1c2VyQWRkcmVzcwQAAAABcggFAAAADWNvbW1vblJlc3VsdHMAAAACXzEEAAAAB3VzZXJJZHgIBQAAAA1jb21tb25SZXN1bHRzAAAAAl8yBAAAAAhjZmdBcnJheQgFAAAADWNvbW1vblJlc3VsdHMAAAACXzMJAAUUAAAAAgUAAAADbmlsCAUAAAABcgAAAAJfMgAAAAFpAQAAABVjYWxjR3d4UGFyYW1zUkVBRE9OTFkAAAADAAAACHd4QW1vdW50AAAAD2xvY2tTdGFydEhlaWdodAAAABJsb2NrRHVyYXRpb25CbG9ja3MEAAAADWxvY2tFbmRIZWlnaHQJAABkAAAAAgUAAAAPbG9ja1N0YXJ0SGVpZ2h0BQAAABJsb2NrRHVyYXRpb25CbG9ja3MEAAAADHNjYWxlOFBhcmFtSwkBAAAAAS0AAAABCQAAawAAAAMFAAAACHd4QW1vdW50BQAAAAZTQ0FMRTYFAAAAEmxvY2tEdXJhdGlvbkJsb2NrcwQAAAAMc2NhbGU4UGFyYW1CCQAAaAAAAAIJAABrAAAAAwUAAAAId3hBbW91bnQFAAAABlNDQUxFNgUAAAASbG9ja0R1cmF0aW9uQmxvY2tzBQAAAA1sb2NrRW5kSGVpZ2h0CQAFFAAAAAIFAAAAA25pbAkABEwAAAACBQAAAAxzY2FsZThQYXJhbUsJAARMAAAAAgUAAAAMc2NhbGU4UGFyYW1CCQAETAAAAAIJAQAAAApuZXh0UGVyaW9kAAAAAAUAAAADbmlsAAAAAWkBAAAAC2NvbnN0cnVjdG9yAAAAAwAAAAx3eEFzc2V0SWRTdHIAAAAabWF0Y2hlclBhY2VtYWtlckFkZHJlc3NTdHIAAAAaYm9vc3RpbmdDb250cmFjdEFkZHJlc3NTdHIDCQEAAAACIT0AAAACBQAAAAR0aGlzCAUAAAABaQAAAAZjYWxsZXIJAAACAAAAAQIAAAAObm90IGF1dGhvcml6ZWQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAACWtleUNvbmZpZwAAAAAJAQAAAAxmb3JtYXRDb25maWcAAAADBQAAAAx3eEFzc2V0SWRTdHIFAAAAGm1hdGNoZXJQYWNlbWFrZXJBZGRyZXNzU3RyBQAAABpib29zdGluZ0NvbnRyYWN0QWRkcmVzc1N0cgUAAAADbmlsAAAAAPT+bhE=", "chainId": 84, "height": 1796609, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: BBJCr3LuhhHqaUJXLTdi4nMYhLEzyjLBTtjz2s1apvC7 Next: HvuQNpjYC9Qz1tyJoRiELRgvoLz6WfWdHj5AR9ArzZa5 Diff:
Old | New | Differences | |
---|---|---|---|
9 | 9 | ||
10 | 10 | let USERDEPTH = 26 | |
11 | 11 | ||
12 | - | let | |
12 | + | let SCALE6 = 1000000 | |
13 | 13 | ||
14 | 14 | func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0) | |
15 | 15 | ||
26 | 26 | ||
27 | 27 | let IdxCfgBoostingContract = 3 | |
28 | 28 | ||
29 | - | let IdxCfgMaxDepth = 4 | |
30 | - | ||
31 | 29 | func keyConfig () = "%s__config" | |
32 | 30 | ||
33 | 31 | ||
34 | 32 | func readConfigArrayOrFail () = split(getStringOrFail(keyConfig()), SEP) | |
35 | 33 | ||
36 | 34 | ||
37 | - | func formatConfig (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr | |
35 | + | func formatConfig (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr) = makeString(["%s%s%s", wxAssetIdStr, matcherPacemakerAddressStr, boostingContractAddressStr], SEP) | |
38 | 36 | ||
39 | 37 | ||
40 | - | func keyUsersCount () = "%s | |
38 | + | func keyUsersCount () = makeString(["%s", "nextUserNum"], SEP) | |
41 | 39 | ||
42 | 40 | ||
43 | - | func keyNextProcessedUser () = "%s | |
41 | + | func keyNextProcessedUser () = makeString(["%s", "nextProcessedUser"], SEP) | |
44 | 42 | ||
45 | 43 | ||
46 | - | func keyLatestPeriod () = "%s | |
44 | + | func keyLatestPeriod () = makeString(["%s", "latestPeriod"], SEP) | |
47 | 45 | ||
48 | 46 | ||
49 | - | func keyNextPeriod () = "%s | |
47 | + | func keyNextPeriod () = makeString(["%s", "nextPeriod"], SEP) | |
50 | 48 | ||
51 | 49 | ||
52 | - | func keyNextProcessedPeriod () = "%s | |
50 | + | func keyNextProcessedPeriod () = makeString(["%s", "nextProcessedPeriod"], SEP) | |
53 | 51 | ||
54 | 52 | ||
55 | - | func keyNextUnlaimedPeriodOfUser (userIndex) = makeString(["%s%d | |
53 | + | func keyNextUnlaimedPeriodOfUser (userIndex) = makeString(["%s%d", "nextClaimedPeriod", toString(userIndex)], SEP) | |
56 | 54 | ||
57 | 55 | ||
58 | - | func keyLastProcessedPeriodOfUser (userIndex) = makeString(["%s%d | |
56 | + | func keyLastProcessedPeriodOfUser (userIndex) = makeString(["%s%d", "lastProcessedPeriod", toString(userIndex)], SEP) | |
59 | 57 | ||
60 | 58 | ||
61 | - | func keyHeightForPeriod (period) = makeString(["%s%d | |
59 | + | func keyHeightForPeriod (period) = makeString(["%s%d", "startHeightForPeriod", toString(period)], SEP) | |
62 | 60 | ||
63 | 61 | ||
64 | - | func keyTotalAmountForPeriod (period) = makeString(["%s%d | |
62 | + | func keyTotalAmountForPeriod (period) = makeString(["%s%d", "totalAmountForPeriod", toString(period)], SEP) | |
65 | 63 | ||
66 | 64 | ||
67 | - | func keyTotalWeightForPeriod (period) = makeString(["%s%d | |
65 | + | func keyTotalWeightForPeriod (period) = makeString(["%s%d", "totalWeightForPeriod", toString(period)], SEP) | |
68 | 66 | ||
69 | 67 | ||
70 | - | func keyUserKValueForPeriod (period,userIndex) = makeString(["%s%d%s%d | |
68 | + | func keyUserKValueForPeriod (period,userIndex) = makeString(["%s%d%s%d", "paramByPeriod", toString(userIndex), "k", toString(period)], SEP) | |
71 | 69 | ||
72 | 70 | ||
73 | - | func keyUserBValueForPeriod (period,userIndex) = makeString(["%s%d%s%d__paramByPeriod", toString(userIndex), "b", toString(period)], SEP) | |
74 | - | ||
75 | - | ||
76 | - | func HistoryEntry (type,user,amount,currentPeriod,latestPeriod,i) = { | |
77 | - | let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP) | |
78 | - | let historyDATA = makeString(["%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(amount), toString(currentPeriod), toString(latestPeriod)], SEP) | |
79 | - | StringEntry(historyKEY, historyDATA) | |
80 | - | } | |
71 | + | func keyUserBValueForPeriod (period,userIndex) = makeString(["%s%d%s%d", "paramByPeriod", toString(userIndex), "b", toString(period)], SEP) | |
81 | 72 | ||
82 | 73 | ||
83 | 74 | func calcUserWeight (boostingContractAddress,heightForPeriod,period,userIndex) = { | |
90 | 81 | let b = value(getInteger(boostingContractAddress, keyUserBValueForPeriod(period, userIndex))) | |
91 | 82 | let w = ((k * heightForPeriod) + b) | |
92 | 83 | if ((w > 0)) | |
93 | - | then $Tuple2((w / | |
84 | + | then $Tuple2((w / SCALE6), [IntegerEntry(kLast, period)]) | |
94 | 85 | else $Tuple2(0, nil) | |
95 | 86 | } | |
96 | 87 | else { | |
102 | 93 | let b = value(getInteger(boostingContractAddress, keyUserBValueForPeriod(pv, userIndex))) | |
103 | 94 | let w = ((k * heightForPeriod) + b) | |
104 | 95 | if ((w > 0)) | |
105 | - | then $Tuple2((w / | |
96 | + | then $Tuple2((w / SCALE6), nil) | |
106 | 97 | else $Tuple2(0, nil) | |
107 | 98 | } | |
108 | 99 | else $Tuple2(0, nil) | |
119 | 110 | func nextPeriod () = getNumberByKey(keyNextPeriod()) | |
120 | 111 | ||
121 | 112 | ||
122 | - | func invokeProcess (boostingContract,period,user,depth,weight) = { | |
113 | + | func invokeProcess (boostingContract,period,user,depth,weight,actions) = { | |
123 | 114 | let result = invoke(this, "processNextBatch", [boostingContract, period, user, depth, weight], nil) | |
124 | 115 | if ((result == result)) | |
125 | 116 | then match result { | |
126 | 117 | case r: (Int, Int, Int) => | |
127 | - | r | |
118 | + | $Tuple4(actions, r._1, r._2, r._3) | |
128 | 119 | case _ => | |
129 | 120 | throw("Incorrect invoke result") | |
130 | 121 | } | |
133 | 124 | ||
134 | 125 | ||
135 | 126 | func checkLastPartOfPeriod (boostingContract,currentPeriod,latestPeriod,depth,totalWeightKey,weight) = if ((latestPeriod >= (currentPeriod + 1))) | |
136 | - | then invokeProcess(boostingContract, (currentPeriod + 1), 0, (depth - 1), 0) | |
137 | - | else $ | |
127 | + | then invokeProcess(boostingContract, (currentPeriod + 1), 0, (depth - 1), 0, [IntegerEntry(totalWeightKey, weight)]) | |
128 | + | else $Tuple4([IntegerEntry(totalWeightKey, weight)], (currentPeriod + 1), 0, 0) | |
138 | 129 | ||
139 | 130 | ||
140 | 131 | func processNextBatchInternal (boostingContract,currentPeriod,currentUser,depth,totalWeight) = { | |
147 | 138 | then (latestPeriod >= currentPeriod) | |
148 | 139 | else false) | |
149 | 140 | then { | |
150 | - | let t0 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, currentUser) | |
151 | - | let weight0 = (totalWeight + t0._1) | |
141 | + | let $t060846186 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, currentUser) | |
142 | + | let w0 = $t060846186._1 | |
143 | + | let save0 = $t060846186._2 | |
144 | + | let weight0 = (totalWeight + w0) | |
152 | 145 | if ((usersCount > (currentUser + 1))) | |
153 | 146 | then { | |
154 | - | let t1 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 1)) | |
155 | - | let weight1 = (weight0 + t1._1) | |
147 | + | let $t062736384 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 1)) | |
148 | + | let weight1 = $t062736384._1 | |
149 | + | let save1 = $t062736384._2 | |
156 | 150 | if ((usersCount > (currentUser + 2))) | |
157 | 151 | then { | |
158 | - | let t2 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 2)) | |
159 | - | let weight2 = (weight1 + t2._1) | |
152 | + | let $t064406551 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 2)) | |
153 | + | let weight2 = $t064406551._1 | |
154 | + | let save2 = $t064406551._2 | |
160 | 155 | if ((usersCount > (currentUser + 3))) | |
161 | 156 | then { | |
162 | - | let t3 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 3)) | |
163 | - | let weight3 = (weight2 + t3._1) | |
157 | + | let $t066116722 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 3)) | |
158 | + | let weight3 = $t066116722._1 | |
159 | + | let save3 = $t066116722._2 | |
164 | 160 | if ((usersCount > (currentUser + 4))) | |
165 | 161 | then { | |
166 | - | let t4 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 4)) | |
167 | - | let weight4 = (weight3 + t4._1) | |
162 | + | let $t067866897 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 4)) | |
163 | + | let weight4 = $t067866897._1 | |
164 | + | let save4 = $t067866897._2 | |
168 | 165 | if ((usersCount > (currentUser + 5))) | |
169 | 166 | then { | |
170 | - | let t5 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 5)) | |
171 | - | let weight5 = (weight4 + t5._1) | |
167 | + | let $t069657076 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 5)) | |
168 | + | let weight5 = $t069657076._1 | |
169 | + | let save5 = $t069657076._2 | |
172 | 170 | if ((usersCount > (currentUser + 6))) | |
173 | 171 | then { | |
174 | - | let r5 = invokeProcess(boostingContract, currentPeriod, (currentUser + 6), (depth - 1), weight5) | |
175 | - | $Tuple4((((((t0._2 ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3) | |
172 | + | let $t071957351 = invokeProcess(boostingContract, currentPeriod, (currentUser + 6), (depth - 1), (((((weight0 + weight1) + weight2) + weight3) + weight4) + weight5), nil) | |
173 | + | let a = $t071957351._1 | |
174 | + | let p = $t071957351._2 | |
175 | + | let u = $t071957351._3 | |
176 | + | let w = $t071957351._4 | |
177 | + | $Tuple4(((((((a ++ save0) ++ save1) ++ save2) ++ save3) ++ save4) ++ save5), p, u, w) | |
176 | 178 | } | |
177 | 179 | else { | |
178 | - | let r5 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight5) | |
179 | - | $Tuple4((((((([IntegerEntry(totalWeightKey, weight5)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3) | |
180 | + | let $t075197688 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, (((((weight0 + weight1) + weight2) + weight3) + weight4) + weight5)) | |
181 | + | let a = $t075197688._1 | |
182 | + | let p = $t075197688._2 | |
183 | + | let u = $t075197688._3 | |
184 | + | let w = $t075197688._4 | |
185 | + | $Tuple4(((((((a ++ save0) ++ save1) ++ save2) ++ save3) ++ save4) ++ save5), p, u, w) | |
180 | 186 | } | |
181 | 187 | } | |
182 | 188 | else { | |
183 | - | let r4 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight4) | |
184 | - | $Tuple4(((((([IntegerEntry(totalWeightKey, weight4)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2), r4._1, r4._2, r4._3) | |
189 | + | let $t078688027 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, ((((weight0 + weight1) + weight2) + weight3) + weight4)) | |
190 | + | let a = $t078688027._1 | |
191 | + | let p = $t078688027._2 | |
192 | + | let u = $t078688027._3 | |
193 | + | let w = $t078688027._4 | |
194 | + | $Tuple4((((((a ++ save0) ++ save1) ++ save2) ++ save3) ++ save4), p, u, w) | |
185 | 195 | } | |
186 | 196 | } | |
187 | 197 | else { | |
188 | - | let r3 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight3) | |
189 | - | $Tuple4((((([IntegerEntry(totalWeightKey, weight3)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2), r3._1, r3._2, r3._3) | |
198 | + | let $t081908339 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, (((weight0 + weight1) + weight2) + weight3)) | |
199 | + | let a = $t081908339._1 | |
200 | + | let p = $t081908339._2 | |
201 | + | let u = $t081908339._3 | |
202 | + | let w = $t081908339._4 | |
203 | + | $Tuple4(((((a ++ save0) ++ save1) ++ save2) ++ save3), p, u, w) | |
190 | 204 | } | |
191 | 205 | } | |
192 | 206 | else { | |
193 | - | let r2 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight2) | |
194 | - | $Tuple4(((([IntegerEntry(totalWeightKey, weight2)] ++ t0._2) ++ t1._2) ++ t2._2), r2._1, r2._2, r2._3) | |
207 | + | let $t084858624 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, ((weight0 + weight1) + weight2)) | |
208 | + | let a = $t084858624._1 | |
209 | + | let p = $t084858624._2 | |
210 | + | let u = $t084858624._3 | |
211 | + | let w = $t084858624._4 | |
212 | + | $Tuple4((((a ++ save0) ++ save1) ++ save2), p, u, w) | |
195 | 213 | } | |
196 | 214 | } | |
197 | 215 | else { | |
198 | - | let r1 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight1) | |
199 | - | $Tuple4((([IntegerEntry(totalWeightKey, weight1)] ++ t0._2) ++ t1._2), r1._1, r1._2, r1._3) | |
216 | + | let $t087538882 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, (weight0 + weight1)) | |
217 | + | let a = $t087538882._1 | |
218 | + | let p = $t087538882._2 | |
219 | + | let u = $t087538882._3 | |
220 | + | let w = $t087538882._4 | |
221 | + | $Tuple4(((a ++ save0) ++ save1), p, u, w) | |
200 | 222 | } | |
201 | 223 | } | |
202 | 224 | else { | |
203 | - | let r0 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight0) | |
204 | - | $Tuple4(([IntegerEntry(totalWeightKey, weight0)] ++ t0._2), r0._1, r0._2, r0._3) | |
225 | + | let $t090239142 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight0) | |
226 | + | let a = $t090239142._1 | |
227 | + | let p = $t090239142._2 | |
228 | + | let u = $t090239142._3 | |
229 | + | let w = $t090239142._4 | |
230 | + | $Tuple4((a ++ save0), p, u, w) | |
205 | 231 | } | |
206 | 232 | } | |
207 | 233 | else if ((currentUser == 0)) | |
228 | 254 | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
229 | 255 | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
230 | 256 | let heightForPeriod = getNumberByKey(keyHeightForPeriod(currentPeriod)) | |
231 | - | let $ | |
232 | - | let userWeight = $ | |
233 | - | let ignored = $ | |
234 | - | let | |
257 | + | let $t01022410336 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, currentUser) | |
258 | + | let userWeight = $t01022410336._1 | |
259 | + | let ignored = $t01022410336._2 | |
260 | + | let userAmoundForPeriod = fraction(getNumberByKey(keyTotalAmountForPeriod(currentPeriod)), userWeight, totalWeight) | |
235 | 261 | if (if ((0 >= depth)) | |
236 | 262 | then true | |
237 | 263 | else ((currentPeriod + 1) >= latestPeriod)) | |
238 | - | then $Tuple2((currentPeriod + 1), (userAccumulated + userAmountForPeriod)) | |
239 | - | else invokeClaim(boostingContract, (currentPeriod + 1), currentUser, (depth - 1), (userAccumulated + userAmountForPeriod)) | |
264 | + | then $Tuple2((currentPeriod + 1), (userAccumulated + userAmoundForPeriod)) | |
265 | + | else invokeClaim(boostingContract, (currentPeriod + 1), currentUser, (depth - 1), (userAccumulated + userAmoundForPeriod)) | |
266 | + | } | |
267 | + | ||
268 | + | ||
269 | + | func commonClaimReward (userAddress) = { | |
270 | + | let cfgArray = readConfigArrayOrFail() | |
271 | + | let userIdx = getUserIndexByAddress(cfgArray[IdxCfgBoostingContract], userAddress) | |
272 | + | let currentPeriod = getNumberByKey(keyNextUnlaimedPeriodOfUser(userIdx)) | |
273 | + | if ((currentPeriod >= getNumberByKey(keyNextProcessedPeriod()))) | |
274 | + | then throw("Nothing to claim") | |
275 | + | else { | |
276 | + | let boostingContract = fromBase58String(cfgArray[IdxCfgBoostingContract]) | |
277 | + | $Tuple3(claimInternal(boostingContract, currentPeriod, userIdx, USERDEPTH, 0), userIdx, cfgArray) | |
278 | + | } | |
240 | 279 | } | |
241 | 280 | ||
242 | 281 | ||
251 | 290 | ||
252 | 291 | ||
253 | 292 | @Callable(i) | |
254 | - | func processPendingPeriodsAndUsers () = { | |
255 | - | let currentPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
256 | - | if ((currentPeriod > getNumberByKey(keyLatestPeriod()))) | |
257 | - | then throw("Nothing to process") | |
258 | - | else { | |
259 | - | let cfgArray = readConfigArrayOrFail() | |
260 | - | let depth = parseIntValue(cfgArray[IdxCfgMaxDepth]) | |
261 | - | if ((depth > MAXDEPTH)) | |
262 | - | then throw("Depth exceeds MAXDEPTH") | |
263 | - | else { | |
264 | - | let boostingContract = fromBase58String(cfgArray[IdxCfgBoostingContract]) | |
265 | - | let currentUser = getNumberByKey(keyNextProcessedUser()) | |
266 | - | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
267 | - | let r = processNextBatchInternal(boostingContract, currentPeriod, currentUser, depth, totalWeight) | |
268 | - | ((r._1 :+ IntegerEntry(keyNextProcessedPeriod(), r._2)) :+ IntegerEntry(keyNextProcessedUser(), r._3)) | |
269 | - | } | |
270 | - | } | |
271 | - | } | |
293 | + | func processPendingPeriodsAndUsers (depth) = if ((depth > MAXDEPTH)) | |
294 | + | then throw("Depth exceeds MAXDEPTH") | |
295 | + | else { | |
296 | + | let currentPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
297 | + | if ((currentPeriod > getNumberByKey(keyLatestPeriod()))) | |
298 | + | then throw("Nothing to process") | |
299 | + | else { | |
300 | + | let boostingContract = fromBase58String(readConfigArrayOrFail()[IdxCfgBoostingContract]) | |
301 | + | let currentUser = getNumberByKey(keyNextProcessedUser()) | |
302 | + | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
303 | + | let r = processNextBatchInternal(boostingContract, currentPeriod, currentUser, depth, totalWeight) | |
304 | + | ((r._1 :+ IntegerEntry(keyNextProcessedPeriod(), r._2)) :+ IntegerEntry(keyNextProcessedUser(), r._3)) | |
305 | + | } | |
306 | + | } | |
272 | 307 | ||
273 | 308 | ||
274 | 309 | ||
275 | 310 | @Callable(i) | |
276 | 311 | func deposit () = { | |
277 | 312 | let cfgArray = readConfigArrayOrFail() | |
278 | - | if ((i.caller != Address(fromBase58String(cfgArray[IdxCfgPacemakerAddress])))) | |
279 | - | then throw("Wrong caller address") | |
313 | + | let assetId = value(value(i.payments[0]).assetId) | |
314 | + | if ((assetId != fromBase58String(cfgArray[IdxCfgAssetId]))) | |
315 | + | then throw("Wrong payment asset") | |
280 | 316 | else { | |
281 | - | let assetId = value(value(i.payments[0]).assetId) | |
282 | - | if ((assetId != fromBase58String(cfgArray[IdxCfgAssetId]))) | |
283 | - | then throw("Wrong payment asset") | |
284 | - | else { | |
285 | - | let period = nextPeriod() | |
317 | + | let period = nextPeriod() | |
286 | 318 | [IntegerEntry(keyLatestPeriod(), period), IntegerEntry(keyHeightForPeriod(period), height), IntegerEntry(keyTotalAmountForPeriod(period), value(i.payments[0]).amount), IntegerEntry(keyNextPeriod(), (period + 1))] | |
287 | - | } | |
288 | 319 | } | |
289 | 320 | } | |
290 | 321 | ||
302 | 333 | ||
303 | 334 | @Callable(i) | |
304 | 335 | func claimReward () = { | |
305 | - | let cfgArray = readConfigArrayOrFail() | |
306 | 336 | let address = toString(i.caller) | |
307 | - | let userIdx = getUserIndexByAddress(cfgArray[IdxCfgBoostingContract], address) | |
308 | - | let currentPeriod = getNumberByKey(keyNextUnlaimedPeriodOfUser(userIdx)) | |
309 | - | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
310 | - | if ((currentPeriod >= latestPeriod)) | |
311 | - | then throw("Nothing to claim") | |
312 | - | else { | |
313 | - | let boostingContract = fromBase58String(cfgArray[IdxCfgBoostingContract]) | |
314 | - | let $t01456214654 = claimInternal(boostingContract, currentPeriod, userIdx, USERDEPTH, 0) | |
315 | - | let period = $t01456214654._1 | |
316 | - | let amount = $t01456214654._2 | |
317 | - | $Tuple2([IntegerEntry(keyNextUnlaimedPeriodOfUser(userIdx), period), ScriptTransfer(i.caller, amount, fromBase58String(cfgArray[IdxCfgAssetId])), HistoryEntry("claim", address, amount, period, latestPeriod, i)], amount) | |
318 | - | } | |
337 | + | let commonResults = commonClaimReward(address) | |
338 | + | let r = commonResults._1 | |
339 | + | let userIdx = commonResults._2 | |
340 | + | let cfgArray = commonResults._3 | |
341 | + | $Tuple2([IntegerEntry(keyNextUnlaimedPeriodOfUser(userIdx), r._1), ScriptTransfer(i.caller, r._2, fromBase58String(cfgArray[IdxCfgAssetId]))], r._2) | |
342 | + | } | |
343 | + | ||
344 | + | ||
345 | + | ||
346 | + | @Callable(i) | |
347 | + | func claimRewardREADONLY (userAddress) = { | |
348 | + | let commonResults = commonClaimReward(userAddress) | |
349 | + | let r = commonResults._1 | |
350 | + | let userIdx = commonResults._2 | |
351 | + | let cfgArray = commonResults._3 | |
352 | + | $Tuple2(nil, r._2) | |
319 | 353 | } | |
320 | 354 | ||
321 | 355 | ||
323 | 357 | @Callable(i) | |
324 | 358 | func calcGwxParamsREADONLY (wxAmount,lockStartHeight,lockDurationBlocks) = { | |
325 | 359 | let lockEndHeight = (lockStartHeight + lockDurationBlocks) | |
326 | - | let scale8ParamK = -(fraction(wxAmount, | |
327 | - | let scale8ParamB = (fraction(wxAmount, | |
360 | + | let scale8ParamK = -(fraction(wxAmount, SCALE6, lockDurationBlocks)) | |
361 | + | let scale8ParamB = (fraction(wxAmount, SCALE6, lockDurationBlocks) * lockEndHeight) | |
328 | 362 | $Tuple2(nil, [scale8ParamK, scale8ParamB, nextPeriod()]) | |
329 | 363 | } | |
330 | 364 | ||
331 | 365 | ||
332 | 366 | ||
333 | 367 | @Callable(i) | |
334 | - | func constructor (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr | |
368 | + | func constructor (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr) = if ((this != i.caller)) | |
335 | 369 | then throw("not authorized") | |
336 | - | else [StringEntry(keyConfig(), formatConfig(wxAssetIdStr, matcherPacemakerAddressStr, boostingContractAddressStr | |
370 | + | else [StringEntry(keyConfig(), formatConfig(wxAssetIdStr, matcherPacemakerAddressStr, boostingContractAddressStr))] | |
337 | 371 | ||
338 | 372 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let revisionNum = "" | |
5 | 5 | ||
6 | 6 | let SEP = "__" | |
7 | 7 | ||
8 | 8 | let MAXDEPTH = 17 | |
9 | 9 | ||
10 | 10 | let USERDEPTH = 26 | |
11 | 11 | ||
12 | - | let | |
12 | + | let SCALE6 = 1000000 | |
13 | 13 | ||
14 | 14 | func getNumberByKey (key) = valueOrElse(getInteger(this, key), 0) | |
15 | 15 | ||
16 | 16 | ||
17 | 17 | func getStringByKey (key) = valueOrElse(getString(this, key), "") | |
18 | 18 | ||
19 | 19 | ||
20 | 20 | func getStringOrFail (key) = valueOrErrorMessage(getString(key), (("mandatory this." + key) + " is not defined")) | |
21 | 21 | ||
22 | 22 | ||
23 | 23 | let IdxCfgAssetId = 1 | |
24 | 24 | ||
25 | 25 | let IdxCfgPacemakerAddress = 2 | |
26 | 26 | ||
27 | 27 | let IdxCfgBoostingContract = 3 | |
28 | 28 | ||
29 | - | let IdxCfgMaxDepth = 4 | |
30 | - | ||
31 | 29 | func keyConfig () = "%s__config" | |
32 | 30 | ||
33 | 31 | ||
34 | 32 | func readConfigArrayOrFail () = split(getStringOrFail(keyConfig()), SEP) | |
35 | 33 | ||
36 | 34 | ||
37 | - | func formatConfig (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr | |
35 | + | func formatConfig (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr) = makeString(["%s%s%s", wxAssetIdStr, matcherPacemakerAddressStr, boostingContractAddressStr], SEP) | |
38 | 36 | ||
39 | 37 | ||
40 | - | func keyUsersCount () = "%s | |
38 | + | func keyUsersCount () = makeString(["%s", "nextUserNum"], SEP) | |
41 | 39 | ||
42 | 40 | ||
43 | - | func keyNextProcessedUser () = "%s | |
41 | + | func keyNextProcessedUser () = makeString(["%s", "nextProcessedUser"], SEP) | |
44 | 42 | ||
45 | 43 | ||
46 | - | func keyLatestPeriod () = "%s | |
44 | + | func keyLatestPeriod () = makeString(["%s", "latestPeriod"], SEP) | |
47 | 45 | ||
48 | 46 | ||
49 | - | func keyNextPeriod () = "%s | |
47 | + | func keyNextPeriod () = makeString(["%s", "nextPeriod"], SEP) | |
50 | 48 | ||
51 | 49 | ||
52 | - | func keyNextProcessedPeriod () = "%s | |
50 | + | func keyNextProcessedPeriod () = makeString(["%s", "nextProcessedPeriod"], SEP) | |
53 | 51 | ||
54 | 52 | ||
55 | - | func keyNextUnlaimedPeriodOfUser (userIndex) = makeString(["%s%d | |
53 | + | func keyNextUnlaimedPeriodOfUser (userIndex) = makeString(["%s%d", "nextClaimedPeriod", toString(userIndex)], SEP) | |
56 | 54 | ||
57 | 55 | ||
58 | - | func keyLastProcessedPeriodOfUser (userIndex) = makeString(["%s%d | |
56 | + | func keyLastProcessedPeriodOfUser (userIndex) = makeString(["%s%d", "lastProcessedPeriod", toString(userIndex)], SEP) | |
59 | 57 | ||
60 | 58 | ||
61 | - | func keyHeightForPeriod (period) = makeString(["%s%d | |
59 | + | func keyHeightForPeriod (period) = makeString(["%s%d", "startHeightForPeriod", toString(period)], SEP) | |
62 | 60 | ||
63 | 61 | ||
64 | - | func keyTotalAmountForPeriod (period) = makeString(["%s%d | |
62 | + | func keyTotalAmountForPeriod (period) = makeString(["%s%d", "totalAmountForPeriod", toString(period)], SEP) | |
65 | 63 | ||
66 | 64 | ||
67 | - | func keyTotalWeightForPeriod (period) = makeString(["%s%d | |
65 | + | func keyTotalWeightForPeriod (period) = makeString(["%s%d", "totalWeightForPeriod", toString(period)], SEP) | |
68 | 66 | ||
69 | 67 | ||
70 | - | func keyUserKValueForPeriod (period,userIndex) = makeString(["%s%d%s%d | |
68 | + | func keyUserKValueForPeriod (period,userIndex) = makeString(["%s%d%s%d", "paramByPeriod", toString(userIndex), "k", toString(period)], SEP) | |
71 | 69 | ||
72 | 70 | ||
73 | - | func keyUserBValueForPeriod (period,userIndex) = makeString(["%s%d%s%d__paramByPeriod", toString(userIndex), "b", toString(period)], SEP) | |
74 | - | ||
75 | - | ||
76 | - | func HistoryEntry (type,user,amount,currentPeriod,latestPeriod,i) = { | |
77 | - | let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP) | |
78 | - | let historyDATA = makeString(["%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(amount), toString(currentPeriod), toString(latestPeriod)], SEP) | |
79 | - | StringEntry(historyKEY, historyDATA) | |
80 | - | } | |
71 | + | func keyUserBValueForPeriod (period,userIndex) = makeString(["%s%d%s%d", "paramByPeriod", toString(userIndex), "b", toString(period)], SEP) | |
81 | 72 | ||
82 | 73 | ||
83 | 74 | func calcUserWeight (boostingContractAddress,heightForPeriod,period,userIndex) = { | |
84 | 75 | let kLast = keyLastProcessedPeriodOfUser(userIndex) | |
85 | 76 | let kKey = keyUserKValueForPeriod(period, userIndex) | |
86 | 77 | let kRaw = getInteger(boostingContractAddress, kKey) | |
87 | 78 | if (isDefined(kRaw)) | |
88 | 79 | then { | |
89 | 80 | let k = value(kRaw) | |
90 | 81 | let b = value(getInteger(boostingContractAddress, keyUserBValueForPeriod(period, userIndex))) | |
91 | 82 | let w = ((k * heightForPeriod) + b) | |
92 | 83 | if ((w > 0)) | |
93 | - | then $Tuple2((w / | |
84 | + | then $Tuple2((w / SCALE6), [IntegerEntry(kLast, period)]) | |
94 | 85 | else $Tuple2(0, nil) | |
95 | 86 | } | |
96 | 87 | else { | |
97 | 88 | let p = getInteger(this, kLast) | |
98 | 89 | if (isDefined(p)) | |
99 | 90 | then { | |
100 | 91 | let pv = value(p) | |
101 | 92 | let k = value(getInteger(boostingContractAddress, keyUserKValueForPeriod(pv, userIndex))) | |
102 | 93 | let b = value(getInteger(boostingContractAddress, keyUserBValueForPeriod(pv, userIndex))) | |
103 | 94 | let w = ((k * heightForPeriod) + b) | |
104 | 95 | if ((w > 0)) | |
105 | - | then $Tuple2((w / | |
96 | + | then $Tuple2((w / SCALE6), nil) | |
106 | 97 | else $Tuple2(0, nil) | |
107 | 98 | } | |
108 | 99 | else $Tuple2(0, nil) | |
109 | 100 | } | |
110 | 101 | } | |
111 | 102 | ||
112 | 103 | ||
113 | 104 | func getUserIndexByAddress (boostingContractAddressStr,userAddress) = { | |
114 | 105 | let key = makeString(["%s%s%s", "mapping", "user2num", userAddress], SEP) | |
115 | 106 | parseIntValue(valueOrErrorMessage(getString(Address(fromBase58String(boostingContractAddressStr)), key), ((("User address " + userAddress) + " is not found in boosting contract data, key=") + key))) | |
116 | 107 | } | |
117 | 108 | ||
118 | 109 | ||
119 | 110 | func nextPeriod () = getNumberByKey(keyNextPeriod()) | |
120 | 111 | ||
121 | 112 | ||
122 | - | func invokeProcess (boostingContract,period,user,depth,weight) = { | |
113 | + | func invokeProcess (boostingContract,period,user,depth,weight,actions) = { | |
123 | 114 | let result = invoke(this, "processNextBatch", [boostingContract, period, user, depth, weight], nil) | |
124 | 115 | if ((result == result)) | |
125 | 116 | then match result { | |
126 | 117 | case r: (Int, Int, Int) => | |
127 | - | r | |
118 | + | $Tuple4(actions, r._1, r._2, r._3) | |
128 | 119 | case _ => | |
129 | 120 | throw("Incorrect invoke result") | |
130 | 121 | } | |
131 | 122 | else throw("Strict value is not equal to itself.") | |
132 | 123 | } | |
133 | 124 | ||
134 | 125 | ||
135 | 126 | func checkLastPartOfPeriod (boostingContract,currentPeriod,latestPeriod,depth,totalWeightKey,weight) = if ((latestPeriod >= (currentPeriod + 1))) | |
136 | - | then invokeProcess(boostingContract, (currentPeriod + 1), 0, (depth - 1), 0) | |
137 | - | else $ | |
127 | + | then invokeProcess(boostingContract, (currentPeriod + 1), 0, (depth - 1), 0, [IntegerEntry(totalWeightKey, weight)]) | |
128 | + | else $Tuple4([IntegerEntry(totalWeightKey, weight)], (currentPeriod + 1), 0, 0) | |
138 | 129 | ||
139 | 130 | ||
140 | 131 | func processNextBatchInternal (boostingContract,currentPeriod,currentUser,depth,totalWeight) = { | |
141 | 132 | let boostingContractAddress = Address(boostingContract) | |
142 | 133 | let latestPeriod = getNumberByKey(keyLatestPeriod()) | |
143 | 134 | let usersCount = valueOrElse(getInteger(boostingContractAddress, keyUsersCount()), 0) | |
144 | 135 | let totalWeightKey = keyTotalWeightForPeriod(currentPeriod) | |
145 | 136 | let heightForPeriod = getNumberByKey(keyHeightForPeriod(currentPeriod)) | |
146 | 137 | if (if ((depth > 0)) | |
147 | 138 | then (latestPeriod >= currentPeriod) | |
148 | 139 | else false) | |
149 | 140 | then { | |
150 | - | let t0 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, currentUser) | |
151 | - | let weight0 = (totalWeight + t0._1) | |
141 | + | let $t060846186 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, currentUser) | |
142 | + | let w0 = $t060846186._1 | |
143 | + | let save0 = $t060846186._2 | |
144 | + | let weight0 = (totalWeight + w0) | |
152 | 145 | if ((usersCount > (currentUser + 1))) | |
153 | 146 | then { | |
154 | - | let t1 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 1)) | |
155 | - | let weight1 = (weight0 + t1._1) | |
147 | + | let $t062736384 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 1)) | |
148 | + | let weight1 = $t062736384._1 | |
149 | + | let save1 = $t062736384._2 | |
156 | 150 | if ((usersCount > (currentUser + 2))) | |
157 | 151 | then { | |
158 | - | let t2 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 2)) | |
159 | - | let weight2 = (weight1 + t2._1) | |
152 | + | let $t064406551 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 2)) | |
153 | + | let weight2 = $t064406551._1 | |
154 | + | let save2 = $t064406551._2 | |
160 | 155 | if ((usersCount > (currentUser + 3))) | |
161 | 156 | then { | |
162 | - | let t3 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 3)) | |
163 | - | let weight3 = (weight2 + t3._1) | |
157 | + | let $t066116722 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 3)) | |
158 | + | let weight3 = $t066116722._1 | |
159 | + | let save3 = $t066116722._2 | |
164 | 160 | if ((usersCount > (currentUser + 4))) | |
165 | 161 | then { | |
166 | - | let t4 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 4)) | |
167 | - | let weight4 = (weight3 + t4._1) | |
162 | + | let $t067866897 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 4)) | |
163 | + | let weight4 = $t067866897._1 | |
164 | + | let save4 = $t067866897._2 | |
168 | 165 | if ((usersCount > (currentUser + 5))) | |
169 | 166 | then { | |
170 | - | let t5 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 5)) | |
171 | - | let weight5 = (weight4 + t5._1) | |
167 | + | let $t069657076 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, (currentUser + 5)) | |
168 | + | let weight5 = $t069657076._1 | |
169 | + | let save5 = $t069657076._2 | |
172 | 170 | if ((usersCount > (currentUser + 6))) | |
173 | 171 | then { | |
174 | - | let r5 = invokeProcess(boostingContract, currentPeriod, (currentUser + 6), (depth - 1), weight5) | |
175 | - | $Tuple4((((((t0._2 ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3) | |
172 | + | let $t071957351 = invokeProcess(boostingContract, currentPeriod, (currentUser + 6), (depth - 1), (((((weight0 + weight1) + weight2) + weight3) + weight4) + weight5), nil) | |
173 | + | let a = $t071957351._1 | |
174 | + | let p = $t071957351._2 | |
175 | + | let u = $t071957351._3 | |
176 | + | let w = $t071957351._4 | |
177 | + | $Tuple4(((((((a ++ save0) ++ save1) ++ save2) ++ save3) ++ save4) ++ save5), p, u, w) | |
176 | 178 | } | |
177 | 179 | else { | |
178 | - | let r5 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight5) | |
179 | - | $Tuple4((((((([IntegerEntry(totalWeightKey, weight5)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3) | |
180 | + | let $t075197688 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, (((((weight0 + weight1) + weight2) + weight3) + weight4) + weight5)) | |
181 | + | let a = $t075197688._1 | |
182 | + | let p = $t075197688._2 | |
183 | + | let u = $t075197688._3 | |
184 | + | let w = $t075197688._4 | |
185 | + | $Tuple4(((((((a ++ save0) ++ save1) ++ save2) ++ save3) ++ save4) ++ save5), p, u, w) | |
180 | 186 | } | |
181 | 187 | } | |
182 | 188 | else { | |
183 | - | let r4 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight4) | |
184 | - | $Tuple4(((((([IntegerEntry(totalWeightKey, weight4)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2), r4._1, r4._2, r4._3) | |
189 | + | let $t078688027 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, ((((weight0 + weight1) + weight2) + weight3) + weight4)) | |
190 | + | let a = $t078688027._1 | |
191 | + | let p = $t078688027._2 | |
192 | + | let u = $t078688027._3 | |
193 | + | let w = $t078688027._4 | |
194 | + | $Tuple4((((((a ++ save0) ++ save1) ++ save2) ++ save3) ++ save4), p, u, w) | |
185 | 195 | } | |
186 | 196 | } | |
187 | 197 | else { | |
188 | - | let r3 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight3) | |
189 | - | $Tuple4((((([IntegerEntry(totalWeightKey, weight3)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2), r3._1, r3._2, r3._3) | |
198 | + | let $t081908339 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, (((weight0 + weight1) + weight2) + weight3)) | |
199 | + | let a = $t081908339._1 | |
200 | + | let p = $t081908339._2 | |
201 | + | let u = $t081908339._3 | |
202 | + | let w = $t081908339._4 | |
203 | + | $Tuple4(((((a ++ save0) ++ save1) ++ save2) ++ save3), p, u, w) | |
190 | 204 | } | |
191 | 205 | } | |
192 | 206 | else { | |
193 | - | let r2 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight2) | |
194 | - | $Tuple4(((([IntegerEntry(totalWeightKey, weight2)] ++ t0._2) ++ t1._2) ++ t2._2), r2._1, r2._2, r2._3) | |
207 | + | let $t084858624 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, ((weight0 + weight1) + weight2)) | |
208 | + | let a = $t084858624._1 | |
209 | + | let p = $t084858624._2 | |
210 | + | let u = $t084858624._3 | |
211 | + | let w = $t084858624._4 | |
212 | + | $Tuple4((((a ++ save0) ++ save1) ++ save2), p, u, w) | |
195 | 213 | } | |
196 | 214 | } | |
197 | 215 | else { | |
198 | - | let r1 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight1) | |
199 | - | $Tuple4((([IntegerEntry(totalWeightKey, weight1)] ++ t0._2) ++ t1._2), r1._1, r1._2, r1._3) | |
216 | + | let $t087538882 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, (weight0 + weight1)) | |
217 | + | let a = $t087538882._1 | |
218 | + | let p = $t087538882._2 | |
219 | + | let u = $t087538882._3 | |
220 | + | let w = $t087538882._4 | |
221 | + | $Tuple4(((a ++ save0) ++ save1), p, u, w) | |
200 | 222 | } | |
201 | 223 | } | |
202 | 224 | else { | |
203 | - | let r0 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight0) | |
204 | - | $Tuple4(([IntegerEntry(totalWeightKey, weight0)] ++ t0._2), r0._1, r0._2, r0._3) | |
225 | + | let $t090239142 = checkLastPartOfPeriod(boostingContract, currentPeriod, latestPeriod, depth, totalWeightKey, weight0) | |
226 | + | let a = $t090239142._1 | |
227 | + | let p = $t090239142._2 | |
228 | + | let u = $t090239142._3 | |
229 | + | let w = $t090239142._4 | |
230 | + | $Tuple4((a ++ save0), p, u, w) | |
205 | 231 | } | |
206 | 232 | } | |
207 | 233 | else if ((currentUser == 0)) | |
208 | 234 | then $Tuple4(nil, currentPeriod, 0, 0) | |
209 | 235 | else $Tuple4([IntegerEntry(totalWeightKey, totalWeight)], currentPeriod, currentUser, 0) | |
210 | 236 | } | |
211 | 237 | ||
212 | 238 | ||
213 | 239 | func invokeClaim (boostingContract,period,user,depth,total) = { | |
214 | 240 | let result = invoke(this, "claimNextBatch", [boostingContract, period, user, depth, total], nil) | |
215 | 241 | if ((result == result)) | |
216 | 242 | then match result { | |
217 | 243 | case r: (Int, Int) => | |
218 | 244 | r | |
219 | 245 | case _ => | |
220 | 246 | throw("Incorrect invoke result") | |
221 | 247 | } | |
222 | 248 | else throw("Strict value is not equal to itself.") | |
223 | 249 | } | |
224 | 250 | ||
225 | 251 | ||
226 | 252 | func claimInternal (boostingContract,currentPeriod,currentUser,depth,userAccumulated) = { | |
227 | 253 | let boostingContractAddress = Address(boostingContract) | |
228 | 254 | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
229 | 255 | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
230 | 256 | let heightForPeriod = getNumberByKey(keyHeightForPeriod(currentPeriod)) | |
231 | - | let $ | |
232 | - | let userWeight = $ | |
233 | - | let ignored = $ | |
234 | - | let | |
257 | + | let $t01022410336 = calcUserWeight(boostingContractAddress, heightForPeriod, currentPeriod, currentUser) | |
258 | + | let userWeight = $t01022410336._1 | |
259 | + | let ignored = $t01022410336._2 | |
260 | + | let userAmoundForPeriod = fraction(getNumberByKey(keyTotalAmountForPeriod(currentPeriod)), userWeight, totalWeight) | |
235 | 261 | if (if ((0 >= depth)) | |
236 | 262 | then true | |
237 | 263 | else ((currentPeriod + 1) >= latestPeriod)) | |
238 | - | then $Tuple2((currentPeriod + 1), (userAccumulated + userAmountForPeriod)) | |
239 | - | else invokeClaim(boostingContract, (currentPeriod + 1), currentUser, (depth - 1), (userAccumulated + userAmountForPeriod)) | |
264 | + | then $Tuple2((currentPeriod + 1), (userAccumulated + userAmoundForPeriod)) | |
265 | + | else invokeClaim(boostingContract, (currentPeriod + 1), currentUser, (depth - 1), (userAccumulated + userAmoundForPeriod)) | |
266 | + | } | |
267 | + | ||
268 | + | ||
269 | + | func commonClaimReward (userAddress) = { | |
270 | + | let cfgArray = readConfigArrayOrFail() | |
271 | + | let userIdx = getUserIndexByAddress(cfgArray[IdxCfgBoostingContract], userAddress) | |
272 | + | let currentPeriod = getNumberByKey(keyNextUnlaimedPeriodOfUser(userIdx)) | |
273 | + | if ((currentPeriod >= getNumberByKey(keyNextProcessedPeriod()))) | |
274 | + | then throw("Nothing to claim") | |
275 | + | else { | |
276 | + | let boostingContract = fromBase58String(cfgArray[IdxCfgBoostingContract]) | |
277 | + | $Tuple3(claimInternal(boostingContract, currentPeriod, userIdx, USERDEPTH, 0), userIdx, cfgArray) | |
278 | + | } | |
240 | 279 | } | |
241 | 280 | ||
242 | 281 | ||
243 | 282 | @Callable(i) | |
244 | 283 | func processNextBatch (boostingContract,currentPeriod,currentUser,depth,totalWeight) = if ((i.caller != this)) | |
245 | 284 | then throw("Should be called by this script only") | |
246 | 285 | else { | |
247 | 286 | let tpl = processNextBatchInternal(boostingContract, currentPeriod, currentUser, depth, totalWeight) | |
248 | 287 | $Tuple2(tpl._1, $Tuple3(tpl._2, tpl._3, tpl._4)) | |
249 | 288 | } | |
250 | 289 | ||
251 | 290 | ||
252 | 291 | ||
253 | 292 | @Callable(i) | |
254 | - | func processPendingPeriodsAndUsers () = { | |
255 | - | let currentPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
256 | - | if ((currentPeriod > getNumberByKey(keyLatestPeriod()))) | |
257 | - | then throw("Nothing to process") | |
258 | - | else { | |
259 | - | let cfgArray = readConfigArrayOrFail() | |
260 | - | let depth = parseIntValue(cfgArray[IdxCfgMaxDepth]) | |
261 | - | if ((depth > MAXDEPTH)) | |
262 | - | then throw("Depth exceeds MAXDEPTH") | |
263 | - | else { | |
264 | - | let boostingContract = fromBase58String(cfgArray[IdxCfgBoostingContract]) | |
265 | - | let currentUser = getNumberByKey(keyNextProcessedUser()) | |
266 | - | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
267 | - | let r = processNextBatchInternal(boostingContract, currentPeriod, currentUser, depth, totalWeight) | |
268 | - | ((r._1 :+ IntegerEntry(keyNextProcessedPeriod(), r._2)) :+ IntegerEntry(keyNextProcessedUser(), r._3)) | |
269 | - | } | |
270 | - | } | |
271 | - | } | |
293 | + | func processPendingPeriodsAndUsers (depth) = if ((depth > MAXDEPTH)) | |
294 | + | then throw("Depth exceeds MAXDEPTH") | |
295 | + | else { | |
296 | + | let currentPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
297 | + | if ((currentPeriod > getNumberByKey(keyLatestPeriod()))) | |
298 | + | then throw("Nothing to process") | |
299 | + | else { | |
300 | + | let boostingContract = fromBase58String(readConfigArrayOrFail()[IdxCfgBoostingContract]) | |
301 | + | let currentUser = getNumberByKey(keyNextProcessedUser()) | |
302 | + | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
303 | + | let r = processNextBatchInternal(boostingContract, currentPeriod, currentUser, depth, totalWeight) | |
304 | + | ((r._1 :+ IntegerEntry(keyNextProcessedPeriod(), r._2)) :+ IntegerEntry(keyNextProcessedUser(), r._3)) | |
305 | + | } | |
306 | + | } | |
272 | 307 | ||
273 | 308 | ||
274 | 309 | ||
275 | 310 | @Callable(i) | |
276 | 311 | func deposit () = { | |
277 | 312 | let cfgArray = readConfigArrayOrFail() | |
278 | - | if ((i.caller != Address(fromBase58String(cfgArray[IdxCfgPacemakerAddress])))) | |
279 | - | then throw("Wrong caller address") | |
313 | + | let assetId = value(value(i.payments[0]).assetId) | |
314 | + | if ((assetId != fromBase58String(cfgArray[IdxCfgAssetId]))) | |
315 | + | then throw("Wrong payment asset") | |
280 | 316 | else { | |
281 | - | let assetId = value(value(i.payments[0]).assetId) | |
282 | - | if ((assetId != fromBase58String(cfgArray[IdxCfgAssetId]))) | |
283 | - | then throw("Wrong payment asset") | |
284 | - | else { | |
285 | - | let period = nextPeriod() | |
317 | + | let period = nextPeriod() | |
286 | 318 | [IntegerEntry(keyLatestPeriod(), period), IntegerEntry(keyHeightForPeriod(period), height), IntegerEntry(keyTotalAmountForPeriod(period), value(i.payments[0]).amount), IntegerEntry(keyNextPeriod(), (period + 1))] | |
287 | - | } | |
288 | 319 | } | |
289 | 320 | } | |
290 | 321 | ||
291 | 322 | ||
292 | 323 | ||
293 | 324 | @Callable(i) | |
294 | 325 | func claimNextBatch (boostingContract,currentPeriod,currentUser,depth,totalWeight) = if ((i.caller != this)) | |
295 | 326 | then throw("Should be called by this script only") | |
296 | 327 | else { | |
297 | 328 | let periodAndTotal = claimInternal(boostingContract, currentPeriod, currentUser, depth, totalWeight) | |
298 | 329 | $Tuple2(nil, periodAndTotal) | |
299 | 330 | } | |
300 | 331 | ||
301 | 332 | ||
302 | 333 | ||
303 | 334 | @Callable(i) | |
304 | 335 | func claimReward () = { | |
305 | - | let cfgArray = readConfigArrayOrFail() | |
306 | 336 | let address = toString(i.caller) | |
307 | - | let userIdx = getUserIndexByAddress(cfgArray[IdxCfgBoostingContract], address) | |
308 | - | let currentPeriod = getNumberByKey(keyNextUnlaimedPeriodOfUser(userIdx)) | |
309 | - | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
310 | - | if ((currentPeriod >= latestPeriod)) | |
311 | - | then throw("Nothing to claim") | |
312 | - | else { | |
313 | - | let boostingContract = fromBase58String(cfgArray[IdxCfgBoostingContract]) | |
314 | - | let $t01456214654 = claimInternal(boostingContract, currentPeriod, userIdx, USERDEPTH, 0) | |
315 | - | let period = $t01456214654._1 | |
316 | - | let amount = $t01456214654._2 | |
317 | - | $Tuple2([IntegerEntry(keyNextUnlaimedPeriodOfUser(userIdx), period), ScriptTransfer(i.caller, amount, fromBase58String(cfgArray[IdxCfgAssetId])), HistoryEntry("claim", address, amount, period, latestPeriod, i)], amount) | |
318 | - | } | |
337 | + | let commonResults = commonClaimReward(address) | |
338 | + | let r = commonResults._1 | |
339 | + | let userIdx = commonResults._2 | |
340 | + | let cfgArray = commonResults._3 | |
341 | + | $Tuple2([IntegerEntry(keyNextUnlaimedPeriodOfUser(userIdx), r._1), ScriptTransfer(i.caller, r._2, fromBase58String(cfgArray[IdxCfgAssetId]))], r._2) | |
342 | + | } | |
343 | + | ||
344 | + | ||
345 | + | ||
346 | + | @Callable(i) | |
347 | + | func claimRewardREADONLY (userAddress) = { | |
348 | + | let commonResults = commonClaimReward(userAddress) | |
349 | + | let r = commonResults._1 | |
350 | + | let userIdx = commonResults._2 | |
351 | + | let cfgArray = commonResults._3 | |
352 | + | $Tuple2(nil, r._2) | |
319 | 353 | } | |
320 | 354 | ||
321 | 355 | ||
322 | 356 | ||
323 | 357 | @Callable(i) | |
324 | 358 | func calcGwxParamsREADONLY (wxAmount,lockStartHeight,lockDurationBlocks) = { | |
325 | 359 | let lockEndHeight = (lockStartHeight + lockDurationBlocks) | |
326 | - | let scale8ParamK = -(fraction(wxAmount, | |
327 | - | let scale8ParamB = (fraction(wxAmount, | |
360 | + | let scale8ParamK = -(fraction(wxAmount, SCALE6, lockDurationBlocks)) | |
361 | + | let scale8ParamB = (fraction(wxAmount, SCALE6, lockDurationBlocks) * lockEndHeight) | |
328 | 362 | $Tuple2(nil, [scale8ParamK, scale8ParamB, nextPeriod()]) | |
329 | 363 | } | |
330 | 364 | ||
331 | 365 | ||
332 | 366 | ||
333 | 367 | @Callable(i) | |
334 | - | func constructor (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr | |
368 | + | func constructor (wxAssetIdStr,matcherPacemakerAddressStr,boostingContractAddressStr) = if ((this != i.caller)) | |
335 | 369 | then throw("not authorized") | |
336 | - | else [StringEntry(keyConfig(), formatConfig(wxAssetIdStr, matcherPacemakerAddressStr, boostingContractAddressStr | |
370 | + | else [StringEntry(keyConfig(), formatConfig(wxAssetIdStr, matcherPacemakerAddressStr, boostingContractAddressStr))] | |
337 | 371 | ||
338 | 372 |
github/deemru/w8io/169f3d6 89.01 ms ◑