Error while deploying ERC1820Registry without truffle

Hello !
I was trying to deploy ERC1820Registry, first i did:

const { singletons } = require('openzeppelin-test-helpers');

and then i did :

    await singletons.ERC1820Registry(_address);
    let Token = await deploy('Token',{ from: _address, args: ["simpletoken", "ST", arr]});

Here i am not using truffle , the function “deploy” is a function that compiles the smart contract with solc then deploys it on ganache …
I tried deploying other smart contracts using that function and it works so far.
My problem is when it hits the line await singletons.ERC1820Registry i get this error :

I guess if im using my own deploy function , then i can’t use singletons ? maybe i should deploy the contract erc1820 on my own ?

Thank you !

2 Likes

Hi @Sarah,

OpenZeppelin Test Helpers 0.5 supports plain Web3.js workflows.

I assume based on openzeppelin-test-helpers that you have an older version.

I suggest that you update to the latest version (npm install @openzeppelin/test-helpers) and try with that.

Hi @abcoathup !
Thank you for the reply i tried with “@openzeppelin/test-helpers”: “^0.5.4” , but i still get the same error…

1 Like

Hi @Sarah,

Are you able to share your repository (if it is open source) or a cut down sample?

Otherwise I will need to create a project without truffle (I use Truffle and OpenZeppelin SDK) so I can reproduce the issue.

Hi @abcoathup , i could share the files that i think are involved , here : https://repl.it/repls/IncompatibleIdealAlgorithm i am sorry the paths are not correct let me know if you need something else !
I basically import the web3 and deploy function from the helper file and use it to deploy my smart contracts …
thank you

1 Like

Hi @Sarah,

Unfortunately I wasn’t able to reproduce the error. I cut down the sample code so it was just deploying an empty contract and the ERC1820Registry.
I am running on Windows Subsystem for Linux

$ node --version
v10.16.0
$ npm --version
6.13.0

When I ran the script (after running ganache-cli -d in a separate terminal) I can see the token deployed in ganache-cli

$ node index.js
token deployed at 0x32Cf1f3a98aeAF57b88b3740875D19912A522c1A

Output in ganache-cli:

  Transaction: 0xfefb2da535e927b85fe68eb81cb2e4a5827c905f78381a01ef2322aa9b0aee8e
  Contract created: 0x1820a4b7618bde71dce8cdc73aab6c95905fad24
  Gas usage: 711453
  Block Number: 2
  Block Time: Tue Nov 19 2019 14:29:17 GMT+1100 (Australian Eastern Daylight Time)

package.json

{
  "name": "lucky",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "@openzeppelin/contracts": "^2.4.0",
    "@openzeppelin/test-helpers": "^0.5.4",
    "chai": "^4.2.0",
    "ganache-core": "^2.8.0",
    "solc": "^0.5.12",
    "web3": "^1.2.1"
  }
}

index.js

const helper =  require('./_helper');
const { singletons } = require('@openzeppelin/test-helpers');

(async () => {
    var { deploy, accounts, web3 } = await  helper.testHelper(`./contracts/`); // 
    //Deploy token contract
    let arr = [accounts[1]]
    await singletons.ERC1820Registry(accounts[1]);
    let Token = await deploy('Token',{ from: accounts[1], args: ["sahar", "sah", arr]});
    console.log('token deployed at', Token._address)
})().catch(e => {
   console.log(e)
});

_helper.js

const fs = require ('fs');
const solc= require('solc');
const linker= require('solc/linker');
const Ganache= require('ganache-core');
const Web3= require('web3');

var solcOpts = {
  language: 'Solidity',
  settings: {
    metadata: { useLiteralContent: true },
    outputSelection: {
      '*': {
        '*': ['abi', 'evm.bytecode.object']
      }
    }
  }
}

// Instantiate a web3 instance. Start a node if one is not already running.
 async function web3Helper(provider = 'ws://127.0.0.1:8545') {
  var web3 = new Web3(provider);
  var instance = await server(web3, provider)
  return { web3, server: instance }
}
module.exports.web3Helper = web3Helper;


function findImportsPath(prefix) {
  return function findImports(path) {
    try {
      return {
        contents: fs.readFileSync(prefix + path).toString()
      }
    } catch (e) {
      return { error: 'File not found' }
    }
  }
}



  async function compile(contractpath,contractName)
  {
    var web3 = new Web3("ws://"+process.env.GANACHE_HOST+":"+process.env.GANACHE_PORT);
   var sources = {
      [contractName]: {
        content: fs.readFileSync(`${contractpath}/${contractName}.sol`).toString()
      }
    }
    var compileOpts = JSON.stringify({ ...solcOpts, sources })

    // Compile the contract using solc
    var rawOutput = solc.compileStandardWrapper(
      compileOpts,
      findImportsPath(contractpath)
    )
    var output = JSON.parse(rawOutput)

    // If there were any compilation errors, throw them
    if (output.errors) {
      output.errors.forEach(err => {
        if (!err.formattedMessage.match(/Warning:/)) {
          throw new SyntaxError(err.formattedMessage)
        }
      })
    }

    var { abi, evm: { bytecode } } = output.contracts[contractName][
      contractName
    ]
     return {abi,web3};


  }

module.exports.compile = compile;


 async function testHelper(contracts, provider) {
  const { web3, server } = await web3Helper(provider)
  const accounts = await web3.eth.getAccounts()



  async function deploy(contractName, { from, args, log }) {

    var sources = {
      [contractName]: {
        content: fs.readFileSync(`${contracts}/${contractName}.sol`).toString()
      }
    }
    var compileOpts = JSON.stringify({ ...solcOpts, sources })

    // Compile the contract using solc
    var rawOutput = solc.compileStandardWrapper(
      compileOpts,
      findImportsPath(contracts)
    )
    var output = JSON.parse(rawOutput)

    // If there were any compilation errors, throw them
    if (output.errors) {
      output.errors.forEach(err => {
        if (!err.formattedMessage.match(/Warning:/)) {
          throw new SyntaxError(err.formattedMessage)
        }
      })
    }

    var { abi, evm: { bytecode } } = output.contracts[contractName][
      contractName
    ]

    // Deploy linked libraries
    for (let linkedFile in bytecode.linkReferences) {
      for (let linkedLib in bytecode.linkReferences[linkedFile]) {
        let libObj = output.contracts[linkedFile][linkedLib]
        let LibContract = new web3.eth.Contract(libObj.abi)
        var libContract = await LibContract.deploy({
          data: libObj.evm.bytecode.object
        }).send({
          from,
          gas: 900000000
        })

        let libs = { [`${linkedFile}:${linkedLib}`]: libContract._address }

        bytecode.object = linker.linkBytecode(bytecode.object, libs)
      }
    }

    if (!bytecode.object) {
      throw new Error(
        'No Bytecode. Do the method signatures match the interface?'
      )
    }

    if (process.env.BUILD) {
      fs.writeFileSync(
        __dirname + '/../src/contracts/' + contractName + '.js',
        'module.exports = ' +
          JSON.stringify(
            {
              abi,
              data: bytecode.object
            },
            null,
            4
          )
      )
    }

    // Instantiate the web3 contract using the abi and bytecode output from solc
    var Contract = new web3.eth.Contract(abi)
    var contract

    await new Promise(async resolve => {
      var chainId = web3.eth.net.getId()

      var data = await Contract.deploy({
        data: '0x' + bytecode.object,
        arguments: args
      }).encodeABI()
      web3.eth
        .sendTransaction({
          data,
          from,
          value: 0,
          gas: 4612388,
          chainId
        })
        .once('transactionHash', hash => {
          if (log) {
            console.log('Transaction Hash', hash)
          }
        })
        .once('receipt', receipt => {
          if (log) {
            console.log(
              `Deployed ${contractName} to ${receipt.contractAddress} (${
                receipt.cumulativeGasUsed
              } gas used)`
            )
          }
        })
        .catch('error', err => {
          console.log('eeeeeeeeeeeeeeeeeeeeeeeeeee', err)
          resolve()
        })
        .then(instance => {
          contract = new web3.eth.Contract(abi, instance.contractAddress)
          resolve()
        })
    })

    if (contract) {
      // Set some default options on the contract
      contract.options.gas = 1500000
      contract.options.from = from
    }

    return contract
  }

  return { web3, accounts, deploy, server}
}

// Start the server if it hasn't been already...
async function server(web3, provider) {
  try {
    // Hack to prevent "connection not open on send" error when using websockets
    web3.setProvider(provider.replace(/^ws/, 'http'))
    await web3.eth.net.getId()
    web3.setProvider(provider)
    return
  } catch (e) {
    /* Ignore */
  }

  var port = '7545'
  if (String(provider).match(/:([0-9]+)$/)) {
    port = provider.match(/:([0-9]+)$/)[1]
  }
  var server = Ganache.server()
  await server.listen(port)
  return server
}
module.exports.testHelper = testHelper;

Token.sol

pragma solidity ^0.5.0;

contract Token {
}

The issue seems to be related to the connection with the node’s RPC endpoint.

test-helpers by defaults looks for a provider in the port 8545. I see that you’re using 7545. Take a look at the Configuration section in the README and follow the steps to configure the provider and let us know how it goes!

2 Likes

Hi @sarah,

I ran ganache-cli on port 7545 and got the same JSON error as you did.

I added the following line to index.js to configure as per excellent pickup by @frangio and it now works. Sorry I didn’t spot this in the first place.

require('@openzeppelin/test-helpers/configure')({ provider: 'http://127.0.0.1:7545' });

index.js (updated)

const helper =  require('./_helper');
const { singletons } = require('@openzeppelin/test-helpers');
require('@openzeppelin/test-helpers/configure')({ provider: 'http://127.0.0.1:7545' });

(async () => {
    var { deploy, accounts, web3 } = await  helper.testHelper(`./contracts/`); // 
    //Deploy token contract
    let arr = [accounts[1]]
    await singletons.ERC1820Registry(accounts[1]);
    let Token = await deploy('Token',{ from: accounts[1], args: ["sahar", "sah", arr]});
    console.log('token deployed at', Token._address)
})().catch(e => {
   console.log(e)
});
2 Likes

@abcoathup @frangio Thank you so much ! indeed that solved my problem !
Thank youuu ! :DDDDDD

2 Likes

Awesome! :smile:

By the way, I think you will like our new project: Test Environment. I noticed that your _helper.js is doing essentially the same thing of spinning up a Ganache server. Our library will also automatically configure Test Helpers for you, and will work great if you want to parallelize your tests using other test runners like Jest or Ava.

2 Likes