My contract has an expiration date that I'd like to unit test but I don't know how to go about doing that. If I could mock the time of the contract that would be dope. Google search provided no information though.
4 Answers
As a general testing method, you can create another, debugging-only, contract descending from your production contract. This second contract can have methods to do anything--for example, to set the expiration date to now
.
If you want to mess with time specifically, TestRPC has an RPC method to fast forward time. Be warned, you'll have to integrate it into your testing harness somehow, since web3 does not come with it.
-
Thats what I ended up doing, see truffleframework.com/tutorials/chain-forking-exploiting-the-dao Apr 30, 2017 at 0:19
-
But there was no way to reset the time back so I made a pr for that feature Apr 30, 2017 at 0:20
This is a fairly old question but I thought I would add this for those looking:
You can utilize the evm_increaseTime method that you get with both hardhat and ganache.
Here's an example with ethers
await ethers.provider.send("evm_increaseTime", [10]) // add 10 seconds
await ethers.provider.send("evm_mine", []) // force mine the next block
And here with web3
web3.currentProvider.send({jsonrpc: "2.0", method: "evm_increaseTime", params: [10], id: 0})
web3.currentProvider.send({jsonrpc: "2.0", method: "evm_mine", params: [], id: 0})
-
1
I've been making my contracts descend from a simple contract that has a currTime()
function and a testing
boolean. If I set testing
to true, currTime()
returns a fake time, which I can manipulate with functions like addDays(uint days)
. If testing
is false, then currTime()
just returns block.timestamp
. Every place where I'd check the timestamp, I call currTime()
instead.
-
Thanks for the tip, this is what I needed to get my tests working. One more question though, when you deploy your contract do you remove the contract that you use to manipulate the current time? Aug 28, 2017 at 3:46
-
1That's tricky. You don't really want to change the tested code when you deploy, but it's kinda nasty leaving it in, too. I guess you just have to decide what's best for your particular contract. Aug 29, 2017 at 1:50
-
Good call. I actually just rewrote all my tests to Mocha tests as it's easier to manipulate time that way. Aug 29, 2017 at 2:24
There is a library in Dapphub: https://github.com/dapphub/ds-warp
A simple mixin for controlling time.
Return the current time with era(). Advance time with warp.
warp(0) to lock the current time to the blocktime.
contract DSWarpTest is DSTest { DSWarp warp; function setUp() { warp = new DSWarp(); } function testInit() { assertEq(warp.era(), now); } function testWarp() { var tic = now; warp.warp(1); assertEq(warp.era(), tic + 1); } function testWarpLock() { warp.warp(0); assertEq(warp.era(), now); } function testFailAfterWarpLock() { warp.warp(0); warp.warp(1); } }