tx · CAAN3NneZKMijyNsLNjYRTHEqaQ9Akjswa6QTNiE2ksY 3N4upXkARvecPGQAtpSQ11CFASTFsvEPiP2: -0.01000000 Waves 2022.01.31 13:16 [1902975] smart account 3N4upXkARvecPGQAtpSQ11CFASTFsvEPiP2 > SELF 0.00000000 Waves
{ "type": 13, "id": "CAAN3NneZKMijyNsLNjYRTHEqaQ9Akjswa6QTNiE2ksY", "fee": 1000000, "feeAssetId": null, "timestamp": 1643624235296, "version": 2, "chainId": 84, "sender": "3N4upXkARvecPGQAtpSQ11CFASTFsvEPiP2", "senderPublicKey": "5dTGvAkGC1ryvEkRCst923pqULtN3qWs6XXueerWos1D", "proofs": [ "4bxJtEwiXtjJ9FpJhwx38d8FpDRTFwd1itkJYfGMZQhQoP8Q4HD4pfpCJQifm5dcwGpKN98PHjLJRMkUVKqvd4Ev" ], "script": "base64:AAIFAAAAAAAAADMIAhIHCgUCAQEBARIAEgASCAoGAgEBAQEBEgASBQoDAQEBEgASABIDCgEBEgYKBAgIAQEAAAAoAAAAAAtyZXZpc2lvbk51bQIAAAAAAAAAAANTRVACAAAAAl9fAAAAAAhNQVhERVBUSAAAAAAAAAAAEQAAAAAJVVNFUkRFUFRIAAAAAAAAAAAaAAAAAAVTQ0FMRQAAAAAAAAAD6AEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABAAAAA2tleQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkAAAAAAAAAAAABAAAADmdldFN0cmluZ0J5S2V5AAAAAQAAAANrZXkJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAADa2V5AgAAAAABAAAAD2dldFN0cmluZ09yRmFpbAAAAAEAAAADa2V5CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQiAAAAAQUAAAADa2V5CQABLAAAAAIJAAEsAAAAAgIAAAAPbWFuZGF0b3J5IHRoaXMuBQAAAANrZXkCAAAADyBpcyBub3QgZGVmaW5lZAAAAAAWSWR4Q2ZnTmV1dHJpbm9Db250cmFjdAAAAAAAAAAAAQAAAAAWSWR4Q2ZnTnNidExvY2tDb250cmFjdAAAAAAAAAAAAgAAAAAOSWR4Q2ZnTWF4RGVwdGgAAAAAAAAAAAMAAAAAEUlkeENmZ1BlcmlvZERlbGF5AAAAAAAAAAAEAQAAAAlrZXlDb25maWcAAAAAAgAAAAolc19fY29uZmlnAQAAABVyZWFkQ29uZmlnQXJyYXlPckZhaWwAAAAACQAEtQAAAAIJAQAAAA9nZXRTdHJpbmdPckZhaWwAAAABCQEAAAAJa2V5Q29uZmlnAAAAAAUAAAADU0VQAQAAAAxmb3JtYXRDb25maWcAAAAEAAAAGm5ldXRyaW5vQ29udHJhY3RBZGRyZXNzU3RyAAAAGm5zYnRMb2NrQ29udHJhY3RBZGRyZXNzU3RyAAAACG1heERlcHRoAAAAC3BlcmlvZERlbGF5CQAEuQAAAAIJAARMAAAAAgIAAAAIJXMlcyVkJWQJAARMAAAAAgUAAAAabmV1dHJpbm9Db250cmFjdEFkZHJlc3NTdHIJAARMAAAAAgUAAAAabnNidExvY2tDb250cmFjdEFkZHJlc3NTdHIJAARMAAAAAgkAAaQAAAABBQAAAAhtYXhEZXB0aAkABEwAAAACCQABpAAAAAEFAAAAC3BlcmlvZERlbGF5BQAAAANuaWwFAAAAA1NFUAEAAAANa2V5VXNlcnNDb3VudAAAAAACAAAADyVzX19uZXh0VXNlck51bQEAAAASa2V5TWF4TG9ja0R1cmF0aW9uAAAAAAIAAAATJXNfX21heExvY2tEdXJhdGlvbgEAAAAUa2V5TmV4dFByb2Nlc3NlZFVzZXIAAAAAAgAAABUlc19fbmV4dFByb2Nlc3NlZFVzZXIBAAAAD2tleUxhdGVzdFBlcmlvZAAAAAACAAAAECVzX19sYXRlc3RQZXJpb2QBAAAADWtleU5leHRQZXJpb2QAAAAAAgAAAA4lc19fbmV4dFBlcmlvZAEAAAAWa2V5TmV4dFByb2Nlc3NlZFBlcmlvZAAAAAACAAAAFyVzX19uZXh0UHJvY2Vzc2VkUGVyaW9kAQAAABtrZXlOZXh0VW5sYWltZWRQZXJpb2RPZlVzZXIAAAABAAAACXVzZXJJbmRleAkABLkAAAACCQAETAAAAAICAAAAFyVzJWRfX25leHRDbGFpbWVkUGVyaW9kCQAETAAAAAIJAAGkAAAAAQUAAAAJdXNlckluZGV4BQAAAANuaWwFAAAAA1NFUAEAAAAca2V5TGFzdFByb2Nlc3NlZFBlcmlvZE9mVXNlcgAAAAEAAAAJdXNlckluZGV4CQAEuQAAAAIJAARMAAAAAgIAAAAZJXMlZF9fbGFzdFByb2Nlc3NlZFBlcmlvZAkABEwAAAACCQABpAAAAAEFAAAACXVzZXJJbmRleAUAAAADbmlsBQAAAANTRVABAAAAEmtleUhlaWdodEZvclBlcmlvZAAAAAEAAAAGcGVyaW9kCQAEuQAAAAIJAARMAAAAAgIAAAAaJXMlZF9fc3RhcnRIZWlnaHRGb3JQZXJpb2QJAARMAAAAAgkAAaQAAAABBQAAAAZwZXJpb2QFAAAAA25pbAUAAAADU0VQAQAAABdrZXlUb3RhbEFtb3VudEZvclBlcmlvZAAAAAIAAAAGcGVyaW9kAAAAB2lzV2F2ZXMJAAS5AAAAAgkABEwAAAACAwUAAAAHaXNXYXZlcwIAAAAfJXMlZF9fdG90YWxXYXZlc0Ftb3VudEZvclBlcmlvZAIAAAAeJXMlZF9fdG90YWxVc2RuQW1vdW50Rm9yUGVyaW9kCQAETAAAAAIJAAGkAAAAAQUAAAAGcGVyaW9kBQAAAANuaWwFAAAAA1NFUAEAAAAOa2V5VG90YWxBbW91bnQAAAABAAAAB2lzV2F2ZXMDBQAAAAdpc1dhdmVzAgAAABQlc19fdG90YWxXYXZlc0Ftb3VudAIAAAATJXNfX3RvdGFsVXNkbkFtb3VudAEAAAAXa2V5VG90YWxXZWlnaHRGb3JQZXJpb2QAAAABAAAABnBlcmlvZAkABLkAAAACCQAETAAAAAICAAAAGiVzJWRfX3RvdGFsV2VpZ2h0Rm9yUGVyaW9kCQAETAAAAAIJAAGkAAAAAQUAAAAGcGVyaW9kBQAAAANuaWwFAAAAA1NFUAEAAAAWa2V5VXNlcktWYWx1ZUZvclBlcmlvZAAAAAIAAAAGcGVyaW9kAAAACXVzZXJJbmRleAkABLkAAAACCQAETAAAAAICAAAAFyVzJWQlcyVkX19wYXJhbUJ5UGVyaW9kCQAETAAAAAIJAAGkAAAAAQUAAAAJdXNlckluZGV4CQAETAAAAAICAAAAAWsJAARMAAAAAgkAAaQAAAABBQAAAAZwZXJpb2QFAAAAA25pbAUAAAADU0VQAQAAABZrZXlVc2VyQlZhbHVlRm9yUGVyaW9kAAAAAgAAAAZwZXJpb2QAAAAJdXNlckluZGV4CQAEuQAAAAIJAARMAAAAAgIAAAAXJXMlZCVzJWRfX3BhcmFtQnlQZXJpb2QJAARMAAAAAgkAAaQAAAABBQAAAAl1c2VySW5kZXgJAARMAAAAAgIAAAABYgkABEwAAAACCQABpAAAAAEFAAAABnBlcmlvZAUAAAADbmlsBQAAAANTRVABAAAADEhpc3RvcnlFbnRyeQAAAAcAAAAEdHlwZQAAAAR1c2VyAAAACnVzZG5BbW91bnQAAAAMd2F2ZXNBYW1vdW50AAAADWN1cnJlbnRQZXJpb2QAAAAMbGF0ZXN0UGVyaW9kAAAAAWkEAAAACmhpc3RvcnlLRVkJAAS5AAAAAgkABEwAAAACAgAAABElcyVzJXMlc19faGlzdG9yeQkABEwAAAACBQAAAAR0eXBlCQAETAAAAAIFAAAABHVzZXIJAARMAAAAAgkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkBQAAAANuaWwFAAAAA1NFUAQAAAALaGlzdG9yeURBVEEJAAS5AAAAAgkABEwAAAACAgAAAAwlZCVkJWQlZCVkJWQJAARMAAAAAgkAAaQAAAABCAUAAAAJbGFzdEJsb2NrAAAABmhlaWdodAkABEwAAAACCQABpAAAAAEIBQAAAAlsYXN0QmxvY2sAAAAJdGltZXN0YW1wCQAETAAAAAIJAAGkAAAAAQUAAAAKdXNkbkFtb3VudAkABEwAAAACCQABpAAAAAEFAAAADHdhdmVzQWFtb3VudAkABEwAAAACCQABpAAAAAEFAAAADWN1cnJlbnRQZXJpb2QJAARMAAAAAgkAAaQAAAABBQAAAAxsYXRlc3RQZXJpb2QFAAAAA25pbAUAAAADU0VQCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAApoaXN0b3J5S0VZBQAAAAtoaXN0b3J5REFUQQEAAAAOZ2V0VXNkbkFzc2V0SWQAAAABAAAAF25ldXRyaW5vQ29udHJhY3RBZGRyZXNzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAXbmV1dHJpbm9Db250cmFjdEFkZHJlc3MCAAAAEW5ldXRyaW5vX2Fzc2V0X2lkAgAAAC5tYW5kYXRvcnkga2V5IG5ldXRyaW5vX2Fzc2V0X2lkIGlzIG5vdCBkZWZpbmVkAQAAAA5nZXROc2J0QXNzZXRJZAAAAAEAAAAXbmV1dHJpbm9Db250cmFjdEFkZHJlc3MJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAABduZXV0cmlub0NvbnRyYWN0QWRkcmVzcwIAAAANYm9uZF9hc3NldF9pZAIAAAAqbWFuZGF0b3J5IGtleSBib25kX2Fzc2V0X2lkIGlzIG5vdCBkZWZpbmVkAQAAAA5jYWxjVXNlcldlaWdodAAAAAQAAAAXbnNidExvY2tDb250cmFjdEFkZHJlc3MAAAAPaGVpZ2h0Rm9yUGVyaW9kAAAABnBlcmlvZAAAAAl1c2VySW5kZXgEAAAABWtMYXN0CQEAAAAca2V5TGFzdFByb2Nlc3NlZFBlcmlvZE9mVXNlcgAA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ABBuc2J0TG9ja0NvbnRyYWN0BAAAAAxsYXRlc3RQZXJpb2QJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAAA9rZXlMYXRlc3RQZXJpb2QAAAAABAAAAAp1c2Vyc0NvdW50CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAAF25zYnRMb2NrQ29udHJhY3RBZGRyZXNzCQEAAAANa2V5VXNlcnNDb3VudAAAAAAAAAAAAAAAAAAEAAAADnRvdGFsV2VpZ2h0S2V5CQEAAAAXa2V5VG90YWxXZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kBAAAAA9oZWlnaHRGb3JQZXJpb2QJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABJrZXlIZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kAwMJAABmAAAAAgUAAAAFZGVwdGgAAAAAAAAAAAAJAABnAAAAAgUAAAAMbGF0ZXN0UGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kBwQAAAACdDAJAQAAAA5jYWxjVXNlcldlaWdodAAAAAQFAAAAF25zYnRMb2NrQ29udHJhY3RBZGRyZXNzBQAAAA9oZWlnaHRGb3JQZXJpb2QFAAAADWN1cnJlbnRQZXJpb2QFAAAAC2N1cnJlbnRVc2VyBAAAAAd3ZWlnaHQwCQAAZAAAAAIFAAAAC3RvdGFsV2VpZ2h0CAUAAAACdDAAAAACXzEDCQAAZgAAAAIFAAAACnVzZXJzQ291bnQJAABkAAAAAgUAAAALY3VycmVudFVzZXIAAAAAAAAAAAEEAAAAAnQxCQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABduc2J0TG9ja0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kCQAAZAAAAAIFAAAAC2N1cnJlbnRVc2VyAAAAAAAAAAABBAAAAAd3ZWlnaHQxCQAAZAAAAAIFAAAAB3dlaWdodDAIBQAAAAJ0MQAAAAJfMQMJAABmAAAAAgUAAAAKdXNlcnNDb3VudAkAAGQAAAACBQAAAAtjdXJyZW50VXNlcgAAAAAAAAAAAgQAAAACdDIJAQAAAA5jYWxjVXNlcldlaWdo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dExvY2tDb250cmFjdAAAAAZwZXJpb2QAAAAEdXNlcgAAAAVkZXB0aAAAAAl0b3RhbFVzZG4AAAAKdG90YWxXYXZlcwQAAAAGcmVzdWx0CQAD/AAAAAQFAAAABHRoaXMCAAAADmNsYWltTmV4dEJhdGNoCQAETAAAAAIFAAAAEG5zYnRMb2NrQ29udHJhY3QJAARMAAAAAgUAAAAGcGVyaW9kCQAETAAAAAIFAAAABHVzZXIJAARMAAAAAgUAAAAFZGVwdGgJAARMAAAAAgUAAAAJdG90YWxVc2RuCQAETAAAAAIFAAAACnRvdGFsV2F2ZXMFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAAZyZXN1bHQFAAAABnJlc3VsdAQAAAAHJG1hdGNoMAUAAAAGcmVzdWx0AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAA8oSW50LCBJbnQsIEludCkEAAAAAXIFAAAAByRtYXRjaDAFAAAAAXIJAAACAAAAAQIAAAAXSW5jb3JyZWN0IGludm9rZSByZXN1bHQJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQAAAA1jbGFpbUludGVybmFsAAAABgAAABBuc2J0TG9ja0NvbnRyYWN0AAAADWN1cnJlbnRQZXJpb2QAAAALY3VycmVudFVzZXIAAAAFZGVwdGgAAAATdXNlclVzZG5BY2N1bXVsYXRlZAAAABR1c2VyV2F2ZXNBY2N1bXVsYXRlZAQAAAAXbnNidExvY2tDb250cmFjdEFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQUAAAAQbnNidExvY2tDb250cmFjdAQAAAAMbGF0ZXN0UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAWa2V5TmV4dFByb2Nlc3NlZFBlcmlvZAAAAAAEAAAAC3RvdGFsV2VpZ2h0CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAXa2V5VG90YWxXZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kBAAAAA9oZWlnaHRGb3JQZXJpb2QJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABJrZXlIZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kBAAAAA0kdDAxMDk2MzExMDc1CQEAAAAOY2FsY1VzZXJXZWlnaHQAAAAEBQAAABduc2J0TG9ja0NvbnRyYWN0QWRkcmVzcwUAAAAPaGVpZ2h0Rm9yUGVyaW9kBQAAAA1jdXJyZW50UGVyaW9kBQAAAAtjdXJyZW50VXNlcgQAAAAKdXNlcldlaWdodAgFAAAADSR0MDEwOTYzMTEwNzUAAAACXzEEAAAAB2lnbm9yZWQIBQAAAA0kdDAxMDk2MzExMDc1AAAAAl8yBAAAABd1c2VyVXNkbkFtb3VudEZvclBlcmlvZAkAAGsAAAADCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAXa2V5VG90YWxBbW91bnRGb3JQZXJpb2QAAAACBQAAAA1jdXJyZW50UGVyaW9kBwUAAAAKdXNlcldlaWdodAUAAAALdG90YWxXZWlnaHQEAAAAGHVzZXJXYXZlc0Ftb3VudEZvclBlcmlvZAkAAGsAAAADCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAXa2V5VG90YWxBbW91bnRGb3JQZXJpb2QAAAACBQAAAA1jdXJyZW50UGVyaW9kBgUAAAAKdXNlcldlaWdodAUAAAALdG90YWxXZWlnaHQDAwkAAGcAAAACAAAAAAAAAAAABQAAAAVkZXB0aAYJAABnAAAAAgkAAGQAAAACBQAAAA1jdXJyZW50UGVyaW9kAAAAAAAAAAABBQAAAAxsYXRlc3RQZXJpb2QJAAUVAAAAAwkAAGQAAAACBQAAAA1jdXJyZW50UGVyaW9kAAAAAAAAAAABCQAAZAAAAAIFAAAAE3VzZXJVc2RuQWNjdW11bGF0ZWQFAAAAF3VzZXJVc2RuQW1vdW50Rm9yUGVyaW9kCQAAZAAAAAIFAAAAFHVzZXJXYXZlc0FjY3VtdWxhdGVkBQAAABh1c2VyV2F2ZXNBbW91bnRGb3JQZXJpb2QJAQAAAAtpbnZva2VDbGFpbQAAAAYFAAAAEG5zYnRMb2NrQ29udHJhY3QJAABkAAAAAgUAAAANY3VycmVudFBlcmlvZAAAAAAAAAAAAQUAAAALY3VycmVudFVzZXIJAABlAAAAAgUAAAAFZGVwdGgAAAAAAAAAAAEJAABkAAAAAgUAAAATdXNlclVzZG5BY2N1bXVsYXRlZAUAAAAXdXNlclVzZG5BbW91bnRGb3JQZXJpb2QJAABkAAAAAgUAAAAUdXNlcldhdmVzQWNjdW11bGF0ZWQFAAAAGHVzZXJXYXZlc0Ftb3VudEZvclBlcmlvZAAAAAoAAAABaQEAAAAQcHJvY2Vzc05leHRCYXRjaAAAAAUAAAAQbnNidExvY2tDb250cmFjdAAAAA1jdXJyZW50UGVyaW9kAAAAC2N1cnJlbnRVc2VyAAAABWRlcHRoAAAAC3RvdGFsV2VpZ2h0AwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAAR0aGlzCQAAAgAAAAECAAAAJFNob3VsZCBiZSBjYWxsZWQgYnkgdGhpcyBzY3JpcHQgb25seQQAAAADdHBsCQEAAAAYcHJvY2Vzc05leHRCYXRjaEludGVybmFsAAAABQUAAAAQbnNidExvY2tDb250cmFjdAUAAAANY3VycmVudFBlcmlvZAUAAAALY3VycmVudFVzZXIFAAAABWRlcHRoBQAAAAt0b3RhbFdlaWdodAkABRQAAAACCAUAAAADdHBsAAAAAl8xCQAFFQAAAAMIBQAAAAN0cGwAAAACXzIIBQAAAAN0cGwAAAACXzMIBQAAAAN0cGwAAAACXzQAAAABaQEAAAAdcHJvY2Vzc1BlbmRpbmdQZXJpb2RzQW5kVXNlcnMAAAAABAAAAA1jdXJyZW50UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAWa2V5TmV4dFByb2Nlc3NlZFBlcmlvZAAAAAADCQAAZgAAAAIFAAAADWN1cnJlbnRQZXJpb2QJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAAA9rZXlMYXRlc3RQZXJpb2QAAAAACQAAAgAAAAECAAAAEk5vdGhpbmcgdG8gcHJvY2VzcwQAAAAIY2ZnQXJyYXkJAQAAABVyZWFkQ29uZmlnQXJyYXlPckZhaWwAAAAABAAAAAVkZXB0aAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAAA5JZHhDZmdNYXhEZXB0aAMJAABmAAAAAgUAAAAFZGVwdGgFAAAACE1BWERFUFRICQAAAgAAAAECAAAAFkRlcHRoIGV4Y2VlZHMgTUFYREVQVEgEAAAAEG5zYnRMb2NrQ29udHJhY3QJAAJZAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAAWSWR4Q2ZnTnNidExvY2tDb250cmFjdAQAAAALY3VycmVudFVzZXIJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEJAQAAABRrZXlOZXh0UHJvY2Vzc2VkVXNlcgAAAAAEAAAAC3RvdGFsV2VpZ2h0CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAXa2V5VG90YWxXZWlnaHRGb3JQZXJpb2QAAAABBQAAAA1jdXJyZW50UGVyaW9kBAAAAAFyCQEAAAAYcHJvY2Vzc05leHRCYXRjaEludGVybmFsAAAABQUAAAAQbnNidExvY2tDb250cmFjdAUAAAANY3VycmVudFBlcmlvZAUAAAALY3VycmVudFVzZXIFAAAABWRlcHRoBQAAAAt0b3RhbFdlaWdodAkABE0AAAACCQAETQAAAAIIBQAAAAFyAAAAAl8xCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAFmtleU5leHRQcm9jZXNzZWRQZXJpb2QAAAAACAUAAAABcgAAAAJfMgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABRrZXlOZXh0UHJvY2Vzc2VkVXNlcgAAAAAIBQAAAAFyAAAAAl8zAAAAAWkBAAAAB2RlcG9zaXQAAAAABAAAAAhjZmdBcnJheQkBAAAAFXJlYWRDb25maWdBcnJheU9yRmFpbAAAAAAEAAAAEG5ldXRyaW5vQ29udHJhY3QJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABZJZHhDZmdOZXV0cmlub0NvbnRyYWN0AwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAABBuZXV0cmlub0NvbnRyYWN0CQAAAgAAAAECAAAAFFdyb25nIGNhbGxlciBhZGRyZXNzBAAAAANwbXQJAQAAAAV2YWx1ZQAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAEAAAAB2Fzc2V0SWQIBQAAAANwbXQAAAAHYXNzZXRJZAQAAAAGcGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAANa2V5TmV4dFBlcmlvZAAAAAAEAAAABGhSYXcJAAQaAAAAAgUAAAAEdGhpcwkBAAAAEmtleUhlaWdodEZvclBlcmlvZAAAAAEFAAAABnBlcmlvZAQAAAAFZGVsYXkJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAARSWR4Q2ZnUGVyaW9kRGVsYXkDCQEAAAABIQAAAAEJAQAAAAlpc0RlZmluZWQAAAABBQAAAARoUmF3CQEAAAAMRGVwb3NpdEVudHJ5AAAAAwUAAAAGcGVyaW9kBQAAAANwbXQHAwkAAGcAAAACBQAAAAZoZWlnaHQJAABkAAAAAgkBAAAABXZhbHVlAAAAAQUAAAAEaFJhdwUAAAAFZGVsYXkJAQAAAAxEZXBvc2l0RW50cnkAAAADCQAAZAAAAAIFAAAABnBlcmlvZAAAAAAAAAAAAQUAAAADcG10BgQAAAAJa2V5QW1vdW50CQEAAAAXa2V5VG90YWxBbW91bnRGb3JQZXJpb2QAAAACBQAAAAZwZXJpb2QJAAAAAAAAAgUAAAAHYXNzZXRJZAUAAAAEdW5pdAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa2V5QW1vdW50CQAAZAAAAAIJAQAAAA5nZXROdW1iZXJCeUtleQAAAAEFAAAACWtleUFtb3VudAgFAAAAA3BtdAAAAAZhbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAA5rZXlUb3RhbEFtb3VudAAAAAEJAAAAAAAAAgUAAAAHYXNzZXRJZAUAAAAEdW5pdAkAAGQAAAACCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAOa2V5VG90YWxBbW91bnQAAAABCQAAAAAAAAIFAAAAB2Fzc2V0SWQFAAAABHVuaXQIBQAAAANwbXQAAAAGYW1vdW50BQAAAANuaWwAAAABaQEAAAAOY2xhaW1OZXh0QmF0Y2gAAAAGAAAAEG5zYnRMb2NrQ29udHJhY3QAAAANY3VycmVudFBlcmlvZAAAAAtjdXJyZW50VXNlcgAAAAVkZXB0aAAAAA91c2RuQWNjdW11bGF0ZWQAAAAQd2F2ZXNBY2N1bXVsYXRlZAMJAQAAAAIhPQAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAEdGhpcwkAAAIAAAABAgAAACRTaG91bGQgYmUgY2FsbGVkIGJ5IHRoaXMgc2NyaXB0IG9ubHkEAAAAD3BlcmlvZEFuZFRvdGFscwkBAAAADWNsYWltSW50ZXJuYWwAAAAGBQAAABBuc2J0TG9ja0NvbnRyYWN0BQAAAA1jdXJyZW50UGVyaW9kBQAAAAtjdXJyZW50VXNlcgUAAAAFZGVwdGgFAAAAD3VzZG5BY2N1bXVsYXRlZAUAAAAQd2F2ZXNBY2N1bXVsYXRlZAkABRQAAAACBQAAAANuaWwFAAAAD3BlcmlvZEFuZFRvdGFscwAAAAFpAQAAAAtjbGFpbVJld2FyZAAAAAAEAAAACGNmZ0FycmF5CQEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAQAAAAHYWRkcmVzcwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAAB3VzZXJJZHgJAQAAABVnZXRVc2VySW5kZXhCeUFkZHJlc3MAAAACCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABZJZHhDZmdOc2J0TG9ja0NvbnRyYWN0BQAAAAdhZGRyZXNzBAAAAA1jdXJyZW50UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAba2V5TmV4dFVubGFpbWVkUGVyaW9kT2ZVc2VyAAAAAQUAAAAHdXNlcklkeAQAAAAMbGF0ZXN0UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAWa2V5TmV4dFByb2Nlc3NlZFBlcmlvZAAAAAADCQAAZwAAAAIFAAAADWN1cnJlbnRQZXJpb2QFAAAADGxhdGVzdFBlcmlvZAkAAAIAAAABAgAAABBOb3RoaW5nIHRvIGNsYWltBAAAABBuc2J0TG9ja0NvbnRyYWN0CQACWQAAAAEJAAGRAAAAAgUAAAAIY2ZnQXJyYXkFAAAAFklkeENmZ05zYnRMb2NrQ29udHJhY3QEAAAADSR0MDE1NTg3MTU2OTkJAQAAAA1jbGFpbUludGVybmFsAAAABgUAAAAQbnNidExvY2tDb250cmFjdAUAAAANY3VycmVudFBlcmlvZAUAAAAHdXNlcklkeAUAAAAJVVNFUkRFUFRIAAAAAAAAAAAAAAAAAAAAAAAABAAAAAZwZXJpb2QIBQAAAA0kdDAxNTU4NzE1Njk5AAAAAl8xBAAAAAp1c2RuQW1vdW50CAUAAAANJHQwMTU1ODcxNTY5OQAAAAJfMgQAAAALd2F2ZXNBbW91bnQIBQAAAA0kdDAxNTU4NzE1Njk5AAAAAl8zAwMJAABnAAAAAgAAAAAAAAAAAAUAAAAKdXNkbkFtb3VudAkAAGcAAAACAAAAAAAAAAAABQAAAAt3YXZlc0Ftb3VudAcJAAACAAAAAQIAAAAUTm8gcGF5b3V0cyBhdmFpbGFibGUEAAAAEG5ldXRyaW5vQ29udHJhY3QJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABZJZHhDZmdOZXV0cmlub0NvbnRyYWN0CQAFFAAAAAIJAAROAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAG2tleU5leHRVbmxhaW1lZFBlcmlvZE9mVXNlcgAAAAEFAAAAB3VzZXJJZHgFAAAABnBlcmlvZAkABEwAAAACCQEAAAAMSGlzdG9yeUVudHJ5AAAABwIAAAALY2xhaW1SZXdhcmQFAAAAB2FkZHJlc3MFAAAACnVzZG5BbW91bnQFAAAAC3dhdmVzQW1vdW50BQAAAAZwZXJpb2QFAAAADGxhdGVzdFBlcmlvZAUAAAABaQUAAAADbmlsAwkAAGYAAAACBQAAAAp1c2RuQW1vdW50AAAAAAAAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKdXNkbkFtb3VudAkAAlkAAAABCQEAAAAOZ2V0VXNkbkFzc2V0SWQAAAABBQAAABBuZXV0cmlub0NvbnRyYWN0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAOa2V5VG90YWxBbW91bnQAAAABBwkAAGUAAAACCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAOa2V5VG90YWxBbW91bnQAAAABBwUAAAAKdXNkbkFtb3VudAUAAAADbmlsCQAETgAAAAIFAAAAA25pbAMJAABmAAAAAgUAAAALd2F2ZXNBbW91bnQAAAAAAAAAAAAJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAt3YXZlc0Ftb3VudAUAAAAEdW5pdAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAADmtleVRvdGFsQW1vdW50AAAAAQYJAABlAAAAAgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAADmtleVRvdGFsQW1vdW50AAAAAQYFAAAAC3dhdmVzQW1vdW50BQAAAANuaWwFAAAAA25pbAkABRQAAAACBQAAAAp1c2RuQW1vdW50BQAAAAt3YXZlc0Ftb3VudAAAAAFpAQAAABxjYWxjR292ZXJuYW5jZVBhcmFtc1JFQURPTkxZAAAAAwAAABBuc2J0TG9ja2VkQW1vdW50AAAAD2xvY2tTdGFydEhlaWdodAAAABJsb2NrRHVyYXRpb25CbG9ja3MEAAAACGNmZ0FycmF5CQEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAQAAAAQbnNidExvY2tDb250cmFjdAkAAlkAAAABCQABkQAAAAIFAAAACGNmZ0FycmF5BQAAABZJZHhDZmdOc2J0TG9ja0NvbnRyYWN0BAAAAAttYXhEdXJhdGlvbgkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAAB0FkZHJlc3MAAAABBQAAABBuc2J0TG9ja0NvbnRyYWN0CQEAAAASa2V5TWF4TG9ja0R1cmF0aW9uAAAAAAQAAAANbG9ja0VuZEhlaWdodAkAAGQAAAACBQAAAA9sb2NrU3RhcnRIZWlnaHQFAAAAEmxvY2tEdXJhdGlvbkJsb2NrcwQAAAABawkBAAAAAS0AAAABCQAAawAAAAMFAAAAEG5zYnRMb2NrZWRBbW91bnQFAAAABVNDQUxFBQAAAAttYXhEdXJhdGlvbgQAAAABYgkAAGgAAAACCQEAAAABLQAAAAEFAAAAAWsFAAAADWxvY2tFbmRIZWlnaHQJAAUUAAAAAgUAAAADbmlsCQAETAAAAAIFAAAAAWsJAARMAAAAAgUAAAABYgkABEwAAAACCQEAAAAKbmV4dFBlcmlvZAAAAAAFAAAAA25pbAAAAAFpAQAAABZnZXRUb3RhbFJld2FyZFJFQURPTkxZAAAAAAkABRQAAAACBQAAAANuaWwJAARMAAAAAgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAADmtleVRvdGFsQW1vdW50AAAAAQcJAARMAAAAAgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAADmtleVRvdGFsQW1vdW50AAAAAQYFAAAAA25pbAAAAAFpAQAAAA5wYXJhbXNSRUFET05MWQAAAAAEAAAACGNmZ0FycmF5CQEAAAAVcmVhZENvbmZpZ0FycmF5T3JGYWlsAAAAAAQAAAALcGVyaW9kRGVsYXkJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAAhjZmdBcnJheQUAAAARSWR4Q2ZnUGVyaW9kRGVsYXkJAAUUAAAAAgUAAAADbmlsCQAETAAAAAIFAAAAC3BlcmlvZERlbGF5BQAAAANuaWwAAAABaQEAAAAgcmV3YXJkc1BlckdOc2J0Rm9yUGVyaW9kUkVBRE9OTFkAAAABAAAABnBlcmlvZAQAAAAMbGF0ZXN0UGVyaW9kCQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAPa2V5TGF0ZXN0UGVyaW9kAAAAAAMDCQAAZgAAAAIAAAAAAAAAAAAFAAAABnBlcmlvZAYJAABmAAAAAgUAAAAGcGVyaW9kBQAAAAxsYXRlc3RQZXJpb2QJAAACAAAAAQIAAAAOSW52YWxpZCBwZXJpb2QEAAAAC3RvdGFsV2VpZ2h0CQEAAAAOZ2V0TnVtYmVyQnlLZXkAAAABCQEAAAAXa2V5VG90YWxXZWlnaHRGb3JQZXJpb2QAAAABBQAAAAZwZXJpb2QEAAAADSR0MDE3NjczMTc5MTQDCQAAZgAAAAIFAAAAC3RvdGFsV2VpZ2h0AAAAAAAAAAAACQAFFAAAAAIJAABpAAAAAgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAF2tleVRvdGFsQW1vdW50Rm9yUGVyaW9kAAAAAgUAAAAGcGVyaW9kBgUAAAALdG90YWxXZWlnaHQJAABpAAAAAgkBAAAADmdldE51bWJlckJ5S2V5AAAAAQkBAAAAF2tleVRvdGFsQW1vdW50Rm9yUGVyaW9kAAAAAgUAAAAGcGVyaW9kBwUAAAALdG90YWxXZWlnaHQJAAUUAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAQAAAANd2F2ZXNQZXJHTnNidAgFAAAADSR0MDE3NjczMTc5MTQAAAACXzEEAAAADHVzZG5QZXJHTnNidAgFAAAADSR0MDE3NjczMTc5MTQAAAACXzIJAAUUAAAAAgUAAAADbmlsCQAETAAAAAIFAAAADXdhdmVzUGVyR05zYnQJAARMAAAAAgUAAAAMdXNkblBlckdOc2J0BQAAAANuaWwAAAABaQEAAAALY29uc3RydWN0b3IAAAAEAAAAGm5ldXRyaW5vQ29udHJhY3RBZGRyZXNzU3RyAAAAGm5zYnRMb2NrQ29udHJhY3RBZGRyZXNzU3RyAAAACG1heERlcHRoAAAAC3BlcmlvZERlbGF5AwkBAAAAAiE9AAAAAgUAAAAEdGhpcwgFAAAAAWkAAAAGY2FsbGVyCQAAAgAAAAECAAAADm5vdCBhdXRob3JpemVkCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAlrZXlDb25maWcAAAAACQEAAAAMZm9ybWF0Q29uZmlnAAAABAUAAAAabmV1dHJpbm9Db250cmFjdEFkZHJlc3NTdHIFAAAAGm5zYnRMb2NrQ29udHJhY3RBZGRyZXNzU3RyBQAAAAhtYXhEZXB0aAUAAAALcGVyaW9kRGVsYXkFAAAAA25pbAAAAABiNwlu", "height": 1902975, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: GvKcfmg4N5vRs6KQWsrCE1WL1BS73bPidhfYeMHkMeyX Next: GjVctdxeMZEvRrm783dvzbK9MACnyfsz8d2bNdweL8L6 Diff:
Old | New | Differences | |
---|---|---|---|
38 | 38 | ||
39 | 39 | ||
40 | 40 | func keyUsersCount () = "%s__nextUserNum" | |
41 | + | ||
42 | + | ||
43 | + | func keyMaxLockDuration () = "%s__maxLockDuration" | |
41 | 44 | ||
42 | 45 | ||
43 | 46 | func keyNextProcessedUser () = "%s__nextProcessedUser" | |
93 | 96 | func getNsbtAssetId (neutrinoContractAddress) = valueOrErrorMessage(getString(neutrinoContractAddress, "bond_asset_id"), "mandatory key bond_asset_id is not defined") | |
94 | 97 | ||
95 | 98 | ||
96 | - | func calcWeight (nsbtLockContractAddress,period,user,periodHeight,periods,users) = { | |
97 | - | let k = value(getInteger(nsbtLockContractAddress, keyUserKValueForPeriod(period, user))) | |
98 | - | let b = value(getInteger(nsbtLockContractAddress, keyUserBValueForPeriod(period, user))) | |
99 | - | let w = ((k * periodHeight) + b) | |
100 | - | if ((w > 0)) | |
101 | - | then $Tuple4((w / SCALE), nil, periods, users) | |
102 | - | else $Tuple4(0, nil, periods, users) | |
103 | - | } | |
104 | - | ||
105 | - | ||
106 | - | func calcUserWeight (nsbtLockContractAddress,heightForPeriod,period,userIndex,periods,users) = { | |
99 | + | func calcUserWeight (nsbtLockContractAddress,heightForPeriod,period,userIndex) = { | |
107 | 100 | let kLast = keyLastProcessedPeriodOfUser(userIndex) | |
108 | 101 | let kKey = keyUserKValueForPeriod(period, userIndex) | |
109 | 102 | let kRaw = getInteger(nsbtLockContractAddress, kKey) | |
113 | 106 | let b = value(getInteger(nsbtLockContractAddress, keyUserBValueForPeriod(period, userIndex))) | |
114 | 107 | let w = ((k * heightForPeriod) + b) | |
115 | 108 | if ((w > 0)) | |
116 | - | then { | |
117 | - | let idx = indexOf(users, userIndex) | |
118 | - | if (isDefined(idx)) | |
119 | - | then $Tuple4((w / SCALE), [IntegerEntry(kLast, period)], (removeByIndex(periods, value(idx)) :+ period), (removeByIndex(users, value(idx)) :+ userIndex)) | |
120 | - | else $Tuple4((w / SCALE), [IntegerEntry(kLast, period)], (periods :+ period), (users :+ userIndex)) | |
121 | - | } | |
122 | - | else $Tuple4(0, nil, periods, users) | |
109 | + | then $Tuple2((w / SCALE), [IntegerEntry(kLast, period)]) | |
110 | + | else $Tuple2(0, nil) | |
123 | 111 | } | |
124 | 112 | else { | |
125 | 113 | let p = getInteger(this, kLast) | |
126 | 114 | if (isDefined(p)) | |
127 | - | then calcWeight(nsbtLockContractAddress, value(p), userIndex, heightForPeriod, periods, users) | |
128 | - | else { | |
129 | - | let idx = indexOf(users, userIndex) | |
130 | - | if (isDefined(idx)) | |
131 | - | then calcWeight(nsbtLockContractAddress, periods[value(idx)], userIndex, heightForPeriod, periods, users) | |
132 | - | else $Tuple4(0, nil, periods, users) | |
115 | + | then { | |
116 | + | let pv = value(p) | |
117 | + | let k = value(getInteger(nsbtLockContractAddress, keyUserKValueForPeriod(pv, userIndex))) | |
118 | + | let b = value(getInteger(nsbtLockContractAddress, keyUserBValueForPeriod(pv, userIndex))) | |
119 | + | let w = ((k * heightForPeriod) + b) | |
120 | + | if ((w > 0)) | |
121 | + | then $Tuple2((w / SCALE), nil) | |
122 | + | else $Tuple2(0, nil) | |
133 | 123 | } | |
124 | + | else $Tuple2(0, nil) | |
134 | 125 | } | |
135 | 126 | } | |
136 | 127 | ||
149 | 140 | else -1), IntegerEntry(keyHeightForPeriod(period), height), IntegerEntry(keyTotalAmountForPeriod(period, (pmt.assetId == unit)), pmt.amount), IntegerEntry(keyTotalAmount((pmt.assetId == unit)), (getNumberByKey(keyTotalAmount((pmt.assetId == unit))) + pmt.amount)), IntegerEntry(keyNextPeriod(), period)] | |
150 | 141 | ||
151 | 142 | ||
152 | - | func invokeProcess (nsbtLockContract,period,user,depth,weight | |
153 | - | let result = invoke(this, "processNextBatch", [nsbtLockContract, period, user, depth, weight | |
143 | + | func invokeProcess (nsbtLockContract,period,user,depth,weight) = { | |
144 | + | let result = invoke(this, "processNextBatch", [nsbtLockContract, period, user, depth, weight], nil) | |
154 | 145 | if ((result == result)) | |
155 | 146 | then match result { | |
156 | - | case r: (Int, Int, | |
147 | + | case r: (Int, Int, Int) => | |
157 | 148 | r | |
158 | 149 | case _ => | |
159 | 150 | throw("Incorrect invoke result") | |
162 | 153 | } | |
163 | 154 | ||
164 | 155 | ||
165 | - | func checkLastPartOfPeriod (nsbtLockContract,currentPeriod,latestPeriod,depth,periods,users) = if ((latestPeriod >= (currentPeriod + 1))) | |
166 | - | then invokeProcess(nsbtLockContract, (currentPeriod + 1), 0, (depth - 1), 0, periods, users) | |
167 | - | else $Tuple5((currentPeriod + 1), 0, nil, nil, 0) | |
168 | - | ||
169 | - | ||
170 | - | func processNextBatchInternal (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight,periods,users) = { | |
156 | + | func processNextBatchInternal (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight) = { | |
171 | 157 | let nsbtLockContractAddress = Address(nsbtLockContract) | |
172 | 158 | let latestPeriod = getNumberByKey(keyLatestPeriod()) | |
173 | 159 | let usersCount = valueOrElse(getInteger(nsbtLockContractAddress, keyUsersCount()), 0) | |
177 | 163 | then (latestPeriod >= currentPeriod) | |
178 | 164 | else false) | |
179 | 165 | then { | |
180 | - | let t0 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, currentUser | |
166 | + | let t0 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, currentUser) | |
181 | 167 | let weight0 = (totalWeight + t0._1) | |
182 | 168 | if ((usersCount > (currentUser + 1))) | |
183 | 169 | then { | |
184 | - | let t1 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 1) | |
170 | + | let t1 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 1)) | |
185 | 171 | let weight1 = (weight0 + t1._1) | |
186 | 172 | if ((usersCount > (currentUser + 2))) | |
187 | 173 | then { | |
188 | - | let t2 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 2) | |
174 | + | let t2 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 2)) | |
189 | 175 | let weight2 = (weight1 + t2._1) | |
190 | 176 | if ((usersCount > (currentUser + 3))) | |
191 | 177 | then { | |
192 | - | let t3 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 3) | |
178 | + | let t3 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 3)) | |
193 | 179 | let weight3 = (weight2 + t3._1) | |
194 | 180 | if ((usersCount > (currentUser + 4))) | |
195 | 181 | then { | |
196 | - | let t4 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 4) | |
182 | + | let t4 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 4)) | |
197 | 183 | let weight4 = (weight3 + t4._1) | |
198 | 184 | if ((usersCount > (currentUser + 5))) | |
199 | 185 | then { | |
200 | - | let t5 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 5) | |
186 | + | let t5 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 5)) | |
201 | 187 | let weight5 = (weight4 + t5._1) | |
202 | 188 | if ((usersCount > (currentUser + 6))) | |
203 | 189 | then { | |
204 | - | let r5 = invokeProcess(nsbtLockContract, currentPeriod, (currentUser + 6), (depth - 1), weight5 | |
205 | - | $ | |
190 | + | let r5 = invokeProcess(nsbtLockContract, currentPeriod, (currentUser + 6), (depth - 1), weight5) | |
191 | + | $Tuple4((((((t0._2 ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3) | |
206 | 192 | } | |
207 | - | else { | |
208 | - | let r5 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t5._3, t5._4) | |
209 | - | $Tuple6((((((([IntegerEntry(totalWeightKey, weight5)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3, r5._4, r5._5) | |
210 | - | } | |
193 | + | else $Tuple4((((((([IntegerEntry(totalWeightKey, weight5)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), (currentPeriod + 1), 0, 0) | |
211 | 194 | } | |
212 | - | else { | |
213 | - | let r4 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t4._3, t4._4) | |
214 | - | $Tuple6(((((([IntegerEntry(totalWeightKey, weight4)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2), r4._1, r4._2, r4._3, r4._4, r4._5) | |
215 | - | } | |
195 | + | else $Tuple4(((((([IntegerEntry(totalWeightKey, weight4)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2), (currentPeriod + 1), 0, 0) | |
216 | 196 | } | |
217 | - | else { | |
218 | - | let r3 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t3._3, t3._4) | |
219 | - | $Tuple6((((([IntegerEntry(totalWeightKey, weight3)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2), r3._1, r3._2, r3._3, r3._4, r3._5) | |
220 | - | } | |
197 | + | else $Tuple4((((([IntegerEntry(totalWeightKey, weight3)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2), (currentPeriod + 1), 0, 0) | |
221 | 198 | } | |
222 | - | else { | |
223 | - | let r2 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t2._3, t2._4) | |
224 | - | $Tuple6(((([IntegerEntry(totalWeightKey, weight2)] ++ t0._2) ++ t1._2) ++ t2._2), r2._1, r2._2, r2._3, r2._4, r2._5) | |
225 | - | } | |
199 | + | else $Tuple4(((([IntegerEntry(totalWeightKey, weight2)] ++ t0._2) ++ t1._2) ++ t2._2), (currentPeriod + 1), 0, 0) | |
226 | 200 | } | |
227 | - | else { | |
228 | - | let r1 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t1._3, t1._4) | |
229 | - | $Tuple6((([IntegerEntry(totalWeightKey, weight1)] ++ t0._2) ++ t1._2), r1._1, r1._2, r1._3, r1._4, r1._5) | |
230 | - | } | |
201 | + | else $Tuple4((([IntegerEntry(totalWeightKey, weight1)] ++ t0._2) ++ t1._2), (currentPeriod + 1), 0, 0) | |
231 | 202 | } | |
232 | - | else { | |
233 | - | let r0 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t0._3, t0._4) | |
234 | - | $Tuple6(([IntegerEntry(totalWeightKey, weight0)] ++ t0._2), r0._1, r0._2, r0._3, r0._4, r0._5) | |
235 | - | } | |
203 | + | else $Tuple4(([IntegerEntry(totalWeightKey, weight0)] ++ t0._2), (currentPeriod + 1), 0, 0) | |
236 | 204 | } | |
237 | 205 | else if ((currentUser == 0)) | |
238 | - | then $ | |
239 | - | else $ | |
206 | + | then $Tuple4(nil, currentPeriod, 0, 0) | |
207 | + | else $Tuple4([IntegerEntry(totalWeightKey, totalWeight)], currentPeriod, currentUser, 0) | |
240 | 208 | } | |
241 | 209 | ||
242 | 210 | ||
258 | 226 | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
259 | 227 | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
260 | 228 | let heightForPeriod = getNumberByKey(keyHeightForPeriod(currentPeriod)) | |
261 | - | let $ | |
262 | - | let userWeight = $ | |
263 | - | let ignored = $ | |
229 | + | let $t01096311075 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, currentUser) | |
230 | + | let userWeight = $t01096311075._1 | |
231 | + | let ignored = $t01096311075._2 | |
264 | 232 | let userUsdnAmountForPeriod = fraction(getNumberByKey(keyTotalAmountForPeriod(currentPeriod, false)), userWeight, totalWeight) | |
265 | 233 | let userWavesAmountForPeriod = fraction(getNumberByKey(keyTotalAmountForPeriod(currentPeriod, true)), userWeight, totalWeight) | |
266 | 234 | if (if ((0 >= depth)) | |
272 | 240 | ||
273 | 241 | ||
274 | 242 | @Callable(i) | |
275 | - | func processNextBatch (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight | |
243 | + | func processNextBatch (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight) = if ((i.caller != this)) | |
276 | 244 | then throw("Should be called by this script only") | |
277 | 245 | else { | |
278 | - | let tpl = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight | |
279 | - | $Tuple2(tpl._1, $ | |
246 | + | let tpl = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight) | |
247 | + | $Tuple2(tpl._1, $Tuple3(tpl._2, tpl._3, tpl._4)) | |
280 | 248 | } | |
281 | 249 | ||
282 | 250 | ||
295 | 263 | let nsbtLockContract = fromBase58String(cfgArray[IdxCfgNsbtLockContract]) | |
296 | 264 | let currentUser = getNumberByKey(keyNextProcessedUser()) | |
297 | 265 | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
298 | - | let r = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight | |
266 | + | let r = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight) | |
299 | 267 | ((r._1 :+ IntegerEntry(keyNextProcessedPeriod(), r._2)) :+ IntegerEntry(keyNextProcessedUser(), r._3)) | |
300 | 268 | } | |
301 | 269 | } | |
349 | 317 | then throw("Nothing to claim") | |
350 | 318 | else { | |
351 | 319 | let nsbtLockContract = fromBase58String(cfgArray[IdxCfgNsbtLockContract]) | |
352 | - | let $ | |
353 | - | let period = $ | |
354 | - | let usdnAmount = $ | |
355 | - | let wavesAmount = $ | |
320 | + | let $t01558715699 = claimInternal(nsbtLockContract, currentPeriod, userIdx, USERDEPTH, 0, 0) | |
321 | + | let period = $t01558715699._1 | |
322 | + | let usdnAmount = $t01558715699._2 | |
323 | + | let wavesAmount = $t01558715699._3 | |
356 | 324 | if (if ((0 >= usdnAmount)) | |
357 | 325 | then (0 >= wavesAmount) | |
358 | 326 | else false) | |
371 | 339 | ||
372 | 340 | ||
373 | 341 | @Callable(i) | |
374 | - | func calcGovernanceParamsREADONLY (nsbtAmount,lockStartHeight,lockDurationBlocks) = { | |
342 | + | func calcGovernanceParamsREADONLY (nsbtLockedAmount,lockStartHeight,lockDurationBlocks) = { | |
343 | + | let cfgArray = readConfigArrayOrFail() | |
344 | + | let nsbtLockContract = fromBase58String(cfgArray[IdxCfgNsbtLockContract]) | |
345 | + | let maxDuration = getIntegerValue(Address(nsbtLockContract), keyMaxLockDuration()) | |
375 | 346 | let lockEndHeight = (lockStartHeight + lockDurationBlocks) | |
376 | - | let | |
377 | - | let | |
378 | - | $Tuple2(nil, [ | |
347 | + | let k = -(fraction(nsbtLockedAmount, SCALE, maxDuration)) | |
348 | + | let b = (-(k) * lockEndHeight) | |
349 | + | $Tuple2(nil, [k, b, nextPeriod()]) | |
379 | 350 | } | |
380 | 351 | ||
381 | 352 | ||
382 | 353 | ||
383 | 354 | @Callable(i) | |
384 | 355 | func getTotalRewardREADONLY () = $Tuple2(nil, [getNumberByKey(keyTotalAmount(false)), getNumberByKey(keyTotalAmount(true))]) | |
356 | + | ||
357 | + | ||
358 | + | ||
359 | + | @Callable(i) | |
360 | + | func paramsREADONLY () = { | |
361 | + | let cfgArray = readConfigArrayOrFail() | |
362 | + | let periodDelay = parseIntValue(cfgArray[IdxCfgPeriodDelay]) | |
363 | + | $Tuple2(nil, [periodDelay]) | |
364 | + | } | |
365 | + | ||
366 | + | ||
367 | + | ||
368 | + | @Callable(i) | |
369 | + | func rewardsPerGNsbtForPeriodREADONLY (period) = { | |
370 | + | let latestPeriod = getNumberByKey(keyLatestPeriod()) | |
371 | + | if (if ((0 > period)) | |
372 | + | then true | |
373 | + | else (period > latestPeriod)) | |
374 | + | then throw("Invalid period") | |
375 | + | else { | |
376 | + | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(period)) | |
377 | + | let $t01767317914 = if ((totalWeight > 0)) | |
378 | + | then $Tuple2((getNumberByKey(keyTotalAmountForPeriod(period, true)) / totalWeight), (getNumberByKey(keyTotalAmountForPeriod(period, false)) / totalWeight)) | |
379 | + | else $Tuple2(0, 0) | |
380 | + | let wavesPerGNsbt = $t01767317914._1 | |
381 | + | let usdnPerGNsbt = $t01767317914._2 | |
382 | + | $Tuple2(nil, [wavesPerGNsbt, usdnPerGNsbt]) | |
383 | + | } | |
384 | + | } | |
385 | 385 | ||
386 | 386 | ||
387 | 387 |
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 | 12 | let SCALE = 1000 | |
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 IdxCfgNeutrinoContract = 1 | |
24 | 24 | ||
25 | 25 | let IdxCfgNsbtLockContract = 2 | |
26 | 26 | ||
27 | 27 | let IdxCfgMaxDepth = 3 | |
28 | 28 | ||
29 | 29 | let IdxCfgPeriodDelay = 4 | |
30 | 30 | ||
31 | 31 | func keyConfig () = "%s__config" | |
32 | 32 | ||
33 | 33 | ||
34 | 34 | func readConfigArrayOrFail () = split(getStringOrFail(keyConfig()), SEP) | |
35 | 35 | ||
36 | 36 | ||
37 | 37 | func formatConfig (neutrinoContractAddressStr,nsbtLockContractAddressStr,maxDepth,periodDelay) = makeString(["%s%s%d%d", neutrinoContractAddressStr, nsbtLockContractAddressStr, toString(maxDepth), toString(periodDelay)], SEP) | |
38 | 38 | ||
39 | 39 | ||
40 | 40 | func keyUsersCount () = "%s__nextUserNum" | |
41 | + | ||
42 | + | ||
43 | + | func keyMaxLockDuration () = "%s__maxLockDuration" | |
41 | 44 | ||
42 | 45 | ||
43 | 46 | func keyNextProcessedUser () = "%s__nextProcessedUser" | |
44 | 47 | ||
45 | 48 | ||
46 | 49 | func keyLatestPeriod () = "%s__latestPeriod" | |
47 | 50 | ||
48 | 51 | ||
49 | 52 | func keyNextPeriod () = "%s__nextPeriod" | |
50 | 53 | ||
51 | 54 | ||
52 | 55 | func keyNextProcessedPeriod () = "%s__nextProcessedPeriod" | |
53 | 56 | ||
54 | 57 | ||
55 | 58 | func keyNextUnlaimedPeriodOfUser (userIndex) = makeString(["%s%d__nextClaimedPeriod", toString(userIndex)], SEP) | |
56 | 59 | ||
57 | 60 | ||
58 | 61 | func keyLastProcessedPeriodOfUser (userIndex) = makeString(["%s%d__lastProcessedPeriod", toString(userIndex)], SEP) | |
59 | 62 | ||
60 | 63 | ||
61 | 64 | func keyHeightForPeriod (period) = makeString(["%s%d__startHeightForPeriod", toString(period)], SEP) | |
62 | 65 | ||
63 | 66 | ||
64 | 67 | func keyTotalAmountForPeriod (period,isWaves) = makeString([if (isWaves) | |
65 | 68 | then "%s%d__totalWavesAmountForPeriod" | |
66 | 69 | else "%s%d__totalUsdnAmountForPeriod", toString(period)], SEP) | |
67 | 70 | ||
68 | 71 | ||
69 | 72 | func keyTotalAmount (isWaves) = if (isWaves) | |
70 | 73 | then "%s__totalWavesAmount" | |
71 | 74 | else "%s__totalUsdnAmount" | |
72 | 75 | ||
73 | 76 | ||
74 | 77 | func keyTotalWeightForPeriod (period) = makeString(["%s%d__totalWeightForPeriod", toString(period)], SEP) | |
75 | 78 | ||
76 | 79 | ||
77 | 80 | func keyUserKValueForPeriod (period,userIndex) = makeString(["%s%d%s%d__paramByPeriod", toString(userIndex), "k", toString(period)], SEP) | |
78 | 81 | ||
79 | 82 | ||
80 | 83 | func keyUserBValueForPeriod (period,userIndex) = makeString(["%s%d%s%d__paramByPeriod", toString(userIndex), "b", toString(period)], SEP) | |
81 | 84 | ||
82 | 85 | ||
83 | 86 | func HistoryEntry (type,user,usdnAmount,wavesAamount,currentPeriod,latestPeriod,i) = { | |
84 | 87 | let historyKEY = makeString(["%s%s%s%s__history", type, user, toBase58String(i.transactionId)], SEP) | |
85 | 88 | let historyDATA = makeString(["%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(usdnAmount), toString(wavesAamount), toString(currentPeriod), toString(latestPeriod)], SEP) | |
86 | 89 | StringEntry(historyKEY, historyDATA) | |
87 | 90 | } | |
88 | 91 | ||
89 | 92 | ||
90 | 93 | func getUsdnAssetId (neutrinoContractAddress) = valueOrErrorMessage(getString(neutrinoContractAddress, "neutrino_asset_id"), "mandatory key neutrino_asset_id is not defined") | |
91 | 94 | ||
92 | 95 | ||
93 | 96 | func getNsbtAssetId (neutrinoContractAddress) = valueOrErrorMessage(getString(neutrinoContractAddress, "bond_asset_id"), "mandatory key bond_asset_id is not defined") | |
94 | 97 | ||
95 | 98 | ||
96 | - | func calcWeight (nsbtLockContractAddress,period,user,periodHeight,periods,users) = { | |
97 | - | let k = value(getInteger(nsbtLockContractAddress, keyUserKValueForPeriod(period, user))) | |
98 | - | let b = value(getInteger(nsbtLockContractAddress, keyUserBValueForPeriod(period, user))) | |
99 | - | let w = ((k * periodHeight) + b) | |
100 | - | if ((w > 0)) | |
101 | - | then $Tuple4((w / SCALE), nil, periods, users) | |
102 | - | else $Tuple4(0, nil, periods, users) | |
103 | - | } | |
104 | - | ||
105 | - | ||
106 | - | func calcUserWeight (nsbtLockContractAddress,heightForPeriod,period,userIndex,periods,users) = { | |
99 | + | func calcUserWeight (nsbtLockContractAddress,heightForPeriod,period,userIndex) = { | |
107 | 100 | let kLast = keyLastProcessedPeriodOfUser(userIndex) | |
108 | 101 | let kKey = keyUserKValueForPeriod(period, userIndex) | |
109 | 102 | let kRaw = getInteger(nsbtLockContractAddress, kKey) | |
110 | 103 | if (isDefined(kRaw)) | |
111 | 104 | then { | |
112 | 105 | let k = value(kRaw) | |
113 | 106 | let b = value(getInteger(nsbtLockContractAddress, keyUserBValueForPeriod(period, userIndex))) | |
114 | 107 | let w = ((k * heightForPeriod) + b) | |
115 | 108 | if ((w > 0)) | |
116 | - | then { | |
117 | - | let idx = indexOf(users, userIndex) | |
118 | - | if (isDefined(idx)) | |
119 | - | then $Tuple4((w / SCALE), [IntegerEntry(kLast, period)], (removeByIndex(periods, value(idx)) :+ period), (removeByIndex(users, value(idx)) :+ userIndex)) | |
120 | - | else $Tuple4((w / SCALE), [IntegerEntry(kLast, period)], (periods :+ period), (users :+ userIndex)) | |
121 | - | } | |
122 | - | else $Tuple4(0, nil, periods, users) | |
109 | + | then $Tuple2((w / SCALE), [IntegerEntry(kLast, period)]) | |
110 | + | else $Tuple2(0, nil) | |
123 | 111 | } | |
124 | 112 | else { | |
125 | 113 | let p = getInteger(this, kLast) | |
126 | 114 | if (isDefined(p)) | |
127 | - | then calcWeight(nsbtLockContractAddress, value(p), userIndex, heightForPeriod, periods, users) | |
128 | - | else { | |
129 | - | let idx = indexOf(users, userIndex) | |
130 | - | if (isDefined(idx)) | |
131 | - | then calcWeight(nsbtLockContractAddress, periods[value(idx)], userIndex, heightForPeriod, periods, users) | |
132 | - | else $Tuple4(0, nil, periods, users) | |
115 | + | then { | |
116 | + | let pv = value(p) | |
117 | + | let k = value(getInteger(nsbtLockContractAddress, keyUserKValueForPeriod(pv, userIndex))) | |
118 | + | let b = value(getInteger(nsbtLockContractAddress, keyUserBValueForPeriod(pv, userIndex))) | |
119 | + | let w = ((k * heightForPeriod) + b) | |
120 | + | if ((w > 0)) | |
121 | + | then $Tuple2((w / SCALE), nil) | |
122 | + | else $Tuple2(0, nil) | |
133 | 123 | } | |
124 | + | else $Tuple2(0, nil) | |
134 | 125 | } | |
135 | 126 | } | |
136 | 127 | ||
137 | 128 | ||
138 | 129 | func getUserIndexByAddress (nsbtLockContractAddressStr,userAddress) = { | |
139 | 130 | let key = makeString(["%s%s%s", "mapping", "user2num", userAddress], SEP) | |
140 | 131 | valueOrErrorMessage(getInteger(Address(fromBase58String(nsbtLockContractAddressStr)), key), ((("User address " + userAddress) + " is not found in nsbtLock contract data, key=") + key)) | |
141 | 132 | } | |
142 | 133 | ||
143 | 134 | ||
144 | 135 | func nextPeriod () = getNumberByKey(keyNextPeriod()) | |
145 | 136 | ||
146 | 137 | ||
147 | 138 | func DepositEntry (period,pmt,finalize) = [IntegerEntry(keyLatestPeriod(), if (finalize) | |
148 | 139 | then (period - 1) | |
149 | 140 | else -1), IntegerEntry(keyHeightForPeriod(period), height), IntegerEntry(keyTotalAmountForPeriod(period, (pmt.assetId == unit)), pmt.amount), IntegerEntry(keyTotalAmount((pmt.assetId == unit)), (getNumberByKey(keyTotalAmount((pmt.assetId == unit))) + pmt.amount)), IntegerEntry(keyNextPeriod(), period)] | |
150 | 141 | ||
151 | 142 | ||
152 | - | func invokeProcess (nsbtLockContract,period,user,depth,weight | |
153 | - | let result = invoke(this, "processNextBatch", [nsbtLockContract, period, user, depth, weight | |
143 | + | func invokeProcess (nsbtLockContract,period,user,depth,weight) = { | |
144 | + | let result = invoke(this, "processNextBatch", [nsbtLockContract, period, user, depth, weight], nil) | |
154 | 145 | if ((result == result)) | |
155 | 146 | then match result { | |
156 | - | case r: (Int, Int, | |
147 | + | case r: (Int, Int, Int) => | |
157 | 148 | r | |
158 | 149 | case _ => | |
159 | 150 | throw("Incorrect invoke result") | |
160 | 151 | } | |
161 | 152 | else throw("Strict value is not equal to itself.") | |
162 | 153 | } | |
163 | 154 | ||
164 | 155 | ||
165 | - | func checkLastPartOfPeriod (nsbtLockContract,currentPeriod,latestPeriod,depth,periods,users) = if ((latestPeriod >= (currentPeriod + 1))) | |
166 | - | then invokeProcess(nsbtLockContract, (currentPeriod + 1), 0, (depth - 1), 0, periods, users) | |
167 | - | else $Tuple5((currentPeriod + 1), 0, nil, nil, 0) | |
168 | - | ||
169 | - | ||
170 | - | func processNextBatchInternal (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight,periods,users) = { | |
156 | + | func processNextBatchInternal (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight) = { | |
171 | 157 | let nsbtLockContractAddress = Address(nsbtLockContract) | |
172 | 158 | let latestPeriod = getNumberByKey(keyLatestPeriod()) | |
173 | 159 | let usersCount = valueOrElse(getInteger(nsbtLockContractAddress, keyUsersCount()), 0) | |
174 | 160 | let totalWeightKey = keyTotalWeightForPeriod(currentPeriod) | |
175 | 161 | let heightForPeriod = getNumberByKey(keyHeightForPeriod(currentPeriod)) | |
176 | 162 | if (if ((depth > 0)) | |
177 | 163 | then (latestPeriod >= currentPeriod) | |
178 | 164 | else false) | |
179 | 165 | then { | |
180 | - | let t0 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, currentUser | |
166 | + | let t0 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, currentUser) | |
181 | 167 | let weight0 = (totalWeight + t0._1) | |
182 | 168 | if ((usersCount > (currentUser + 1))) | |
183 | 169 | then { | |
184 | - | let t1 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 1) | |
170 | + | let t1 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 1)) | |
185 | 171 | let weight1 = (weight0 + t1._1) | |
186 | 172 | if ((usersCount > (currentUser + 2))) | |
187 | 173 | then { | |
188 | - | let t2 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 2) | |
174 | + | let t2 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 2)) | |
189 | 175 | let weight2 = (weight1 + t2._1) | |
190 | 176 | if ((usersCount > (currentUser + 3))) | |
191 | 177 | then { | |
192 | - | let t3 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 3) | |
178 | + | let t3 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 3)) | |
193 | 179 | let weight3 = (weight2 + t3._1) | |
194 | 180 | if ((usersCount > (currentUser + 4))) | |
195 | 181 | then { | |
196 | - | let t4 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 4) | |
182 | + | let t4 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 4)) | |
197 | 183 | let weight4 = (weight3 + t4._1) | |
198 | 184 | if ((usersCount > (currentUser + 5))) | |
199 | 185 | then { | |
200 | - | let t5 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 5) | |
186 | + | let t5 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, (currentUser + 5)) | |
201 | 187 | let weight5 = (weight4 + t5._1) | |
202 | 188 | if ((usersCount > (currentUser + 6))) | |
203 | 189 | then { | |
204 | - | let r5 = invokeProcess(nsbtLockContract, currentPeriod, (currentUser + 6), (depth - 1), weight5 | |
205 | - | $ | |
190 | + | let r5 = invokeProcess(nsbtLockContract, currentPeriod, (currentUser + 6), (depth - 1), weight5) | |
191 | + | $Tuple4((((((t0._2 ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3) | |
206 | 192 | } | |
207 | - | else { | |
208 | - | let r5 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t5._3, t5._4) | |
209 | - | $Tuple6((((((([IntegerEntry(totalWeightKey, weight5)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), r5._1, r5._2, r5._3, r5._4, r5._5) | |
210 | - | } | |
193 | + | else $Tuple4((((((([IntegerEntry(totalWeightKey, weight5)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2) ++ t5._2), (currentPeriod + 1), 0, 0) | |
211 | 194 | } | |
212 | - | else { | |
213 | - | let r4 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t4._3, t4._4) | |
214 | - | $Tuple6(((((([IntegerEntry(totalWeightKey, weight4)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2), r4._1, r4._2, r4._3, r4._4, r4._5) | |
215 | - | } | |
195 | + | else $Tuple4(((((([IntegerEntry(totalWeightKey, weight4)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2) ++ t4._2), (currentPeriod + 1), 0, 0) | |
216 | 196 | } | |
217 | - | else { | |
218 | - | let r3 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t3._3, t3._4) | |
219 | - | $Tuple6((((([IntegerEntry(totalWeightKey, weight3)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2), r3._1, r3._2, r3._3, r3._4, r3._5) | |
220 | - | } | |
197 | + | else $Tuple4((((([IntegerEntry(totalWeightKey, weight3)] ++ t0._2) ++ t1._2) ++ t2._2) ++ t3._2), (currentPeriod + 1), 0, 0) | |
221 | 198 | } | |
222 | - | else { | |
223 | - | let r2 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t2._3, t2._4) | |
224 | - | $Tuple6(((([IntegerEntry(totalWeightKey, weight2)] ++ t0._2) ++ t1._2) ++ t2._2), r2._1, r2._2, r2._3, r2._4, r2._5) | |
225 | - | } | |
199 | + | else $Tuple4(((([IntegerEntry(totalWeightKey, weight2)] ++ t0._2) ++ t1._2) ++ t2._2), (currentPeriod + 1), 0, 0) | |
226 | 200 | } | |
227 | - | else { | |
228 | - | let r1 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t1._3, t1._4) | |
229 | - | $Tuple6((([IntegerEntry(totalWeightKey, weight1)] ++ t0._2) ++ t1._2), r1._1, r1._2, r1._3, r1._4, r1._5) | |
230 | - | } | |
201 | + | else $Tuple4((([IntegerEntry(totalWeightKey, weight1)] ++ t0._2) ++ t1._2), (currentPeriod + 1), 0, 0) | |
231 | 202 | } | |
232 | - | else { | |
233 | - | let r0 = checkLastPartOfPeriod(nsbtLockContract, currentPeriod, latestPeriod, depth, t0._3, t0._4) | |
234 | - | $Tuple6(([IntegerEntry(totalWeightKey, weight0)] ++ t0._2), r0._1, r0._2, r0._3, r0._4, r0._5) | |
235 | - | } | |
203 | + | else $Tuple4(([IntegerEntry(totalWeightKey, weight0)] ++ t0._2), (currentPeriod + 1), 0, 0) | |
236 | 204 | } | |
237 | 205 | else if ((currentUser == 0)) | |
238 | - | then $ | |
239 | - | else $ | |
206 | + | then $Tuple4(nil, currentPeriod, 0, 0) | |
207 | + | else $Tuple4([IntegerEntry(totalWeightKey, totalWeight)], currentPeriod, currentUser, 0) | |
240 | 208 | } | |
241 | 209 | ||
242 | 210 | ||
243 | 211 | func invokeClaim (nsbtLockContract,period,user,depth,totalUsdn,totalWaves) = { | |
244 | 212 | let result = invoke(this, "claimNextBatch", [nsbtLockContract, period, user, depth, totalUsdn, totalWaves], nil) | |
245 | 213 | if ((result == result)) | |
246 | 214 | then match result { | |
247 | 215 | case r: (Int, Int, Int) => | |
248 | 216 | r | |
249 | 217 | case _ => | |
250 | 218 | throw("Incorrect invoke result") | |
251 | 219 | } | |
252 | 220 | else throw("Strict value is not equal to itself.") | |
253 | 221 | } | |
254 | 222 | ||
255 | 223 | ||
256 | 224 | func claimInternal (nsbtLockContract,currentPeriod,currentUser,depth,userUsdnAccumulated,userWavesAccumulated) = { | |
257 | 225 | let nsbtLockContractAddress = Address(nsbtLockContract) | |
258 | 226 | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
259 | 227 | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
260 | 228 | let heightForPeriod = getNumberByKey(keyHeightForPeriod(currentPeriod)) | |
261 | - | let $ | |
262 | - | let userWeight = $ | |
263 | - | let ignored = $ | |
229 | + | let $t01096311075 = calcUserWeight(nsbtLockContractAddress, heightForPeriod, currentPeriod, currentUser) | |
230 | + | let userWeight = $t01096311075._1 | |
231 | + | let ignored = $t01096311075._2 | |
264 | 232 | let userUsdnAmountForPeriod = fraction(getNumberByKey(keyTotalAmountForPeriod(currentPeriod, false)), userWeight, totalWeight) | |
265 | 233 | let userWavesAmountForPeriod = fraction(getNumberByKey(keyTotalAmountForPeriod(currentPeriod, true)), userWeight, totalWeight) | |
266 | 234 | if (if ((0 >= depth)) | |
267 | 235 | then true | |
268 | 236 | else ((currentPeriod + 1) >= latestPeriod)) | |
269 | 237 | then $Tuple3((currentPeriod + 1), (userUsdnAccumulated + userUsdnAmountForPeriod), (userWavesAccumulated + userWavesAmountForPeriod)) | |
270 | 238 | else invokeClaim(nsbtLockContract, (currentPeriod + 1), currentUser, (depth - 1), (userUsdnAccumulated + userUsdnAmountForPeriod), (userWavesAccumulated + userWavesAmountForPeriod)) | |
271 | 239 | } | |
272 | 240 | ||
273 | 241 | ||
274 | 242 | @Callable(i) | |
275 | - | func processNextBatch (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight | |
243 | + | func processNextBatch (nsbtLockContract,currentPeriod,currentUser,depth,totalWeight) = if ((i.caller != this)) | |
276 | 244 | then throw("Should be called by this script only") | |
277 | 245 | else { | |
278 | - | let tpl = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight | |
279 | - | $Tuple2(tpl._1, $ | |
246 | + | let tpl = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight) | |
247 | + | $Tuple2(tpl._1, $Tuple3(tpl._2, tpl._3, tpl._4)) | |
280 | 248 | } | |
281 | 249 | ||
282 | 250 | ||
283 | 251 | ||
284 | 252 | @Callable(i) | |
285 | 253 | func processPendingPeriodsAndUsers () = { | |
286 | 254 | let currentPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
287 | 255 | if ((currentPeriod > getNumberByKey(keyLatestPeriod()))) | |
288 | 256 | then throw("Nothing to process") | |
289 | 257 | else { | |
290 | 258 | let cfgArray = readConfigArrayOrFail() | |
291 | 259 | let depth = parseIntValue(cfgArray[IdxCfgMaxDepth]) | |
292 | 260 | if ((depth > MAXDEPTH)) | |
293 | 261 | then throw("Depth exceeds MAXDEPTH") | |
294 | 262 | else { | |
295 | 263 | let nsbtLockContract = fromBase58String(cfgArray[IdxCfgNsbtLockContract]) | |
296 | 264 | let currentUser = getNumberByKey(keyNextProcessedUser()) | |
297 | 265 | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(currentPeriod)) | |
298 | - | let r = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight | |
266 | + | let r = processNextBatchInternal(nsbtLockContract, currentPeriod, currentUser, depth, totalWeight) | |
299 | 267 | ((r._1 :+ IntegerEntry(keyNextProcessedPeriod(), r._2)) :+ IntegerEntry(keyNextProcessedUser(), r._3)) | |
300 | 268 | } | |
301 | 269 | } | |
302 | 270 | } | |
303 | 271 | ||
304 | 272 | ||
305 | 273 | ||
306 | 274 | @Callable(i) | |
307 | 275 | func deposit () = { | |
308 | 276 | let cfgArray = readConfigArrayOrFail() | |
309 | 277 | let neutrinoContract = Address(fromBase58String(cfgArray[IdxCfgNeutrinoContract])) | |
310 | 278 | if ((i.caller != neutrinoContract)) | |
311 | 279 | then throw("Wrong caller address") | |
312 | 280 | else { | |
313 | 281 | let pmt = value(i.payments[0]) | |
314 | 282 | let assetId = pmt.assetId | |
315 | 283 | let period = getNumberByKey(keyNextPeriod()) | |
316 | 284 | let hRaw = getInteger(this, keyHeightForPeriod(period)) | |
317 | 285 | let delay = parseIntValue(cfgArray[IdxCfgPeriodDelay]) | |
318 | 286 | if (!(isDefined(hRaw))) | |
319 | 287 | then DepositEntry(period, pmt, false) | |
320 | 288 | else if ((height >= (value(hRaw) + delay))) | |
321 | 289 | then DepositEntry((period + 1), pmt, true) | |
322 | 290 | else { | |
323 | 291 | let keyAmount = keyTotalAmountForPeriod(period, (assetId == unit)) | |
324 | 292 | [IntegerEntry(keyAmount, (getNumberByKey(keyAmount) + pmt.amount)), IntegerEntry(keyTotalAmount((assetId == unit)), (getNumberByKey(keyTotalAmount((assetId == unit))) + pmt.amount))] | |
325 | 293 | } | |
326 | 294 | } | |
327 | 295 | } | |
328 | 296 | ||
329 | 297 | ||
330 | 298 | ||
331 | 299 | @Callable(i) | |
332 | 300 | func claimNextBatch (nsbtLockContract,currentPeriod,currentUser,depth,usdnAccumulated,wavesAccumulated) = if ((i.caller != this)) | |
333 | 301 | then throw("Should be called by this script only") | |
334 | 302 | else { | |
335 | 303 | let periodAndTotals = claimInternal(nsbtLockContract, currentPeriod, currentUser, depth, usdnAccumulated, wavesAccumulated) | |
336 | 304 | $Tuple2(nil, periodAndTotals) | |
337 | 305 | } | |
338 | 306 | ||
339 | 307 | ||
340 | 308 | ||
341 | 309 | @Callable(i) | |
342 | 310 | func claimReward () = { | |
343 | 311 | let cfgArray = readConfigArrayOrFail() | |
344 | 312 | let address = toString(i.caller) | |
345 | 313 | let userIdx = getUserIndexByAddress(cfgArray[IdxCfgNsbtLockContract], address) | |
346 | 314 | let currentPeriod = getNumberByKey(keyNextUnlaimedPeriodOfUser(userIdx)) | |
347 | 315 | let latestPeriod = getNumberByKey(keyNextProcessedPeriod()) | |
348 | 316 | if ((currentPeriod >= latestPeriod)) | |
349 | 317 | then throw("Nothing to claim") | |
350 | 318 | else { | |
351 | 319 | let nsbtLockContract = fromBase58String(cfgArray[IdxCfgNsbtLockContract]) | |
352 | - | let $ | |
353 | - | let period = $ | |
354 | - | let usdnAmount = $ | |
355 | - | let wavesAmount = $ | |
320 | + | let $t01558715699 = claimInternal(nsbtLockContract, currentPeriod, userIdx, USERDEPTH, 0, 0) | |
321 | + | let period = $t01558715699._1 | |
322 | + | let usdnAmount = $t01558715699._2 | |
323 | + | let wavesAmount = $t01558715699._3 | |
356 | 324 | if (if ((0 >= usdnAmount)) | |
357 | 325 | then (0 >= wavesAmount) | |
358 | 326 | else false) | |
359 | 327 | then throw("No payouts available") | |
360 | 328 | else { | |
361 | 329 | let neutrinoContract = Address(fromBase58String(cfgArray[IdxCfgNeutrinoContract])) | |
362 | 330 | $Tuple2(([IntegerEntry(keyNextUnlaimedPeriodOfUser(userIdx), period), HistoryEntry("claimReward", address, usdnAmount, wavesAmount, period, latestPeriod, i)] ++ (if ((usdnAmount > 0)) | |
363 | 331 | then [ScriptTransfer(i.caller, usdnAmount, fromBase58String(getUsdnAssetId(neutrinoContract))), IntegerEntry(keyTotalAmount(false), (getNumberByKey(keyTotalAmount(false)) - usdnAmount))] | |
364 | 332 | else (nil ++ (if ((wavesAmount > 0)) | |
365 | 333 | then [ScriptTransfer(i.caller, wavesAmount, unit), IntegerEntry(keyTotalAmount(true), (getNumberByKey(keyTotalAmount(true)) - wavesAmount))] | |
366 | 334 | else nil)))), $Tuple2(usdnAmount, wavesAmount)) | |
367 | 335 | } | |
368 | 336 | } | |
369 | 337 | } | |
370 | 338 | ||
371 | 339 | ||
372 | 340 | ||
373 | 341 | @Callable(i) | |
374 | - | func calcGovernanceParamsREADONLY (nsbtAmount,lockStartHeight,lockDurationBlocks) = { | |
342 | + | func calcGovernanceParamsREADONLY (nsbtLockedAmount,lockStartHeight,lockDurationBlocks) = { | |
343 | + | let cfgArray = readConfigArrayOrFail() | |
344 | + | let nsbtLockContract = fromBase58String(cfgArray[IdxCfgNsbtLockContract]) | |
345 | + | let maxDuration = getIntegerValue(Address(nsbtLockContract), keyMaxLockDuration()) | |
375 | 346 | let lockEndHeight = (lockStartHeight + lockDurationBlocks) | |
376 | - | let | |
377 | - | let | |
378 | - | $Tuple2(nil, [ | |
347 | + | let k = -(fraction(nsbtLockedAmount, SCALE, maxDuration)) | |
348 | + | let b = (-(k) * lockEndHeight) | |
349 | + | $Tuple2(nil, [k, b, nextPeriod()]) | |
379 | 350 | } | |
380 | 351 | ||
381 | 352 | ||
382 | 353 | ||
383 | 354 | @Callable(i) | |
384 | 355 | func getTotalRewardREADONLY () = $Tuple2(nil, [getNumberByKey(keyTotalAmount(false)), getNumberByKey(keyTotalAmount(true))]) | |
356 | + | ||
357 | + | ||
358 | + | ||
359 | + | @Callable(i) | |
360 | + | func paramsREADONLY () = { | |
361 | + | let cfgArray = readConfigArrayOrFail() | |
362 | + | let periodDelay = parseIntValue(cfgArray[IdxCfgPeriodDelay]) | |
363 | + | $Tuple2(nil, [periodDelay]) | |
364 | + | } | |
365 | + | ||
366 | + | ||
367 | + | ||
368 | + | @Callable(i) | |
369 | + | func rewardsPerGNsbtForPeriodREADONLY (period) = { | |
370 | + | let latestPeriod = getNumberByKey(keyLatestPeriod()) | |
371 | + | if (if ((0 > period)) | |
372 | + | then true | |
373 | + | else (period > latestPeriod)) | |
374 | + | then throw("Invalid period") | |
375 | + | else { | |
376 | + | let totalWeight = getNumberByKey(keyTotalWeightForPeriod(period)) | |
377 | + | let $t01767317914 = if ((totalWeight > 0)) | |
378 | + | then $Tuple2((getNumberByKey(keyTotalAmountForPeriod(period, true)) / totalWeight), (getNumberByKey(keyTotalAmountForPeriod(period, false)) / totalWeight)) | |
379 | + | else $Tuple2(0, 0) | |
380 | + | let wavesPerGNsbt = $t01767317914._1 | |
381 | + | let usdnPerGNsbt = $t01767317914._2 | |
382 | + | $Tuple2(nil, [wavesPerGNsbt, usdnPerGNsbt]) | |
383 | + | } | |
384 | + | } | |
385 | 385 | ||
386 | 386 | ||
387 | 387 | ||
388 | 388 | @Callable(i) | |
389 | 389 | func constructor (neutrinoContractAddressStr,nsbtLockContractAddressStr,maxDepth,periodDelay) = if ((this != i.caller)) | |
390 | 390 | then throw("not authorized") | |
391 | 391 | else [StringEntry(keyConfig(), formatConfig(neutrinoContractAddressStr, nsbtLockContractAddressStr, maxDepth, periodDelay))] | |
392 | 392 | ||
393 | 393 |
github/deemru/w8io/169f3d6 746.09 ms ◑![]()