Skip to content

Commit ec0d7bd

Browse files
Merge pull request #1165 from multiversx/block-info
SC preparations for Supernova, time types, new block info API
2 parents d702acb + d83a77e commit ec0d7bd

File tree

4 files changed

+342
-6
lines changed

4 files changed

+342
-6
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
---
2+
id: prepare-sc-supernova
3+
title: Preparing SCs for Supernova
4+
---
5+
6+
7+
The MultiversX Supernova upgrade reduces block time from **6 seconds to 0.6 seconds**, enabling sub-second blocks. While this is a major improvement, it can impact existing smart contracts, especially those relying on assumptions about timestamp behavior.
8+
9+
This guide explains how to prepare your contracts for Supernova safely.
10+
11+
12+
13+
[comment]: # (mx-context-auto)
14+
15+
## Understand What Changes — and What Doesn’t
16+
17+
All existing timestamp APIs continue returning **seconds** unless you explicitly call the millisecond versions. Nothing changes silently in the VM, the framework, or deployed contracts.
18+
19+
Obviously, contracts that have the 6 seconds between blocks hardcoded will have to change. But more importantly, block times expressed in seconds no longer uniquely identify a block, which leads to potential problems.
20+
21+
We are going to go through the most important patterns to look out for.
22+
23+
24+
25+
[comment]: # (mx-context-auto)
26+
27+
## Potential problems to look out for
28+
29+
[comment]: # (mx-context-auto)
30+
31+
### Replace Hardcoded Block Timing
32+
33+
If your contract uses hard-coded constants (like `6 seconds` or `6000 milliseconds`) to estimate the time between blocks, this logic will need to be changed.
34+
35+
It might estimate durations from nonce deltas, or vice-versa, it might estimate number of blocks by timestamps.
36+
37+
**Fix:** Use the API instead: `self.blockchain().get_block_round_time_millis()`. This returns `6000` (as `DurationMillis`) today and `600` after Supernova.
38+
39+
40+
41+
[comment]: # (mx-context-auto)
42+
43+
### Avoid Timestamp-Based Monotonicity
44+
45+
Logic such as:
46+
47+
```
48+
require!(ts_now > last_ts)
49+
```
50+
51+
may break because multiple blocks can share the same timestamp.
52+
53+
**Fix:** Use **block nonces** for guaranteed monotonicity.
54+
55+
56+
57+
[comment]: # (mx-context-auto)
58+
59+
### Prevent Rate-Limit Bypasses
60+
61+
If your contract allows one action “per block” but checks the difference in **seconds**, multiple blocks in the same second can bypass restrictions.
62+
63+
**Fix:** Use block nonces or switch to millisecond timestamps.
64+
65+
66+
67+
[comment]: # (mx-context-auto)
68+
69+
### Revisit Expiration Logic
70+
71+
Expiration logic written assuming a fixed block interval may accidentally allow:
72+
73+
* extra blocks before expiration
74+
* longer-than-intended windows for execution
75+
76+
If your expiration logic uses seconds, double-check assumptions.
77+
78+
79+
80+
[comment]: # (mx-context-auto)
81+
82+
### Stop Using Timestamps as Block Identifiers
83+
84+
Before Supernova, a timestamp could uniquely identify a block.
85+
After Supernova, multiple blocks may share the same timestamp.
86+
87+
If you use timestamps as map keys or identifiers:
88+
89+
* collisions will occur
90+
* data may be overwritten or skipped
91+
92+
**Fix:** Use block **nonces**.
93+
94+
95+
96+
[comment]: # (mx-context-auto)
97+
98+
### Review Reward and Accumulation Calculations
99+
100+
Reward logic that uses:
101+
102+
```
103+
delta = ts_now - last_ts
104+
```
105+
106+
may behave unexpectedly:
107+
108+
* delta may be zero over multiple blocks
109+
* rewards might accumulate slower or unevenly
110+
* divisions by delta may cause division-by-zero errors
111+
112+
Consider switching to milliseconds for finer granularity.
113+
114+
115+
116+
[comment]: # (mx-context-auto)
117+
118+
## Migration Guidance
119+
120+
Just as important as fixing potential issues with Supernova, it is essential not to introduce new bugs in the process.
121+
122+
Make sure to take the following into consideration when migrating:
123+
124+
125+
126+
[comment]: # (mx-context-auto)
127+
128+
### Seconds vs. Milliseconds
129+
130+
Switching from second to millisecond timestamp can be error-prone.
131+
132+
The most dangerous bug is accidentally mixing second and millisecond values, causing storage and logic corruption.
133+
134+
To prevent this issue, use the [strongly typed timestamp and duration objects](time-types).
135+
136+
Starting in **multiversx-sc v0.63.0**, all timestamp APIs have typed replacements:
137+
138+
* `get_block_timestamp_seconds()`
139+
* `get_block_timestamp_millis()`
140+
* `get_prev_block_timestamp_seconds()`
141+
* `get_prev_block_timestamp_millis()`
142+
* `get_block_round_time_millis()`
143+
* `epoch_start_block_timestamp_millis()`
144+
145+
And avoid using raw `u64` for time values.
146+
147+
Make sure to convert form `u64` to type timestamps **before** doing any other refactoring. It is much safer this way.
148+
149+
150+
151+
[comment]: # (mx-context-auto)
152+
153+
### Backwards compatibility
154+
155+
When upgrading an existing contract from second to millisecond timestamps, it is essential to:
156+
157+
* Ensure storage remains consistent
158+
* Update ESDT metadata carefully
159+
* Add compatibility logic if needed
160+
161+
If you are unsure that this can be done safely, it might be safer to keep the contract running on second timestamps.
162+
163+
164+
165+
[comment]: # (mx-context-auto)
166+
167+
## Summary Checklist
168+
169+
To prepare for Supernova:
170+
171+
* [ ] Upgrade to `multiversx-sc v0.63.0`
172+
* [ ] Use typed timestamp/duration APIs
173+
* [ ] Remove all hardcoded 6-second or 6000-millisecond assumptions
174+
* [ ] Avoid using timestamps as block identifiers
175+
* [ ] Review expiration, reward, and accumulation logic
176+
* [ ] Switch to millisecond timestamps where appropriate
177+
* [ ] Ensure storage/metadata compatibility
178+
* [ ] Update tests to use for millisecond block timestamps, where needed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
id: time-types
3+
title: Time-related Types
4+
---
5+
6+
7+
The Supernova release introduces increased block frequency and encourages transitioning to millisecond timestamps, instead of seconds. To support this, the SpaceCraft SDK (starting with `v0.63.0`) provides strong type wrappers for time values to prevent common bugs.
8+
9+
10+
[comment]: # (mx-context-auto)
11+
12+
## Overview
13+
14+
Traditionally, smart contracts used plain `u64` values to represent timestamps and durations. As the ecosystem transitions to millisecond precision, mixing seconds and milliseconds becomes error-prone. Runtime errors are difficult to detect, so the compiler now assists by enforcing type correctness.
15+
16+
17+
[comment]: # (mx-context-auto)
18+
19+
## The Four Time-Related Types
20+
21+
The framework introduces four new types:
22+
23+
* **`TimestampSeconds`** — moment in time measured in seconds
24+
* **`TimestampMillis`** — moment in time measured in milliseconds
25+
* **`DurationSeconds`** — duration measured in seconds
26+
* **`DurationMillis`** — duration measured in milliseconds
27+
28+
Each is a **newtype wrapper around `u64`**, with an identical underlying representation but distinct meaning.
29+
30+
31+
[comment]: # (mx-context-auto)
32+
33+
## Why These Types Exist
34+
35+
Using plain `u64` makes it easy to:
36+
37+
* accidentally mix seconds and milliseconds
38+
* add timestamps together (nonsensical)
39+
* subtract mismatched units
40+
* perform invalid arithmetic without realizing it
41+
42+
The new types make such mistakes **fail at compile time**.
43+
44+
45+
[comment]: # (mx-context-auto)
46+
47+
## Supported Operations
48+
49+
The framework implements common operators only where they make sense.
50+
51+
Examples:
52+
53+
```
54+
TimestampMillis - TimestampMillis → DurationMillis
55+
TimestampSeconds + DurationSeconds → TimestampSeconds
56+
DurationSeconds + DurationSeconds → DurationSeconds
57+
```
58+
59+
Examples of invalid operations (will not compile):
60+
61+
```
62+
TimestampMillis - TimestampSeconds
63+
TimestampMillis + TimestampMillis
64+
```
65+
66+
67+
[comment]: # (mx-context-auto)
68+
69+
## Codec and ABI Support
70+
71+
All four types:
72+
73+
* support codec and ABI traits
74+
* can be used in storage
75+
* can be used in events and arguments
76+
* behave like `u64` for serialization
77+
78+
This makes them safe to adopt even in existing contracts.
79+
80+
81+
[comment]: # (mx-context-auto)
82+
83+
## When to Use Seconds vs. Milliseconds
84+
85+
* **Seconds**: acceptable when your contract already stores timestamps in seconds or relies on existing storage/metadata
86+
* **Milliseconds**: recommended for all new contracts and for future-proof logic
87+
88+
The key rule: **Never mix seconds and milliseconds without explicit conversion.**
89+
90+
91+
[comment]: # (mx-context-auto)
92+
93+
## Testing
94+
95+
Time-related types also work in testing frameworks.
96+
97+
In blackbox tests, one can write:
98+
99+
```rust
100+
let block_timestamp_ms = TimestampMillis::new(123_000_000);
101+
102+
world
103+
.epoch_start_block()
104+
.block_timestamp_ms(block_timestamp_ms)
105+
.block_nonce(15_000)
106+
.block_round(17_000);
107+
```
108+
109+
110+
Mandos supports both `blockTimestamp` and the newer `blockTimestampMs`. Set both if they are used together for backward compatibility.
111+
112+
113+
[comment]: # (mx-context-auto)
114+
115+
## Summary
116+
117+
* Time-related newtypes enforce correctness at compile time
118+
* They eliminate a class of subtle bugs related to timestamp unit mismatches
119+
* Both seconds and milliseconds will continue to work, but milliseconds are recommended for new code
120+
121+
Use these types to ensure your contract remains safe and consistent across all future protocol updates.

docs/developers/developer-reference/sc-api-functions.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,26 @@ A smart contract call that runs out of gas will revert all operations, so this f
140140

141141
[comment]: # (mx-context-auto)
142142

143-
### get_block_timestamp
143+
### get_block_timestamp_seconds
144144

145145
```rust
146-
get_block_timestamp() -> u64
146+
get_block_timestamp_millis() -> TimestampSeconds
147147
```
148148

149149
Returns the timestamp of the current block, in seconds (UNIX timestamp).
150150

151+
152+
[comment]: # (mx-context-auto)
153+
154+
### get_block_timestamp_millis
155+
156+
```rust
157+
get_block_timestamp_millis() -> TimestampMillis
158+
```
159+
160+
Returns the timestamp of the current block, in milliseconds (UNIX timestamp).
161+
162+
151163
[comment]: # (mx-context-auto)
152164

153165
### get_block_nonce
@@ -194,12 +206,26 @@ This will be the same for all the calls in the current block, so it can be predi
194206

195207
[comment]: # (mx-context-auto)
196208

197-
### get_prev_block_timestamp
209+
### get_prev_block_timestamp_seconds
210+
211+
```rust
212+
get_prev_block_timestamp_seconds() -> TimestampSeconds
213+
```
214+
215+
Returns the timestamp of the previous block, in seconds (UNIX timestamp).
216+
217+
218+
[comment]: # (mx-context-auto)
219+
220+
### get_prev_block_timestamp_millis
198221

199222
```rust
200-
get_prev_block_timestamp() -> u64
223+
get_prev_block_timestamp_millis() -> TimestampMillis
201224
```
202225

226+
Returns the timestamp of the previous block, in milliseconds (UNIX timestamp).
227+
228+
203229
[comment]: # (mx-context-auto)
204230

205231
### get_prev_block_nonce
@@ -232,7 +258,16 @@ get_prev_block_epoch() -> u64
232258
get_prev_block_random_seed() -> ManagedByteArray<Self::Api, 48>
233259
```
234260

235-
The same as the functions above, but for the previous block instead of the current block.
261+
[comment]: # (mx-context-auto)
262+
263+
### get_block_round_time_millis
264+
265+
```rust
266+
get_block_round_time_millis(&self) -> DurationMillis
267+
```
268+
269+
The block round time, in milliseconds, i.e the time between consecutive blocks.
270+
236271

237272
[comment]: # (mx-context-auto)
238273

sidebars.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,14 @@ const sidebars = {
126126
},
127127
{
128128
type: "category",
129-
label: "Rust Developers Best Practices",
129+
label: "Best Practices",
130130
items: [
131131
"developers/best-practices/best-practices-basics",
132132
"developers/best-practices/biguint-operations",
133133
"developers/best-practices/managed-decimal",
134134
"developers/best-practices/the-dynamic-allocation-problem",
135+
"developers/best-practices/time-types",
136+
"developers/best-practices/prepare-sc-supernova",
135137
],
136138
},
137139
{

0 commit comments

Comments
 (0)