# Time

{% embed url="https://youtu.be/B_3Kax70sF4" %}
Time
{% endembed %}

## Setup

Target contract:

```solidity
pragma solidity 0.8.18;

contract Auction {
    uint256 public startAt = block.timestamp + 1 days;
    uint256 public endAt = block.timestamp + 2 days;

    function bid() external {
        require(
            block.timestamp >= startAt && block.timestamp < endAt, "cannot bid"
        );
    }

    function end() external {
        require(block.timestamp >= endAt, "cannot end");
    }
}
```

Test file:

```solidity
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import {Auction} from "../src/Time.sol";

contract TimeTest is Test {
    Auction public auction;
    uint256 private startAt;

    // vm.warp - set block.timestamp to future timestamp
    // vm.roll - set block.number
    // skip - increment current timestamp
    // rewind - decrement current timestamp

    function setUp() public {
        auction = new Auction();
        startAt = block.timestamp;
    }

    function testBidFailsBeforeStartTime() public {
        vm.expectRevert(bytes("cannot bid"));
        auction.bid();
    }

    function testBid() public {
        vm.warp(startAt + 1 days);
        auction.bid();
    }

    function testBidFailsAfterEndTime() public {
        vm.expectRevert(bytes("cannot bid"));
        vm.warp(startAt + 2 days);
        auction.bid();
    }

    function testTimestamp() public {
        uint256 t = block.timestamp;
        // set block.timestamp to t + 100
        skip(100);
        assertEq(block.timestamp, t + 100);

        // set block.timestamp to t + 100 - 100;
        rewind(100);
        assertEq(block.timestamp, t);
    }

    function testBlockNumber() public {
        uint256 b = block.number;
        // set block number to 11
        vm.roll(11);
        assertEq(block.number, 11);
    }
}
```

## vm.warp()

If we call `bid()` right away, it will fail because the auction is not started yet:

```solidity
    function testBidFailsBeforeStartTime() public {
        vm.expectRevert(bytes("cannot bid"));
        auction.bid();
    }
```

If we call `bid()` at `block.timestamp + 1 days`, it works:

```solidity
    function testBid() public {
        vm.warp(startAt + 1 days);
        auction.bid();
    }
```

But if we call `bid()` at `block.timestamp + 2 days`, it will fail because the audtion was already ended:

```solidity
    function testBidFailsAfterEndTime() public {
        vm.expectRevert(bytes("cannot bid"));
        vm.warp(startAt + 2 days);
        auction.bid();
    }
```

## skip and rewind

Similar to `vm.warp()`:

```solidity
    function testTimestamp() public {
        uint256 t = block.timestamp;
        // set block.timestamp to t + 100
        skip(100);
        assertEq(block.timestamp, t + 100);

        // set block.timestamp to t + 100 - 100;
        rewind(100);
        assertEq(block.timestamp, t);
    }
```

## vm.roll()

Set `block.number`:

```solidity
    function testBlockNumber() public {
        uint256 b = block.number;
        // set block number to 11
        vm.roll(11);
        assertEq(block.number, 11);
    }
```
