Solidity – Fixing the Error: Contract Not Deployed to Detected Network in Truffle Test

soliditysolidity-0.8.xtruffletruffle-test

As I excessively read all posts given and none solved my problem I'm opening this thread. Please don't consider every test useful as I'm in the development of useful tests. As mentioned it is about the (network/artifact mismatch) error.

In the following, you will find my source code

./test/TestEscrow.js file

/* 
  @dev: web3 instance is available in each test
*/

// Contracts that need to be interacted within the test
const TestEscrow = artifacts.require("../contracts/Escrow.sol");

contract("Testing Escrow SC", (accounts) => {
  const importer = accounts[0];
  const exporter = accounts[1];
  const carrier = accounts[2];

  it("ESCROW: Initial escrow contract test", async () => {
    const escrow = await TestEscrow.deployed();
    console.log(escrow); //checking if contract was properly deployed

    const escrowBalance = await escrow.getBalance.call(accounts[0]);
    console.log(escrowBalance);
    const escrowBalanceToNumber = await escrowBalance;
    console.log(escrowBalanceToNumber);
    assert.equal(escrowBalance, 100, "100 was not in the first account");
  });

  it("ESCROW: Constructor test", async () => {
    const escrow = await TestEscrow.deployed();
    console.log(escrow); //checking if contract was properly deployed

    await escrow.new(carrier, exporter, 10, { from: accounts[0] });
    assert.equal(
      escrow.owner,
      importer,
      "The importer is not the contract owner, which is accounts[0]."
    );
    assert.equal(escrow.exporter, exporter, "The exporter is not accounts[1].");
    assert.equal(escrow.carrier, carrier, "The carrier is not accounts[2].");
    assert.equal(
      escrow.value,
      10,
      "THe value of the ESCROW account is not 10."
    );
  });
});

./contracts/Escrow.sol

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;

contract Escrow{
    
    address payable owner;
    address payable importer; 
    address payable exporter;
    address carrier;
    uint value;
    State state;
 

    event EscrowCreated(address indexed _importer, address indexed _exporter, address indexed _carrier, uint _value);

    constructor (address payable _carrier, address payable _exporter, uint256 _value) {
        require(_carrier != address(0), "Carrier missing");
        require(_exporter != address(0), "Exporter missing");
        owner = payable(msg.sender); //we assume the impoert is the person calling
        importer = payable(msg.sender);
        carrier = _carrier;
        exporter = _exporter;
        value = _value;
        state = State.waitingForDeposit;
        emit EscrowCreated(msg.sender, _exporter, _carrier, _value);
    }
    
}

./migrations/1_initial_migrations.js

var Migrations = artifacts.require("./Migrations.sol");

module.exports = function (deployer) {
  deployer.deploy(Migrations);
};

./migrations/2_deploy_contracts.js

var Escrow = artifacts.require("../contracts/Escrow.sol");
var Lc = artifacts.require("../contracts/Lc.sol");

module.exports = function (deployer, network, accounts) {
  deployer.then(async () => {
    deployer
      .deploy(Escrow, accounts[1], accounts[2], 10, {
        from: accounts[0],
      })
      .then((inst) => console.log(inst));
    deployer.deploy(Lc);
  });
};

truffle-config.js

const path = require("path");

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
  // contracts_build_directory: path.join(__dirname, "client/src/contracts"),
  networks: {
    develop: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*",
    },
    test: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*",
    },
  },
  compilers: {
    solc: {
      version: "^0.8.0",
      settings: {
        /* 
          Optimizer is able to allocate assigned variables in a more efficient way. For example it adds up multiple uint64 to a whole uint256 block. 
        */
        optimizer: {
          enabled: true,
          runs: 200,
        },
      },
    },
  },
};

So now the problem is if I'm running truffle test or truffle test --network develop. Although contracts are compiled and the initial contract is deployed, because it returns the EscrowCreated Event (see Escrow.sol), it still says that both tests are failing and in both cases, the <(network/artifact mismatch)> Error is issued. See the error message below:

Compiling your contracts...
===========================
✔ Fetching solc version list from solc-bin. Attempt #1
> Compiling .\contracts\Escrow.sol
> Compiling .\contracts\Helpers.sol
> Compiling .\contracts\Lc.sol
> Compiling .\contracts\Migrations.sol
✔ Fetching solc version list from solc-bin. Attempt #1
> Artifacts written to C:\Users\andre\AppData\Local\Temp\test--34512-KTgIYcQedlwC
> Compiled successfully using:
   - solc: 0.8.10+commit.fc410830.Emscripten.clang



  Contract: Testing Escrow SC
    1) ESCROW: Initial escrow contract test

#########################################################
######## Wildcard for Smart Contract Information ######## 
#########################################################

 Events emitted during test:
    ---------------------------

    Escrow.EscrowCreated(
      _importer: <indexed> 0x9820BA3aCf2f2AadB6b4C704eb485C35a9328A3E (type: address),
      _exporter: <indexed> 0x9B7E32E202De7C64ad0d13d157A2D8425A1C7336 (type: address),
      _carrier: <indexed> 0xf5AD10f4dF3180d59046112708bFf9A23B34dc43 (type: address),
      _value: 10 (type: uint256)
    )


    ---------------------------
    2) ESCROW: Constructor test
    > No events were emitted


  0 passing (821ms)
  2 failing

  1) Contract: Testing Escrow SC
       ESCROW: Initial escrow contract test:
     Error: Escrow has not been deployed to detected network (network/artifact mismatch)
      at Object.checkNetworkArtifactMatch (C:\Users\andre\AppData\Roaming\nvm\v16.6.1\node_modules\truffle\build\webpack:\packages\contract\lib\utils\index.js:247:1)
      at Function.deployed (C:\Users\andre\AppData\Roaming\nvm\v16.6.1\node_modules\truffle\build\webpack:\packages\contract\lib\contract\constructorMethods.js:83:1)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at Context.<anonymous> (test\TestEscrow.js:9:20)

  2) Contract: Testing Escrow SC
       ESCROW: Constructor test:
     Error: Escrow has not been deployed to detected network (network/artifact mismatch)
      at Object.checkNetworkArtifactMatch (C:\Users\andre\AppData\Roaming\nvm\v16.6.1\node_modules\truffle\build\webpack:\packages\contract\lib\utils\index.js:247:1)
      at Function.deployed (C:\Users\andre\AppData\Roaming\nvm\v16.6.1\node_modules\truffle\build\webpack:\packages\contract\lib\contract\constructorMethods.js:83:1)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at Context.<anonymous> (test\TestEscrow.js:20:20)

Lastly I'm using

Truffle v5.4.5 (core: 5.4.5)
Solidity - ^0.8.0 (solc-js)
Node v16.6.1
Web3.js v1.5.1

Hope somebody can explain to me what exactly happens that my tests are not matching the artifact. The more detailed the answer, the more I will learn. Looking forward to your response!

Kind regards,
Andreas

#2 Edited (Question): Sharing a thought: I thought that I maybe got something wrong about the relationship between the migration files (cause I'm calling there the constructor of the Escrow construct with its arguments) and I thought that the actual initialization of the contract will more likely be happening in the test file, when defining my actual test cases. Looking forward if you can clarify this additional question/thought.

#3 Edited (Additional Information): Even though i delete all files in my .build/contracts/ directory, re-run truffle compile and truffle migrate --reset --network develop the error still exists.

#4 Edited (Question):Furthermore I observed that the contract ABI in ./build/contracts/ do not contain a value inside of their "networks": {} parameter. Is that normal?

Best Answer

Your issue is here :

var Escrow = artifacts.require("../contracts/Escrow.sol");
var Lc = artifacts.require("../contracts/Lc.sol");

module.exports = function (deployer, network, accounts) {
  deployer.then(async () => {
    deployer
      .deploy(Escrow, accounts[1], accounts[2], 10, {
        from: accounts[0],
      })
      .then((inst) => console.log(inst));
    deployer.deploy(Lc);
  });
};

You are using promises, but you never return it, so it is never fulfilled and the deployment information never updated.

If you whish to keep the promise version (not recommended) switch to this (slightly modified version not deploying your LC contract which I do not have):

var Escrow = artifacts.require("Escrow");

    module.exports = function (deployer, network, accounts) {
      deployer.then(async () => {
        return deployer.deploy(Escrow, accounts[1], accounts[2], 10, {from: accounts[0]})
      });
    };

Or you could simply switch to async/await (recommended) that you are already using elsewhere :

var Escrow = artifacts.require("Escrow");

module.exports = function (deployer, network, accounts) {
  deployer.then(async () => {
    await deployer.deploy(Escrow, accounts[1], accounts[2], 10, {from: accounts[0]})
  });
};

Your first test is still failing but you did not provide the full implementation so I only validated that the deployment is successful.

I tested with this code :

  it("ESCROW: Initial escrow contract test", async () => {
    const escrow = await TestEscrow.deployed();
    //const escrowBalance = await escrow.getBalance.call(accounts[0]);
    //const escrowBalanceToNumber = await escrowBalance;
    //assert.equal(escrowBalance, 100, "100 was not in the first account");
  });

Your second test will not work given your current contract code :

address payable owner;
address payable importer; 
address payable exporter;
address carrier;
uint value;
State state;

The default visibility is internal so not accessible from the outside. Simply specifying public when required will allow external access to your public variables (assuming here that they all need to be public) :

address payable public owner;
address payable public importer; 
address payable public exporter;
address public carrier;
uint public value;
State public state;

Then change the code of your second test to :

  it("ESCROW: Constructor test", async () => {

    const escrow = await TestEscrow.new(carrier, exporter, 10, { from: accounts[0] });

    assert.equal(
      await escrow.owner(),
      importer,
      "The importer is not the contract owner, which is accounts[0]."
    );
    assert.equal(await escrow.exporter(), exporter, "The exporter is not accounts[1].");
    assert.equal(await escrow.carrier(), carrier, "The carrier is not accounts[2].");
    assert.equal(
      await escrow.value(),
      10,
      "THe value of the ESCROW account is not 10."
    );
  });

To make use of the auto generated "getters" allowing you to read the state of your public variables.

After those changes everything is working fine on my side.

Related Topic