Sui - Clock Object

Jay NalamJay Nalam
3 min read

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.

0
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.