Sui - Clock Object
Hello everyone..
Welcome to another day of exploring Web3 Engineering. In our series, we are learning about Sui language and how to write smart contracts using Move language. So far, we have already covered the basic and necessary concepts that are required to write smart contracts. In this article, let us understand how to include time aka clock module in our contracts. So, without any further ado, let's get started...
Clock module
Sui standard package contains a special module called clock
which contains the Clock
using which we can access the current timestamp during execution. Clock is a shared object on the network and initialized during the genesis block. This object contains only one field which is timestamp_ms
storing the current time of the network in milliseconds.
Even though it's a regular shared object, it can only be included as a reference in our functions and adding as a mutable reference results in compilation errors. The structure of the Clock object is as follows:
public struct Clock has key {
id: UID,
timestamp_ms: u64,
}
The module can be imported and used as follows:
public struct Counter has key, store {
id:UID,
count: u64,
time: u64,
last_updated: u64
}
public entry fun new(time: u64, clock: &Clock, ctx: &mut TxContext) {
transfer::transfer(Counter {
id: object::new(ctx),
count: 0,
time: time,
last_updated: clock.timestamp_ms()
}, ctx.sender());
}
public entry fun update(counter: &mut Counter, clock: &Clock) {
assert!(counter.last_updated + counter.time <= clock.timestamp_ms(), 0);
counter.count = counter.count + 1;
counter.last_updated = clock.timestamp_ms();
}
In our above contract, we have a Counter object which can only be updated after time
which is given during the initialization. As you can, we have added the Clock as a reference on both of the functions. Now, let us write some test cases for the above code.
#[test]
fun test_new_counter() {
let user = @0x12e4;
let mut scenario = test_scenario::begin(user);
{
let ctx = scenario.ctx();
let mut clock = clock::create_for_testing(ctx);
clock_obj::new(TIME, &clock, ctx);
clock.increment_for_testing(1);
clock.share_for_testing();
};
scenario.next_tx(user);
{
let mut counter = scenario.take_from_sender<clock_obj::Counter>();
let clock = scenario.take_shared<clock::Clock>();
counter.update(&clock);
scenario.return_to_sender(counter);
test_scenario::return_shared(clock);
};
scenario.end();
}
Here we are creating a test Clock
object for our test scenario and sharing it into the network. We are also using the test helper functions provided by the clock module from the sui
package. Now let us write a failure test case for the above scenario.
#[test, expected_failure]
fun test_fail_counter() {
let user = @0x12e4;
let mut scenario = test_scenario::begin(user);
{
let ctx = scenario.ctx();
let clock = clock::create_for_testing(ctx);
clock_obj::new(TIME, &clock, ctx);
clock.share_for_testing();
};
scenario.next_tx(user);
{
let mut counter = scenario.take_from_sender<clock_obj::Counter>();
let clock = scenario.take_shared<clock::Clock>();
counter.update(&clock);
scenario.return_to_sender(counter);
test_scenario::return_shared(clock);
};
scenario.end();
}
In the above test case, we are not updating the clock object. Hence it should throw an error as expected.
NOTE: For using the clock module in a function call made externally, we must pass the value 0x6
as the clock module object id.
The full code can be found here: https://github.com/jveer634/sui_contracts
That's all for today. Thank you.
Subscribe to my newsletter
Read articles from Jay Nalam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jay Nalam
Jay Nalam
Hi, I'm Jay Nalam, a seasoned Web3 Engineer committed to advancing decentralized technologies. Specializing in EVM-based blockchains, smart contracts, and web3 protocols, I've developed NFTs, DeFi protocols, and more, pushing boundaries in the crypto realm.