Skip to content

Unit Testing Smart Contracts (Use Case) Manipulating EVM Timestamps for Testing Time-Dependent Smart Contracts

Posted on:January 25, 2023 at 05:56 AM

In this use case, the contract defines ten functions for manipulating the EVM timestamp.

The tool is Foundry

This test contract inherits from DSTest and utilizes the Vm module from the “forge-std/Test.sol” library.

Each function calculates the target time based on the current block timestamp and the specified number of time units. Then, it calls the warp() function of the Vm module to set the EVM timestamp to the target time. This contract is beneficial for testing time-dependent functionality in other smart contracts.

// SPDX-License-Identifier: UNLICENSED

/// @custom:test-contacts that works with time ipcanw@gmail.com
/// Forward block.timestamp forward by a given number

pragma solidity >=0.8.11;

import {DSTest, Vm} from "forge-std/Test.sol";

contract Timestamp is DSTest {
    Vm internal immutable vm = Vm(HEVM_ADDRESS);

    // dayForward(uint256 num) moves the EVM timestamp forward by a specified number of days.
    function dayForward(uint256 num) external returns (uint256 targetTime) {
        targetTime = (block.timestamp + 1 days) * num;
        vm.warp(targetTime);
    }
    // secondForward(uint256 num) moves the EVM timestamp forward by a specified number of seconds.
    function secondForward(uint256 num) external {
        uint256 targetTime = (block.timestamp + 1 seconds) * num;
        vm.warp(targetTime);
    }
    // minuteForward(uint256 num) moves the EVM timestamp forward by a specified number of minutes.
    function minuteForward(uint256 num) external {
        uint256 targetTime = (block.timestamp + 1 minutes) * num;
        vm.warp(targetTime);
    }
    // hourForward(uint256 num) moves the EVM timestamp forward by a specified number of hours.
    function hourForward(uint256 num) external {
        uint256 targetTime = (block.timestamp + 1 hours) * num;
        vm.warp(targetTime);
    }
    // weekForward(uint256 num) moves the EVM timestamp forward by a specified number of weeks.
    function weekForward(uint256 num) external {
        uint256 targetTime = (block.timestamp + 1 weeks) * num;
        vm.warp(targetTime);
    }
    // dayBackward(uint256 num) moves the EVM timestamp backward by a specified number of days.
    function dayBackward(uint256 num) external {
        uint256 targetTime = (block.timestamp - 1 days) * num;
        vm.warp(targetTime);
    }
    // secondBackward(uint256 num) moves the EVM timestamp backward by a specified number of seconds.
    function secondBackward(uint256 num) external {
        uint256 targetTime = (block.timestamp - 1 seconds) * num;
        vm.warp(targetTime);
    }
    // minuteBackward(uint256 num) moves the EVM timestamp backward by a specified number of minutes.
    function minuteBackward(uint256 num) external {
        uint256 targetTime = (block.timestamp - 1 minutes) * num;
        vm.warp(targetTime);
    }
    // hourBackward(uint256 num) moves the EVM timestamp backward by a specified number of hours.
    function hourBackward(uint256 num) external {
        uint256 targetTime = (block.timestamp - 1 hours) * num;
        vm.warp(targetTime);
    }
    // weekBackward(uint256 num) moves the EVM timestamp backward by a specified number of weeks.
    function weekBackward(uint256 num) external {
        uint256 targetTime = (block.timestamp - 1 weeks) * num;
        vm.warp(targetTime);
    }
}

Below is how it can be used in testing a contract, declaring the variable as a public named “timestamp,” so it is declared of type an instance of the “Timestamp” library and can access its functions.

Timestamp public timestamp;

timestamp = new Timestamp();

timestamp.dayForward(30);

One interesting use case for unit testing smart contracts is the manipulation of the EVM timestamp in many smart contracts involving time-locked tokens, vesting schedules, or auction expiration times. However, testing such features can be challenging due to the need to simulate the passage of time on the blockchain. Check my github for an example of using the permit method.