I'm currently using Provable (formerly Oraclize) to make a CRON job :

constructor() public payable {
    OAR = OracleAddrResolverI(0x6F486C8BD6fc43eA212E93CCF8ce047C7f1Cb475);
    provable_query(7 days, "URL", "");

In order to test that (Truffle, Mocha, Chai), I'm importing the following:

const Web3 = require("web3");
const { waitForEvent } = require("./utils");
const { time } = require("@openzeppelin/test-helpers");
const web3 = new Web3(
    new Web3.providers.WebsocketProvider("ws://localhost:9545")

Except for time coming from OpenZeppelin, those come from the Provable truffle box.

(waitForEvent, in particular, can return an event name and its description when triggered from Solidity.)

In order to test that, I have the following test:

it("Should have logged a new Provable query after the contract creation + cooldown", async () => {
    console.log(await time.latest());
    await time.increase(TIME_BETWEEN_TWO_QUERIES);
    console.log(await time.latest());
    const {
        returnValues: { description },
    } = await waitForEvent(contractEvents[PROVABLE_QUERY_EVENT]);
        description === PROVABLE_QUERY_STRING,
        "Provable query incorrectly logged!"

The time increase seems to work, but the waitForEvent promise is still waiting for TIME_BETWEEN_TWO_QUERIES to complete, which is problematic.

Does anyone know how I can properly test those time-sensitive matters? How to "advance" time for Provable to be able to detect it?

  • 1
    Why don't you put the time increase before the waitForEvent promise? – goodvibration Apr 4 at 12:26
  • I tried that before, but it didn't change anything... So it makes me think that the issue isn't coming from here, but rather from the websocket provider that may have its own time to manage. Does it make sense? – Thanh-Quy Nguyen Apr 4 at 13:37
  • @goodvibration I went further in the tests and edited the original post to detail these – Thanh-Quy Nguyen Apr 4 at 16:00
  • I don't know anything about OZ time-helper, but why don't you simply try web3.currentProvider.send({method: "evm_increaseTime", params: [TIME_BETWEEN_TWO_QUERIES]})? – goodvibration Apr 4 at 16:06
  • I tried that, as well as method: 'evm_mine', id: TIME_BETWEEN_TWO_QUERIES, and I'm getting TypeError: callback is not a function in both cases – Thanh-Quy Nguyen Apr 4 at 16:37

Have a look at the OpenZeppelin Test Helpers documentation: https://docs.openzeppelin.com/test-helpers/0.5/configuration#provider

Including the time related operations: https://docs.openzeppelin.com/test-helpers/0.5/api#time

If you have questions on using OpenZeppelin you can ask in the Community Forum: https://forum.openzeppelin.com/

Disclosure: I am the Community Manager at OpenZeppelin

| improve this answer | |
  • Hi, like I said in my original post I was already using it in my original code. But the problem was coming from Provable, which I got the answer from their support, so I'm going to post it right now! – Thanh-Quy Nguyen Apr 7 at 9:32

Okay, so I got the answer from Provable's gitter. The way it works is the following:

  • Whenever a provable query is made (through provable_query or provable_newRandomDSQuery for example), a request is immediately sent to Provable's servers, even in a test environment
  • The delay passed as an argument in the Provable query is passed as an argument to a setTimeout (or equivalent) so Provable's servers "know" when to make a request to the __callback function from the smart contract

Therefore, since the Provable's server time is completely independent from the evm, using time.increase from OpenZeppelin-test-helpers or the evm increase time functions won't have any effect. And there is no way, as of today, to increase time of Provable's servers in a test environment, since it is not using a VM but their actual servers.

Alternative solutions

In order to go around that problem, a simple idea would be to declare constants at the top of smart contracts using provable_query functions to make these a reasonable delay to wait, and to change these for production.

| improve this answer | |

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.