Accessing On-Chain Time in IOTA
When you need to access network-based time for your transactions on IOTA, you have several options:
- Near Real-Time Measurement: Use the immutable reference of time provided by the
Clock
module in Move. This value updates with every network checkpoint. - Epoch Start Time: Use the
epoch_timestamp_ms
function to capture the precise moment the current epoch started.
Using the iota::clock::Clock
Module
To access a prompt timestamp, you can pass a read-only reference of iota::clock::Clock
as an entry function parameter in your transactions.
An instance of Clock
is provided at the address 0x6
, and no new instances can be created.
Use the timestamp_ms
function from the iota::clock
module to extract a Unix timestamp in milliseconds.
/// The `clock`'s current timestamp as a running total of
/// milliseconds since an arbitrary point in the past.
public fun timestamp_ms(clock: &Clock): u64 {
clock.timestamp_ms
}
Example: Emitting an Event with a Timestamp
The following example demonstrates an entry function that emits an event containing a timestamp from the Clock
:
module basics::clock {
use iota::{clock::Clock, event};
public struct TimeEvent has copy, drop, store {
timestamp_ms: u64,
}
entry fun access(clock: &Clock) {
event::emit(TimeEvent { timestamp_ms: clock.timestamp_ms() });
}
}
To call the previous entry function, pass 0x6
as the address for the Clock
parameter:
iota client call --package <EXAMPLE> --module 'clock' --function 'access' --args '0x6'
Note: The Clock
timestamp changes at the rate the network generates checkpoints, which is every 1 second with Narwhal/Bullshark consensus and every 0.1 to 0.2 seconds with Mysticeti consensus.
Successive calls to iota::clock::timestamp_ms
within the same transaction will always produce the same result because transactions are considered to take effect instantly.
However, timestamps from Clock
are monotonic across transactions that touch the same shared objects, meaning successive transactions see a greater or equal timestamp compared to their predecessors.
Transaction Requirements
- Consensus Requirement: Any transaction that requires access to a
Clock
must go through consensus because the only available instance is a shared object. - Immutable Reference: Transactions that use the clock must accept it as an immutable reference (
&Clock
), not as a mutable reference or value. This prevents contention, as transactions that access theClock
can only read it.
Validators will refuse to sign transactions that do not meet this requirement, and packages that include entry functions accepting a Clock
or &mut Clock
will fail to publish.