3

I have a function that makes use of the current time (now). The Contract as a whole is a Crowdfunding token and the cost of tokens differ depending on the date and time that tokens are purchased.

How does one simulate different times when testing a Smart Contract? For instance, with regards to the code below, I would like to do unit testing to find out if the code for setting price is correct but I can't change the value of now.

Would it be a good solution to simply substitute the now keyword for another temporary testing variable, say now_sim and then manually changing now_sim during simulation?

    if (now < (startTime + 1 days)) {
        currentPrice = safeDiv(safeMul(price, 80), 100);  // 20 % discount (x * 80 / 100)
    } 
    else if (now < (startTime + 2 days)) {
        currentPrice = safeDiv(safeMul(price, 90), 100);  // 10 % discount (x * 90 / 100)
    }
    else if (now < (startTime + 12 days)) {
        // 1 % reduction in the discounted rate from day 2 until day 12 (sliding scale per second)
        // 8640000 is 60 x 60 x 24 x 100 (100 for 1%) (60 x 60 x 24 for seconds per day)
        currentPrice = price - safeDiv(safeMul((startTime + 12 days) - now), price), 8640000);
    }
    else {
        currentPrice = price;
    }
  • 2
    There's a way to increase the time with testrpc. May help in this case. Check out evm_increaseTime: github.com/ethereumjs/testrpc – Rob Hitchens - B9lab Apr 8 '17 at 6:57
  • @RobHitchens YES: for standard Javascript based unit testing in Truffle, evm_increaseTime would be the best option to simulate different times. – RFV5s Apr 8 '17 at 8:15
  • @RobHitchens, I have search all the testrpc and truffle documentation but I ant figure out how to use evm_increaseTime from the truffle console. Cant you perhaps help?? – RFV5s Apr 11 '17 at 9:41
  • Haven't used it before. Seems like the more general question here is how to access any of the TestRPC methods listed there from inside the truffle context. Doesn't seem obvious. – Rob Hitchens - B9lab Apr 11 '17 at 10:16
2

In general, yes, probably better to set static values for all the important test vars.

In the contract, now is the block.timeStamp.

This timeStamp is approximate in practice, with variance up to fifteen minutes.

I would inquire to the contract or blockchain to get the time that was actually used.

In similar situations, I've had the test wait for a mined block with a timestamp past a time I'm waiting for. I can see how this will be a problem if you have to wait 12 days.

Might be good to break down and parameterize the milestones so you can test with smaller intervals, so the whole thing can pass all tests in a minute or two. Possibly not satisfactory for a "final" test but sufficient for initial tests.

Hope it helps.

3

If you use pyethereum for testing - which I highly recommend, it's lovely - you can directly alter the timestamp of the simulated block that is mining your transaction.

self.s = t.state()
self.s.block.timestamp = self.s.block.timestamp + 86400
self.s.mine(1)
some_val = your_contract.do_something(some_parameter)
self.assertEqual(some_val, whatever)

See a working example here (maybe a bit out-of-date): https://github.com/realitykeys/subjectivocracy/blob/master/contracts/test.py#L85

  • Truffle works best with testrpc. I tried setting up pyethereum on Windows and just gave up after a day or so. I also could find any documentation about solidity code, is it only compatible with serpent? – RFV5s Apr 11 '17 at 9:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.