Skip to main content

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.

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.

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.

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.

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

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 the types ABI-compatible with existing u64 values, but it does not convert the unit of an existing value. For example, decoding a seconds value directly as TimestampMillis preserves the numeric value instead of multiplying it by 1000. Existing storage, endpoint semantics, events, and token attributes must be converted explicitly if their unit changes.

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.

Testing​

Time-related types also work in testing frameworks.

In blackbox tests, one can write:

    let block_timestamp_ms = TimestampMillis::new(123_000_000);

world
.epoch_start_block()
.block_timestamp_millis(block_timestamp_ms)
.block_nonce(15_000)
.block_round(17_000);

Scenario files support both blockTimestamp (seconds) and blockTimestampMs (milliseconds). In RustVM, they update the same underlying timestamp. Set blockTimestampMs for sub-second tests; the seconds API returns the truncated value. A later seconds-only state update discards sub-second precision.

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.