-
Notifications
You must be signed in to change notification settings - Fork 152
SC preparations for Supernova, time types, new block info API #1165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| --- | ||
| id: prepare-sc-supernova | ||
| title: Preparing SCs for Supernova | ||
| --- | ||
|
|
||
|
|
||
| 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. | ||
|
|
||
| This guide explains how to prepare your contracts for Supernova safely. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Understand What Changes — and What Doesn’t | ||
|
|
||
| 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. | ||
|
|
||
| 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. | ||
|
|
||
| We are going to go through the most important patterns to look out for. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Potential problems to look out for | ||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Replace Hardcoded Block Timing | ||
|
|
||
| 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. | ||
|
|
||
| It might estimate durations from nonce deltas, or vice-versa, it might estimate number of blocks by timestamps. | ||
|
|
||
| **Fix:** Use the API instead: `self.blockchain().get_block_round_time_millis()`. This returns `6000` (as `DurationMillis`) today and `600` after Supernova. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Avoid Timestamp-Based Monotonicity | ||
|
|
||
| Logic such as: | ||
|
|
||
| ``` | ||
| require!(ts_now > last_ts) | ||
| ``` | ||
|
|
||
| may break because multiple blocks can share the same timestamp. | ||
|
|
||
| **Fix:** Use **block nonces** for guaranteed monotonicity. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Prevent Rate-Limit Bypasses | ||
|
|
||
| If your contract allows one action “per block” but checks the difference in **seconds**, multiple blocks in the same second can bypass restrictions. | ||
|
|
||
| **Fix:** Use block nonces or switch to millisecond timestamps. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Revisit Expiration Logic | ||
|
|
||
| Expiration logic written assuming a fixed block interval may accidentally allow: | ||
|
|
||
| * extra blocks before expiration | ||
| * longer-than-intended windows for execution | ||
|
|
||
| If your expiration logic uses seconds, double-check assumptions. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Stop Using Timestamps as Block Identifiers | ||
|
|
||
| Before Supernova, a timestamp could uniquely identify a block. | ||
| After Supernova, multiple blocks may share the same timestamp. | ||
|
|
||
| If you use timestamps as map keys or identifiers: | ||
|
|
||
| * collisions will occur | ||
| * data may be overwritten or skipped | ||
|
|
||
| **Fix:** Use block **nonces**. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Review Reward and Accumulation Calculations | ||
|
|
||
| Reward logic that uses: | ||
|
|
||
| ``` | ||
| delta = ts_now - last_ts | ||
| ``` | ||
|
|
||
| may behave unexpectedly: | ||
|
|
||
| * delta may be zero over multiple blocks | ||
| * rewards might accumulate slower or unevenly | ||
| * divisions by delta may cause division-by-zero errors | ||
|
|
||
| Consider switching to milliseconds for finer granularity. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Migration Guidance | ||
|
|
||
| Just as important as fixing potential issues with Supernova, it is essential not to introduce new bugs in the process. | ||
|
|
||
| Make sure to take the following into consideration when migrating: | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Seconds vs. Milliseconds | ||
|
|
||
| Switching from second to millisecond timestamp can be error-prone. | ||
|
|
||
| The most dangerous bug is accidentally mixing second and millisecond values, causing storage and logic corruption. | ||
|
|
||
| To prevent this issue, use the [strongly typed timestamp and duration objects](time-types). | ||
|
|
||
| Starting in **multiversx-sc v0.63.0**, all timestamp APIs have typed replacements: | ||
|
|
||
| * `get_block_timestamp_seconds()` | ||
| * `get_block_timestamp_millis()` | ||
| * `get_prev_block_timestamp_seconds()` | ||
| * `get_prev_block_timestamp_millis()` | ||
| * `get_block_round_time_millis()` | ||
| * `epoch_start_block_timestamp_millis()` | ||
|
|
||
| And avoid using raw `u64` for time values. | ||
|
|
||
| Make sure to convert form `u64` to type timestamps **before** doing any other refactoring. It is much safer this way. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ### Backwards compatibility | ||
|
|
||
| When upgrading an existing contract from second to millisecond timestamps, it is essential to: | ||
|
|
||
| * Ensure storage remains consistent | ||
| * Update ESDT metadata carefully | ||
| * Add compatibility logic if needed | ||
|
|
||
| If you are unsure that this can be done safely, it might be safer to keep the contract running on second timestamps. | ||
|
|
||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Summary Checklist | ||
|
|
||
| To prepare for Supernova: | ||
|
|
||
| * [ ] Upgrade to `multiversx-sc v0.63.0` | ||
| * [ ] Use typed timestamp/duration APIs | ||
| * [ ] Remove all hardcoded 6-second or 6000-millisecond assumptions | ||
| * [ ] Avoid using timestamps as block identifiers | ||
| * [ ] Review expiration, reward, and accumulation logic | ||
| * [ ] Switch to millisecond timestamps where appropriate | ||
| * [ ] Ensure storage/metadata compatibility | ||
| * [ ] Update tests to use for millisecond block timestamps, where needed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| --- | ||
| id: time-types | ||
| title: Time-related Types | ||
| --- | ||
|
|
||
|
|
||
| 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. | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Overview | ||
|
|
||
| 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. | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## The Four Time-Related Types | ||
|
|
||
| The framework introduces four new types: | ||
|
|
||
| * **`TimestampSeconds`** — moment in time measured in seconds | ||
| * **`TimestampMillis`** — moment in time measured in milliseconds | ||
| * **`DurationSeconds`** — duration measured in seconds | ||
| * **`DurationMillis`** — duration measured in milliseconds | ||
|
|
||
| Each is a **newtype wrapper around `u64`**, with an identical underlying representation but distinct meaning. | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Why These Types Exist | ||
|
|
||
| Using plain `u64` makes it easy to: | ||
|
|
||
| * accidentally mix seconds and milliseconds | ||
| * add timestamps together (nonsensical) | ||
| * subtract mismatched units | ||
| * perform invalid arithmetic without realizing it | ||
|
|
||
| The new types make such mistakes **fail at compile time**. | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Supported Operations | ||
|
|
||
| The framework implements common operators only where they make sense. | ||
|
|
||
| Examples: | ||
|
|
||
| ``` | ||
| TimestampMillis - TimestampMillis → DurationMillis | ||
| TimestampSeconds + DurationSeconds → TimestampSeconds | ||
| DurationSeconds + DurationSeconds → DurationSeconds | ||
| ``` | ||
|
|
||
| Examples of invalid operations (will not compile): | ||
|
|
||
| ``` | ||
| TimestampMillis - TimestampSeconds | ||
| TimestampMillis + TimestampMillis | ||
| ``` | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Codec and ABI Support | ||
|
|
||
| All four types: | ||
|
|
||
| * support codec and ABI traits | ||
| * can be used in storage | ||
| * can be used in events and arguments | ||
| * behave like `u64` for serialization | ||
|
|
||
| This makes them safe to adopt even in existing contracts. | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## When to Use Seconds vs. Milliseconds | ||
|
|
||
| * **Seconds**: acceptable when your contract already stores timestamps in seconds or relies on existing storage/metadata | ||
| * **Milliseconds**: recommended for all new contracts and for future-proof logic | ||
|
|
||
| The key rule: **Never mix seconds and milliseconds without explicit conversion.** | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Testing | ||
|
|
||
| Time-related types also work in testing frameworks. | ||
|
|
||
| In blackbox tests, one can write: | ||
|
|
||
| ```rust | ||
| let block_timestamp_ms = TimestampMillis::new(123_000_000); | ||
|
|
||
| world | ||
| .epoch_start_block() | ||
| .block_timestamp_ms(block_timestamp_ms) | ||
| .block_nonce(15_000) | ||
| .block_round(17_000); | ||
| ``` | ||
|
|
||
|
|
||
| Mandos supports both `blockTimestamp` and the newer `blockTimestampMs`. Set both if they are used together for backward compatibility. | ||
|
|
||
|
|
||
| [comment]: # (mx-context-auto) | ||
|
|
||
| ## Summary | ||
|
|
||
| * Time-related newtypes enforce correctness at compile time | ||
| * They eliminate a class of subtle bugs related to timestamp unit mismatches | ||
| * Both seconds and milliseconds will continue to work, but milliseconds are recommended for new code | ||
|
|
||
| Use these types to ensure your contract remains safe and consistent across all future protocol updates. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better emphasize this sentence using :::info
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't use info boxes anywhere, feels a bit off