question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

eve_mine with timestamp parameter is some times off by one second

See original GitHub issue

evm_mine with timestamp parameter is some times off by one second. This is not helpful as deterministic behaviour of contracts is often desirable when hunting for bugs.

Expected Behavior

I would expect evm_mine with timestamp to deliver a block with exactly the given timestamp.

Current Behavior

I call evm_mine with a timestamp parameter, which usually is honoured but not always. This is an intermittent problem. Below I provide two sample outputs of a test contract in Truffle, which differ only in the timestamps of block 14.

Here is the first output, with block 14 having a time stamp 1600000071

$ truffle test
Compiling ./contracts/ConvertLib.sol...
Compiling ./contracts/MetaCoin.sol...
Compiling ./contracts/Migrations.sol...

  Contract: MetaCoin
block.number 5 block.timestamp 1552999213 timestamp 1600000000
1 'blockNumber' 6
    ✓ TEST 1: should deploy (42ms)
block.number 6 block.timestamp 1600000000 timestamp 1600000020
2 'blockNumber' 7
    ✓ TEST 2: should put 10000 MetaCoin in the first account (69ms)
block.number 7 block.timestamp 1600000020 timestamp 1600000030
3 'blockNumber' 8
    ✓ TEST 3: should fail because function does not exist on contract
block.number 8 block.timestamp 1600000030 timestamp 1600000040
4 'blockNumber' 9
    ✓ TEST 4: should call a function that depends on a linked library (85ms)
block.number 9 block.timestamp 1600000040 timestamp 1600000050
5 'blockNumber' 10
    ✓ TEST 5: should send coin (109ms)
block.number 11 block.timestamp 1600000050 timestamp 1600000060
6 'blockNumber' 12
    ✓ TEST 6: should not send coin (54ms)
block.number 12 block.timestamp 1600000060 timestamp 1600000070
7 'blockNumber' 13
    ✓ TEST 7: should send coin correctly (227ms)
block.number 14 block.timestamp 1600000071 timestamp 1600000080
8 'blockNumber' 15
0 'blockNumber' 0 'timeStamp' 1552999209
1 'blockNumber' 1 'timeStamp' 1552999212
2 'blockNumber' 2 'timeStamp' 1552999212
3 'blockNumber' 3 'timeStamp' 1552999213
4 'blockNumber' 4 'timeStamp' 1552999213
5 'blockNumber' 5 'timeStamp' 1552999213
6 'blockNumber' 6 'timeStamp' 1600000000
7 'blockNumber' 7 'timeStamp' 1600000020
8 'blockNumber' 8 'timeStamp' 1600000030
9 'blockNumber' 9 'timeStamp' 1600000040
10 'blockNumber' 10 'timeStamp' 1600000050
11 'blockNumber' 11 'timeStamp' 1600000050
12 'blockNumber' 12 'timeStamp' 1600000060
13 'blockNumber' 13 'timeStamp' 1600000070
14 'blockNumber' 14 'timeStamp' 1600000071
15 'blockNumber' 15 'timeStamp' 1600000080
    ✓ TEST 8: check all addresses (234ms)

  8 passing (904ms)

Here is the second output with block 14 having a time stamp 1600000070

$ truffle test
Compiling ./contracts/ConvertLib.sol...
Compiling ./contracts/MetaCoin.sol...
Compiling ./contracts/Migrations.sol...

  Contract: MetaCoin
block.number 5 block.timestamp 1552999262 timestamp 1600000000
1 'blockNumber' 6
    ✓ TEST 1: should deploy (39ms)
block.number 6 block.timestamp 1600000000 timestamp 1600000020
2 'blockNumber' 7
    ✓ TEST 2: should put 10000 MetaCoin in the first account (67ms)
block.number 7 block.timestamp 1600000020 timestamp 1600000030
3 'blockNumber' 8
    ✓ TEST 3: should fail because function does not exist on contract
block.number 8 block.timestamp 1600000030 timestamp 1600000040
4 'blockNumber' 9
    ✓ TEST 4: should call a function that depends on a linked library (91ms)
block.number 9 block.timestamp 1600000040 timestamp 1600000050
5 'blockNumber' 10
    ✓ TEST 5: should send coin (119ms)
block.number 11 block.timestamp 1600000050 timestamp 1600000060
6 'blockNumber' 12
    ✓ TEST 6: should not send coin (57ms)
block.number 12 block.timestamp 1600000060 timestamp 1600000070
7 'blockNumber' 13
    ✓ TEST 7: should send coin correctly (228ms)
block.number 14 block.timestamp 1600000070 timestamp 1600000080
8 'blockNumber' 15
0 'blockNumber' 0 'timeStamp' 1552999258
1 'blockNumber' 1 'timeStamp' 1552999261
2 'blockNumber' 2 'timeStamp' 1552999261
3 'blockNumber' 3 'timeStamp' 1552999262
4 'blockNumber' 4 'timeStamp' 1552999262
5 'blockNumber' 5 'timeStamp' 1552999262
6 'blockNumber' 6 'timeStamp' 1600000000
7 'blockNumber' 7 'timeStamp' 1600000020
8 'blockNumber' 8 'timeStamp' 1600000030
9 'blockNumber' 9 'timeStamp' 1600000040
10 'blockNumber' 10 'timeStamp' 1600000050
11 'blockNumber' 11 'timeStamp' 1600000050
12 'blockNumber' 12 'timeStamp' 1600000060
13 'blockNumber' 13 'timeStamp' 1600000070
14 'blockNumber' 14 'timeStamp' 1600000070
15 'blockNumber' 15 'timeStamp' 1600000080
    ✓ TEST 8: check all addresses (229ms)

  8 passing (914ms)

Possible Solution

I’m sorry, I have no idea.

Steps to Reproduce (for bugs)

Here is the truffle code needed to reproduce the issue: MetaCoin.zip

$ unzip MetaCoin.zip $ cd MetaCoin $ truffle test … keep trying until the behaviour changes $ truffle test

Context

I am trying to debug smart contracts that use now. It would be most helpful if the contracts could be made to behave deterministically.

Your Environment

$ truffle version
Truffle v5.0.2 (core: 5.0.2)
Solidity v0.5.0 (solc-js)
Node v10.15.0
$ uname -a
Darwin 18.2.0 Darwin Kernel Version 18.2.0: Thu Dec 20 20:46:53 PST 2018; root:xnu-4903.241.1~1/RELEASE_X86_64 x86_64

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
davidmurdochcommented, Mar 19, 2019

Thanks @pieterhartel for the detailed reproduction steps!

This apparent non-determinism is caused by ganache “instamining”; that is to say: it mines a new block immediately after a transaction is received.

evm_mine(timestamp) causes a block to be mined exactly at the timestamp given, and also updates the internal timeAdjustment (this basically lets us fast-forward or rewind time) so blocks mined in the future always happen after the last block mined. Block timestamps are still based on the real clock though, just with this timeAdjustment added in.

The amount of time between evm_mine and your next transaction is not going to be 0, and sometimes the time difference will span two different real seconds – and this can happen even if the difference is a single millisecond. This is what causes the block timestamps vary in your tests.

To make your tests deterministic you should:

  1. start ganache with the time option (in addition to a deterministic seed/mnemonic option). This will create a genesis block at the given timestamp (there is actually a bug here so this part might not always happen perfectly).
  2. Send a miner_stop RPC call to prevent any more blocks from being insta-mined.
  3. Send the transaction or transactions you want mined in the next block
  1. Send an evm_mine RPC call with a timestamp to cause the transaction(s) you sent in step 3 to be mined at the specific timestamp.

Let me know if you have an questions. Thanks again!

0reactions
pieterhartelcommented, Apr 16, 2019

@davidmurdoch some of my transactions now timeout after 750 seconds.

Transaction was not mined within750 seconds, please make sure your transaction was properly sent. Be aware that it might still be mined!

I’m trying to reproduce it in a small test but that’s not easy. Would it be possible to improve the code that you suggested to make such timeouts impossible, or at least a lot less likely?

const txRequest = deployedContract.methods[ "Play()" ]( txOptions ) ;
await new Promise((resolve) => {txRequest.on("transactionHash", resolve)});
await mine_time.mineBlockWithTimestamp( 1600000000 ) ;
const txResult = await txRequest ;
Read more comments on GitHub >

github_iconTop Results From Across the Web

Flow fails to save or run - Power Platform Community - Microsoft
(a) Using Dynamic Content "Event Start Date Time" Flow save failed ... expects its second parameter to be a time zone matching the...
Read more >
DATE_TRUNC: SQL Timestamp Function Explained | Mode
Learn how to use Date_Trunc in SQL to round a timestamp to the interval you need. Aggregate time-based data with this helpful function....
Read more >
Demystifying DateTime Manipulation in JavaScript - Toptal
As a software developer, you can't run away from date manipulation. ... In JavaScript, a time stamp is the number of milliseconds that...
Read more >
Fun with dates and times - IBM Developer
Given a date, time, or timestamp, you can extract (where applicable) the year, month, day, hour, minutes, seconds, and microseconds portions independently ...
Read more >
Timestamp functions | BigQuery - Google Cloud
CURRENT_TIMESTAMP() produces a TIMESTAMP value that is continuous, non-ambiguous, has exactly 60 seconds per minute and does not repeat values over the leap ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found