OpenZeppelin Test Environment global web3 not defined error

When runs with test environment "mocha --exit --recursive test", it has the following error but it runs fine with truffle test

Error Message:

ReferenceError: web3 is not defined

Steps to reproduce:

  1. yarn add @gnosis.pm/safe-contracts
  2. Then create testGnosisModule.js and have the following codes:
const Web3 = require('web3');
const web3 = new Web3();
const utils = require('@gnosis.pm/safe-contracts/test/utils/general');
2 Likes

Hi @leckylao,

I assume the issue is that you first need to convert your test from Truffle to OpenZeppelin Test Environment.

Please see the documentation for details: https://docs.openzeppelin.com/test-environment/0.1/migrating-from-truffle#switching_to_test_envrionment

OpenZeppelin Test Environment provides a web3 provider connected to the local test blockchain (see the API: https://docs.openzeppelin.com/test-environment/0.1/api#web3)

Thank you @abcoathup for the reply. I’ve created the repo for reproducing error https://github.com/leckylao/GnosisSafeModule/tree/master

1 Like

Hi @leckylao,

I wasn’t sure what you were trying to do here.

The GnosisSafe tests (at least general.js from utils) use web3 (being provided by Truffle).

I assume you would need to first convert the tests and the utility scripts to OpenZeppelin Test Environment. I was able to get the script running by starting this process.

general.js

I created a local copy of general.js and added in the require for OpenZeppelin Test Environment

// test/general.js
const { accounts, contract, web3 } = require('@openzeppelin/test-environment');

const util = require('util');
const solc = require('solc')
const lightwallet = require('eth-lightwallet')
const abi = require("ethereumjs-abi")

...

testGnosisSafeModule.js

I obtained web3 from OpenZeppelin Test Environment, used the local general.js and updated the fromArtifact to obtain the artifacts once I compiled them.

const { accounts, contract, web3 } = require('@openzeppelin/test-environment');
const [ owner ] = accounts;

describe('GnosisSafeModule', function () {
  const utils = require('./general.js');
  const GnosisSafe = contract.fromArtifact("GnosisSafe");
  const ProxyFactory = contract.fromArtifact("GnosisSafeProxyFactory");
  const GnosisSafeModule = contract.fromArtifact("GnosisSafeModule");
});

Thank you for the reply @abcoathup. Sorry for not specifying clearly.

So the problem is it runs fine with truffle test but failed on yarn test running with openzeppelin/test-environment. You can test on https://github.com/leckylao/GnosisSafeModule. The general.js is from @gnosis.pm/safe-contracts, so once you ran the yarn install you would have it.

const utils = require('@gnosis.pm/safe-contracts/test/utils/general');

It’s having web3 is not defined problem as general.js is looking for a global web3 instance, which I have already defined in the test case and it works on truffle test. So any idea why it failed on running with test-environment?

1 Like

Hi @leckylao,

To use OpenZeppelin Test Environment we need to migrate tests written for Truffle. We can’t just run OpenZeppelin Test Environment on Truffle tests.

The changes are straight forward, please see the documentation for details: https://docs.openzeppelin.com/test-environment/0.1/migrating-from-truffle

This is what I used when I did the above: OpenZeppelin Test Environment global web3 not defined error

Hi @abcoathup,

Could you point out what’s missing in order to use OZ test environment test please? As shown I believe it’s able to run with test environment.


In your example you are making your own general.js which is not the case as I would like to use the one from the package const utils = require('@gnosis.pm/safe-contracts/test/utils/general'); and that’s where it’s causing the problem.

Additionally I found you could still run truffle test on oz test environment test as it’s still compatible but seems not the other way around. For example in this case I can’t get it work with OZ test environment and have to stick with truffle test.

2 Likes

Hi @leckylao,

Currently the repository https://github.com/leckylao/GnosisSafeModule doesn’t work for truffle test.

$ npx truffle test
Could not find suitable configuration file.
Truffle v5.1.24 (core: 5.1.24)
Node v10.19.0

I initialized using truffle to create the config file but didn’t overwrite the contracts or tests.

$ npx truffle init

But as you don’t have a Migrations.sol I had to delete the migrations script that truffle init creates.

I had to fix the artifact names (you don’t need the .sol e.g. ./GnosisSafe.sol can be GnosisSafe)

const { accounts, contract } = require('@openzeppelin/test-environment');
const [ owner ] = accounts;

describe('GnosisSafeModule', function () {
  const Web3 = require('web3');
  const web3 = new Web3();
  const utils = require('@gnosis.pm/safe-contracts/test/utils/general');
  const GnosisSafe = contract.fromArtifact("GnosisSafe");
  const ProxyFactory = contract.fromArtifact("GnosisSafeProxyFactory");
  const GnosisSafeModule = contract.fromArtifact("GnosisSafeModule");
});

I had to install @truffle/debug-utils

$ npm i @truffle/debug-utils

I was then able to run npx truffle test


OpenZeppelin Test Environment

Truffle provides web3

OpenZeppelin Test environment provides web3 but you need to obtain it.

This means that the current utils/general.js works as is with Truffle but requires the addition of const { web3 } = require('@openzeppelin/test-environment');
There may also be other things which would need to be migrated to work on OpenZeppelin Test Environment. It depends what you use from this helper.

I created a local copy of utils/general.js with the only difference being the addition of the following line:

const { web3 } = require('@openzeppelin/test-environment');

I then modified testGnosisSafeModule.js as follows to:

  • add getting web3 from @openzeppelin/test-environment.
  • change to use the local copy of `./utils/general.js’
  • fixed artifact names (you don’t need the .sol e.g. ./GnosisSafe.sol can be GnosisSafe)

testGnosisSafeModule.js

const { accounts, contract, web3 } = require('@openzeppelin/test-environment');
const [ owner ] = accounts;

describe('GnosisSafeModule', function () {
  //const Web3 = require('web3'); provided by @openzeppelin/test-environment
  //const web3 = new Web3();
  const utils = require('./utils/general'); // use local copy to get web3 from test-environment
  const GnosisSafe = contract.fromArtifact("GnosisSafe");
  const ProxyFactory = contract.fromArtifact("GnosisSafeProxyFactory");
  const GnosisSafeModule = contract.fromArtifact("GnosisSafeModule");
});
$ npm run test

> test-gnosis@0.1.0 test /home/abcoathup/projects/forum/GnosisSafeModule
> mocha --exit --recursive test



  0 passing (1ms)
1 Like

Firstly It doesn’t need Migrations.sol as we are not testing deploy, we are just testing import here.

Secondly it doesn’t need init, and not sure why you need @truffle/debug-utils. But please try with node v11.10.1, then yarn/npm install. As you can see it will load from truffle-config.js for configuration file and it runs fine without error.

Thirdly, you are correct, it doesn’t need .sol. And could obtain web3 from test-environment

At the end, as you would need to upgrade the general.js to have the web3 local variable to work. So I think the issue here is why the web3 global variable can’t pass inside the general.js in using test-environment but it can read it from truffle test?

line 6 from general.js which is using web3 from global variable

2 Likes

Hey @leckylao! Thanks for trying Test Environment!
Using global variables is considered a bad practice, but I know sometimes there is no other choice. You can fix your tests with one line. Just set global web3 instance before requesting Gnosis utils.

const { accounts, contract, web3 } = require('@openzeppelin/test-environment');
const [ owner ] = accounts;

global.web3 = web3;

describe('GnosisSafeModule', function () {
  const utils = require('@gnosis.pm/safe-contracts/test/utils/general');
  const GnosisSafe = contract.fromArtifact("GnosisSafe");
  const ProxyFactory = contract.fromArtifact("GnosisSafeProxyFactory");
  const GnosisSafeModule = contract.fromArtifact("GnosisSafeModule");
});

This would run without any problem. Let me know how it works for you!

2 Likes

Thanks @ylv-io. I didn’t know you could set a global variable like that in JavaScript.