tx · HTxJqi7dKQfP4Hv4izxRpjLK6GuokUSqeT8BGEGX9Src 3P5x9RxuqbMaVFPsaycvXHeFZXPmcswxA1c: -0.01000000 Waves 2022.11.02 13:18 [3364710] smart account 3P5x9RxuqbMaVFPsaycvXHeFZXPmcswxA1c > SELF 0.00000000 Waves
{ "type": 13, "id": "HTxJqi7dKQfP4Hv4izxRpjLK6GuokUSqeT8BGEGX9Src", "fee": 1000000, "feeAssetId": null, "timestamp": 1667384290540, "version": 2, "chainId": 87, "sender": "3P5x9RxuqbMaVFPsaycvXHeFZXPmcswxA1c", "senderPublicKey": "9uEm8fN7ZMqn6sPuc39LRogUGXKNPPmRThGEL4GAqGa3", "proofs": [ "3fQQYZSJqHuijtFzNWwAEUage3FoqhRiM1mq3wMwJRTKuk9GaY1k7Hja25Z62zcy6uoLxgSYHQYbmskFi5NZ3H2U" ], "script": "base64:BgIWCAISAwoBCBIDCgEBEgQKAgEBEgASAA4AC1NUQVJUX1BSSUNFAKDCHgAIUVVPVElFTlQAAgAIREVDSU1BTFMAgMLXLwEOa2V5VXNlckFkZHJlc3MBB2FkZHJlc3MJAKwCAgUHYWRkcmVzcwIGX2xldmVsARNrZXlVc2VyU3BlbnRPbkxldmVsAQdhZGRyZXNzCQCsAgIFB2FkZHJlc3MCDV9zcGVudE9uTGV2ZWwBFmtleVVzZXJTa2lsbFJlc2V0VGltZXMBB2FkZHJlc3MJAKwCAgUHYWRkcmVzcwIRX3NraWxsc1Jlc2V0VGltZXMBE2tleVVzZXJTcGVudE9uUmVzZXQBB2FkZHJlc3MJAKwCAgUHYWRkcmVzcwINX3NwZW50T25SZXNldAENdHJ5R2V0SW50ZWdlcgEDa2V5BAckbWF0Y2gwCQCaCAIFBHRoaXMFA2tleQMJAAECBQckbWF0Y2gwAgNJbnQEAWIFByRtYXRjaDAFAWIAAAEUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwCB2FkZHJlc3MDa2V5BAckbWF0Y2gwCQCdCAIFB2FkZHJlc3MFA2tleQMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAWEFByRtYXRjaDAFAWECAAEMdHJ5R2V0U3RyaW5nAQNrZXkJARR0cnlHZXRTdHJpbmdFeHRlcm5hbAIFBHRoaXMFA2tleQEJZ2V0T3JhY2xlAAkBB0FkZHJlc3MBCQDZBAEJAQx0cnlHZXRTdHJpbmcBAhRzdGF0aWNfb3JhY2xlQWRkcmVzcwENZ2V0RWdnQXNzZXRJZAAJANkEAQkBFHRyeUdldFN0cmluZ0V4dGVybmFsAgkBCWdldE9yYWNsZQACEXN0YXRpY19lZ2dBc3NldElkARBjYWxjdWxhdGVMZXZlbFVwAQtmdXR1cmVMZXZlbAQCcDEJAGwGBQtTVEFSVF9QUklDRQAICQBpAgCQTgULZnV0dXJlTGV2ZWwABAAIBQdDRUlMSU5HBAJwMgkAbAYFC2Z1dHVyZUxldmVsAAAJAGkCAJBOBQhRVU9USUVOVAAEAAgFB0NFSUxJTkcEBXRvdGFsCQBrAwUCcDEFAnAyBQhERUNJTUFMUwQFZGVidWcJALkJAgkAzAgCCQCsAgICCW5ld0xldmVsPQkApAMBBQtmdXR1cmVMZXZlbAkAzAgCCQCsAgICA3AxPQkApAMBBQJwMQkAzAgCCQCsAgICA3AyPQkApAMBBQJwMgkAzAgCCQCsAgICBnRvdGFsPQkApAMBBQV0b3RhbAUDbmlsAgE7CQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgIFREVCVUcFBWRlYnVnBQNuaWwFBXRvdGFsAQ5jYWxjdWxhdGVSZXNldAIMY3VycmVudExldmVsCnJlc2V0VGltZXMEB0RFVklERVIABAQPcmVzZXRUaW1lc1RvVXNlCQBkAgUKcmVzZXRUaW1lcwABBAZyZXN1bHQJAGsDBQ9yZXNldFRpbWVzVG9Vc2UJAGgCBQxjdXJyZW50TGV2ZWwFCERFQ0lNQUxTBQdERVZJREVSBAVkZWJ1ZwkAuQkCCQDMCAIJAKwCAgIGbGV2ZWw9CQCkAwEFDGN1cnJlbnRMZXZlbAkAzAgCCQCsAgICC3Jlc2V0VGltZXM9CQCkAwEFCnJlc2V0VGltZXMJAMwIAgkArAICAhByZXNldFRpbWVzVG9Vc2U9CQCkAwEFD3Jlc2V0VGltZXNUb1VzZQkAzAgCCQCsAgICB3Jlc3VsdD0JAKQDAQUGcmVzdWx0BQNuaWwCATsJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCAgVERUJVRwUFZGVidWcFA25pbAUGcmVzdWx0BQFpAQ9jb25maWd1cmVPcmFjbGUBBm9yYWNsZQMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECD1JDTzogYWRtaW4gb25seQkAzAgCCQELU3RyaW5nRW50cnkCAhRzdGF0aWNfb3JhY2xlQWRkcmVzcwUGb3JhY2xlBQNuaWwBaQELbGV2ZWxVcE1hdGgBC2Z1dHVyZUxldmVsCQEQY2FsY3VsYXRlTGV2ZWxVcAEFC2Z1dHVyZUxldmVsAWkBD3Jlc2V0U2tpbGxzTWF0aAIMY3VycmVudExldmVsCnJlc2V0VGltZXMJAQ5jYWxjdWxhdGVSZXNldAIFDGN1cnJlbnRMZXZlbAUKcmVzZXRUaW1lcwFpAQdsZXZlbFVwAAQUa2V5VXNlckFkZHJlc3NGaWxsZWQJAQ5rZXlVc2VyQWRkcmVzcwEJAKUIAQgFAWkGY2FsbGVyBBlrZXlVc2VyU3BlbnRPbkxldmVsRmlsbGVkCQETa2V5VXNlclNwZW50T25MZXZlbAEJAKUIAQgFAWkGY2FsbGVyBAtsZXZlbE9mVXNlcgkBDXRyeUdldEludGVnZXIBBRRrZXlVc2VyQWRkcmVzc0ZpbGxlZAQOdG90YWxTcGVudFVzZXIJAQ10cnlHZXRJbnRlZ2VyAQUZa2V5VXNlclNwZW50T25MZXZlbEZpbGxlZAQJcHJpY2VDYWxjCQEQY2FsY3VsYXRlTGV2ZWxVcAEJAGQCBQtsZXZlbE9mVXNlcgABBAVwcmljZQgFCXByaWNlQ2FsYwJfMgQMZmlyc3RQYXltZW50CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEBmFtb3VudAgFDGZpcnN0UGF5bWVudAZhbW91bnQDCQECIT0CCAUMZmlyc3RQYXltZW50B2Fzc2V0SWQJAQ1nZXRFZ2dBc3NldElkAAkAAgEJAKwCAgJBTExVOiBZb3UgY2FuIGF0dGFjaCBvbmx5IEVHRyB0b2tlbnMgd2l0aCB0aGUgZm9sbG93aW5nIGFzc2V0IGlkOiAJANgEAQkBDWdldEVnZ0Fzc2V0SWQAAwkBAiE9AgUGYW1vdW50BQVwcmljZQkAAgEJAKwCAgIpTExVOiBQbGVhc2UgYXR0YWNoIHRoZSBleGFjdCBhc3NldCBhbW91bnQJAKQDAQUFcHJpY2UJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUUa2V5VXNlckFkZHJlc3NGaWxsZWQJAGQCBQtsZXZlbE9mVXNlcgABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRlrZXlVc2VyU3BlbnRPbkxldmVsRmlsbGVkCQBkAgUOdG90YWxTcGVudFVzZXIFBmFtb3VudAUDbmlsCAUJcHJpY2VDYWxjAl8xAWkBBXJlc2V0AAQUa2V5VXNlckFkZHJlc3NGaWxsZWQJAQ5rZXlVc2VyQWRkcmVzcwEJAKUIAQgFAWkGY2FsbGVyBAtsZXZlbE9mVXNlcgkBDXRyeUdldEludGVnZXIBBRRrZXlVc2VyQWRkcmVzc0ZpbGxlZAQca2V5VXNlclNraWxsUmVzZXRUaW1lc0ZpbGxlZAkBFmtleVVzZXJTa2lsbFJlc2V0VGltZXMBCQClCAEIBQFpBmNhbGxlcgQMcmVzZXRzT2ZVc2VyCQENdHJ5R2V0SW50ZWdlcgEFHGtleVVzZXJTa2lsbFJlc2V0VGltZXNGaWxsZWQEGWtleVVzZXJTcGVudE9uUmVzZXRGaWxsZWQJARNrZXlVc2VyU3BlbnRPblJlc2V0AQkApQgBCAUBaQZjYWxsZXIEFGFtb3VudE9mU3BlbmRPblJlc2V0CQENdHJ5R2V0SW50ZWdlcgEFGWtleVVzZXJTcGVudE9uUmVzZXRGaWxsZWQEGGNhbGN1bGF0ZVJlc2V0Q2FsY3VsYXRlZAkBDmNhbGN1bGF0ZVJlc2V0AgULbGV2ZWxPZlVzZXIFDHJlc2V0c09mVXNlcgQFcHJpY2UIBRhjYWxjdWxhdGVSZXNldENhbGN1bGF0ZWQCXzIEDGZpcnN0UGF5bWVudAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAZhbW91bnQIBQxmaXJzdFBheW1lbnQGYW1vdW50AwkBAiE9AggFDGZpcnN0UGF5bWVudAdhc3NldElkCQENZ2V0RWdnQXNzZXRJZAAJAAIBCQCsAgICQExSOiBZb3UgY2FuIGF0dGFjaCBvbmx5IEVHRyB0b2tlbnMgd2l0aCB0aGUgZm9sbG93aW5nIGFzc2V0IGlkOiAJANgEAQkBDWdldEVnZ0Fzc2V0SWQAAwkBAiE9AgUGYW1vdW50BQVwcmljZQkAAgEJAKwCAgIoTFI6IFBsZWFzZSBhdHRhY2ggdGhlIGV4YWN0IGFzc2V0IGFtb3VudAkApAMBBQVwcmljZQkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRxrZXlVc2VyU2tpbGxSZXNldFRpbWVzRmlsbGVkCQBkAgUMcmVzZXRzT2ZVc2VyAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFGWtleVVzZXJTcGVudE9uUmVzZXRGaWxsZWQJAGQCBRRhbW91bnRPZlNwZW5kT25SZXNldAUGYW1vdW50BQNuaWwIBRhjYWxjdWxhdGVSZXNldENhbGN1bGF0ZWQCXzEAMhwDHg==", "height": 3364710, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3ZnqCPzxa59KrPfdLAgSo9H48bMhtCPvnfnvf53nk2PT Next: FqzC8FRHCiRjgzSDc4gSbdSSNRiEG6bT9RtaXg4UkDiB Diff:
Old | New | Differences | |
---|---|---|---|
54 | 54 | let t = pow(a, 8, (10000 / s), 4, 8, CEILING) | |
55 | 55 | let u = pow(s, 0, (10000 / b), 4, 8, CEILING) | |
56 | 56 | let v = fraction(t, u, c) | |
57 | - | let w = makeString([(" | |
57 | + | let w = makeString([("newLevel=" + toString(s)), ("p1=" + toString(t)), ("p2=" + toString(u)), ("total=" + toString(v))], ";") | |
58 | 58 | $Tuple2([StringEntry("DEBUG", w)], v) | |
59 | 59 | } | |
60 | 60 | ||
61 | 61 | ||
62 | - | func x ( | |
63 | - | let | |
64 | - | let | |
65 | - | let | |
66 | - | let w = makeString([("level=" + toString( | |
67 | - | $Tuple2([StringEntry("DEBUG", w)], | |
62 | + | func x (y,z) = { | |
63 | + | let A = 4 | |
64 | + | let B = (z + 1) | |
65 | + | let C = fraction(B, (y * c), A) | |
66 | + | let w = makeString([("level=" + toString(y)), ("resetTimes=" + toString(z)), ("resetTimesToUse=" + toString(B)), ("result=" + toString(C))], ";") | |
67 | + | $Tuple2([StringEntry("DEBUG", w)], C) | |
68 | 68 | } | |
69 | 69 | ||
70 | 70 | ||
71 | - | @Callable( | |
72 | - | func configureOracle ( | |
71 | + | @Callable(D) | |
72 | + | func configureOracle (E) = if ((D.caller != this)) | |
73 | 73 | then throw("RCO: admin only") | |
74 | - | else [StringEntry("static_oracleAddress", | |
74 | + | else [StringEntry("static_oracleAddress", E)] | |
75 | 75 | ||
76 | 76 | ||
77 | 77 | ||
78 | - | @Callable( | |
78 | + | @Callable(D) | |
79 | 79 | func levelUpMath (s) = r(s) | |
80 | 80 | ||
81 | 81 | ||
82 | 82 | ||
83 | - | @Callable( | |
84 | - | func resetSkillsMath ( | |
83 | + | @Callable(D) | |
84 | + | func resetSkillsMath (y,z) = x(y, z) | |
85 | 85 | ||
86 | 86 | ||
87 | 87 | ||
88 | - | @Callable( | |
88 | + | @Callable(D) | |
89 | 89 | func levelUp () = { | |
90 | - | let E = d(toString(C.caller)) | |
91 | - | let F = f(toString(C.caller)) | |
92 | - | let G = i(E) | |
90 | + | let F = d(toString(D.caller)) | |
91 | + | let G = f(toString(D.caller)) | |
93 | 92 | let H = i(F) | |
94 | - | let I = r(G) | |
95 | - | let J = I._2 | |
96 | - | let K = value(C.payments[0]) | |
97 | - | let L = K.amount | |
98 | - | if ((K.assetId != q())) | |
93 | + | let I = i(G) | |
94 | + | let J = r((H + 1)) | |
95 | + | let K = J._2 | |
96 | + | let L = value(D.payments[0]) | |
97 | + | let M = L.amount | |
98 | + | if ((L.assetId != q())) | |
99 | 99 | then throw(("LLU: You can attach only EGG tokens with the following asset id: " + toBase58String(q()))) | |
100 | - | else if (( | |
101 | - | then throw(("LLU: Please attach the exact asset amount" + toString( | |
102 | - | else ([IntegerEntry( | |
100 | + | else if ((M != K)) | |
101 | + | then throw(("LLU: Please attach the exact asset amount" + toString(K))) | |
102 | + | else ([IntegerEntry(F, (H + 1)), IntegerEntry(G, (I + M))] ++ J._1) | |
103 | 103 | } | |
104 | 104 | ||
105 | 105 | ||
106 | 106 | ||
107 | - | @Callable( | |
107 | + | @Callable(D) | |
108 | 108 | func reset () = { | |
109 | - | let | |
110 | - | let | |
111 | - | let | |
112 | - | let | |
113 | - | let | |
114 | - | let | |
115 | - | let | |
116 | - | let | |
117 | - | let | |
118 | - | let | |
119 | - | if (( | |
109 | + | let F = d(toString(D.caller)) | |
110 | + | let H = i(F) | |
111 | + | let N = g(toString(D.caller)) | |
112 | + | let O = i(N) | |
113 | + | let P = h(toString(D.caller)) | |
114 | + | let Q = i(P) | |
115 | + | let R = x(H, O) | |
116 | + | let K = R._2 | |
117 | + | let L = value(D.payments[0]) | |
118 | + | let M = L.amount | |
119 | + | if ((L.assetId != q())) | |
120 | 120 | then throw(("LR: You can attach only EGG tokens with the following asset id: " + toBase58String(q()))) | |
121 | - | else if (( | |
122 | - | then throw(("LR: Please attach the exact asset amount" + toString( | |
123 | - | else ([IntegerEntry( | |
121 | + | else if ((M != K)) | |
122 | + | then throw(("LR: Please attach the exact asset amount" + toString(K))) | |
123 | + | else ([IntegerEntry(N, (O + 1)), IntegerEntry(P, (Q + M))] ++ R._1) | |
124 | 124 | } | |
125 | 125 | ||
126 | 126 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let a = 500000 | |
5 | 5 | ||
6 | 6 | let b = 2 | |
7 | 7 | ||
8 | 8 | let c = 100000000 | |
9 | 9 | ||
10 | 10 | func d (e) = (e + "_level") | |
11 | 11 | ||
12 | 12 | ||
13 | 13 | func f (e) = (e + "_spentOnLevel") | |
14 | 14 | ||
15 | 15 | ||
16 | 16 | func g (e) = (e + "_skillsResetTimes") | |
17 | 17 | ||
18 | 18 | ||
19 | 19 | func h (e) = (e + "_spentOnReset") | |
20 | 20 | ||
21 | 21 | ||
22 | 22 | func i (j) = { | |
23 | 23 | let k = getInteger(this, j) | |
24 | 24 | if ($isInstanceOf(k, "Int")) | |
25 | 25 | then { | |
26 | 26 | let l = k | |
27 | 27 | l | |
28 | 28 | } | |
29 | 29 | else 0 | |
30 | 30 | } | |
31 | 31 | ||
32 | 32 | ||
33 | 33 | func m (e,j) = { | |
34 | 34 | let k = getString(e, j) | |
35 | 35 | if ($isInstanceOf(k, "String")) | |
36 | 36 | then { | |
37 | 37 | let n = k | |
38 | 38 | n | |
39 | 39 | } | |
40 | 40 | else "" | |
41 | 41 | } | |
42 | 42 | ||
43 | 43 | ||
44 | 44 | func o (j) = m(this, j) | |
45 | 45 | ||
46 | 46 | ||
47 | 47 | func p () = Address(fromBase58String(o("static_oracleAddress"))) | |
48 | 48 | ||
49 | 49 | ||
50 | 50 | func q () = fromBase58String(m(p(), "static_eggAssetId")) | |
51 | 51 | ||
52 | 52 | ||
53 | 53 | func r (s) = { | |
54 | 54 | let t = pow(a, 8, (10000 / s), 4, 8, CEILING) | |
55 | 55 | let u = pow(s, 0, (10000 / b), 4, 8, CEILING) | |
56 | 56 | let v = fraction(t, u, c) | |
57 | - | let w = makeString([(" | |
57 | + | let w = makeString([("newLevel=" + toString(s)), ("p1=" + toString(t)), ("p2=" + toString(u)), ("total=" + toString(v))], ";") | |
58 | 58 | $Tuple2([StringEntry("DEBUG", w)], v) | |
59 | 59 | } | |
60 | 60 | ||
61 | 61 | ||
62 | - | func x ( | |
63 | - | let | |
64 | - | let | |
65 | - | let | |
66 | - | let w = makeString([("level=" + toString( | |
67 | - | $Tuple2([StringEntry("DEBUG", w)], | |
62 | + | func x (y,z) = { | |
63 | + | let A = 4 | |
64 | + | let B = (z + 1) | |
65 | + | let C = fraction(B, (y * c), A) | |
66 | + | let w = makeString([("level=" + toString(y)), ("resetTimes=" + toString(z)), ("resetTimesToUse=" + toString(B)), ("result=" + toString(C))], ";") | |
67 | + | $Tuple2([StringEntry("DEBUG", w)], C) | |
68 | 68 | } | |
69 | 69 | ||
70 | 70 | ||
71 | - | @Callable( | |
72 | - | func configureOracle ( | |
71 | + | @Callable(D) | |
72 | + | func configureOracle (E) = if ((D.caller != this)) | |
73 | 73 | then throw("RCO: admin only") | |
74 | - | else [StringEntry("static_oracleAddress", | |
74 | + | else [StringEntry("static_oracleAddress", E)] | |
75 | 75 | ||
76 | 76 | ||
77 | 77 | ||
78 | - | @Callable( | |
78 | + | @Callable(D) | |
79 | 79 | func levelUpMath (s) = r(s) | |
80 | 80 | ||
81 | 81 | ||
82 | 82 | ||
83 | - | @Callable( | |
84 | - | func resetSkillsMath ( | |
83 | + | @Callable(D) | |
84 | + | func resetSkillsMath (y,z) = x(y, z) | |
85 | 85 | ||
86 | 86 | ||
87 | 87 | ||
88 | - | @Callable( | |
88 | + | @Callable(D) | |
89 | 89 | func levelUp () = { | |
90 | - | let E = d(toString(C.caller)) | |
91 | - | let F = f(toString(C.caller)) | |
92 | - | let G = i(E) | |
90 | + | let F = d(toString(D.caller)) | |
91 | + | let G = f(toString(D.caller)) | |
93 | 92 | let H = i(F) | |
94 | - | let I = r(G) | |
95 | - | let J = I._2 | |
96 | - | let K = value(C.payments[0]) | |
97 | - | let L = K.amount | |
98 | - | if ((K.assetId != q())) | |
93 | + | let I = i(G) | |
94 | + | let J = r((H + 1)) | |
95 | + | let K = J._2 | |
96 | + | let L = value(D.payments[0]) | |
97 | + | let M = L.amount | |
98 | + | if ((L.assetId != q())) | |
99 | 99 | then throw(("LLU: You can attach only EGG tokens with the following asset id: " + toBase58String(q()))) | |
100 | - | else if (( | |
101 | - | then throw(("LLU: Please attach the exact asset amount" + toString( | |
102 | - | else ([IntegerEntry( | |
100 | + | else if ((M != K)) | |
101 | + | then throw(("LLU: Please attach the exact asset amount" + toString(K))) | |
102 | + | else ([IntegerEntry(F, (H + 1)), IntegerEntry(G, (I + M))] ++ J._1) | |
103 | 103 | } | |
104 | 104 | ||
105 | 105 | ||
106 | 106 | ||
107 | - | @Callable( | |
107 | + | @Callable(D) | |
108 | 108 | func reset () = { | |
109 | - | let | |
110 | - | let | |
111 | - | let | |
112 | - | let | |
113 | - | let | |
114 | - | let | |
115 | - | let | |
116 | - | let | |
117 | - | let | |
118 | - | let | |
119 | - | if (( | |
109 | + | let F = d(toString(D.caller)) | |
110 | + | let H = i(F) | |
111 | + | let N = g(toString(D.caller)) | |
112 | + | let O = i(N) | |
113 | + | let P = h(toString(D.caller)) | |
114 | + | let Q = i(P) | |
115 | + | let R = x(H, O) | |
116 | + | let K = R._2 | |
117 | + | let L = value(D.payments[0]) | |
118 | + | let M = L.amount | |
119 | + | if ((L.assetId != q())) | |
120 | 120 | then throw(("LR: You can attach only EGG tokens with the following asset id: " + toBase58String(q()))) | |
121 | - | else if (( | |
122 | - | then throw(("LR: Please attach the exact asset amount" + toString( | |
123 | - | else ([IntegerEntry( | |
121 | + | else if ((M != K)) | |
122 | + | then throw(("LR: Please attach the exact asset amount" + toString(K))) | |
123 | + | else ([IntegerEntry(N, (O + 1)), IntegerEntry(P, (Q + M))] ++ R._1) | |
124 | 124 | } | |
125 | 125 | ||
126 | 126 |
github/deemru/w8io/3ef1775 54.70 ms ◑