1

I'm trying to write and run tests for my smart contract and I get this error: "Error: Provider not set or invalid"

Smart contract code:

const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const provider = ganache.provider();
const web3 = new Web3(provider);

const { interface, bytecode } = require('../compile');

let lottery;
let accounts;

beforeEach(async () => {
  accounts = await web3.eth.getAccounts();

  const contractJson = JSON.parse(interface);

  lottery = await new web3.eth.Contract(contractJson)
    .deploy({data: bytecode})
    .send({ from : accounts[0], gas: '1000000' })
});

describe('Lottery Contract', () => {
  it('deploys a contract', () => {
    assert.ok(lottery.options.address);
  });

  it('allows one account to enter', async () => {
    await lottery.methods.enter().send({
      from: accounts[0],
      value: web3.utils.toWei('0.02', 'ether')
    });

    const players = await lottery.methods.getPlayers().call({
      from: accounts[0]
    });

    assert.equal(accounts[0], players[0]);
    assert.equal(1, players.length);
  });
});

It fails exactly after this code:

await lottery.methods.enter().send({
          from: accounts[0],
          value: web3.utils.toWei('0.02', 'ether')
        });

Any ideas?

2

I have read the solution in one of Stephen Grider's Udemy course:

    const assert = require('assert');
    const ganache = require('ganache-cli');
    const Web3 = require('web3');
    const provider = ganache.provider();
    const web3 = new Web3(provider);

    const { interface, bytecode } = require('../compile');

    let lottery;
    let accounts;

    beforeEach(async () => {
      accounts = await web3.eth.getAccounts();

      const contractJson = JSON.parse(interface);

      lottery = await new web3.eth.Contract(contractJson)
        .deploy({data: bytecode})
        .send({ from : accounts[0], gas: '1000000' })

      /* ************ HERE, ADD THE NEXT LINE ******************* */
      lottery.setProvider(provider);
      /* ******************************************************** */
    });

    describe('Lottery Contract', () => {
      it('deploys a contract', () => {
        assert.ok(lottery.options.address);
      });

      it('allows one account to enter', async () => {
        await lottery.methods.enter().send({
          from: accounts[0],
          value: web3.utils.toWei('0.02', 'ether')
    });

    const players = await lottery.methods.getPlayers().call({
      from: accounts[0]
    });

    assert.equal(accounts[0], players[0]);
    assert.equal(1, players.length);
   });
  });

According to Grider's comment in the course, this is due to some bug in Web3.

Hope it helps.

2

After debugging around I've visited ganache-core repo and found the solution inside their test folder.

The file is ganache-core/test/runtime_errors.js and the solution to my problem is the code below:

...
testState.ErrorContract.deploy({data: testState.code})
      .send({from: testState.accounts[0], gas: 3141592})
      .then(function(instance) {
        // TODO: ugly workaround - not sure why this is necessary.
        if (!instance._requestManager.provider) {
          instance._requestManager.setProvider(web3.eth._provider);
        }
        testState.errorInstance = instance;
        done();
      });
...

Still not sure why requestManager didn't get my provider set, but it works now and maybe will be useful for someone else facing the same issue.

0

Immediately after creating the contract

lottery = await new web3.eth.Contract(contractJson)
.deploy({data: bytecode})
.send({ from : accounts[0], gas: '1000000' });

you must always give it the provider you got from ganache

lottery.setProvider(provider);

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.