1

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?

2 Answers 2

1

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.

4
  • First I'm so damn thankful, really I just struggled the so long for this issue... Thanks!
    – Ndrslmpk
    Commented Nov 15, 2021 at 22:03
  • ... as I'm curious I'm having a few more questions: (1) Can you explain why I need to use await to access the escrow state variables? (2) Am I supposed to call the constructor of the contract in the migration file? I thought it might be more reasonable to do it inside of the actual test as shown in the docs But what is then the difference between the constructor call in the test vs migrations file.
    – Ndrslmpk
    Commented Nov 15, 2021 at 22:04
  • 1
    (1) : Not sure to understand when you ask for the use of await to access the escrow variable. It's never used simply as await escrow only as await escrow.function(). You can use promises or async/await it's just that those are asynchronous operations, you do need to communicate with the nodes / blockchain after all. (2) : The only real difference is that the migration file wraps the deployement in the deployer object that will update some informations (address of the contract / network / etc.. ) in the artifact. and also will not deploy again if the contract is already deployed.
    – hroussille
    Commented Nov 15, 2021 at 22:11
  • You can see more about it here : trufflesuite.com/docs/truffle/getting-started/… On the other hand, calling the "constructor" will deploy a new instance every time, bypassing the deployer object. The constructor basically creates and send the tx to deploy your contract and the deployer object used in the migration file wraps that and ensures that it is recorded and done only if required.
    – hroussille
    Commented Nov 15, 2021 at 22:12
0

Solution :

In My case I am using truffle-contract to load contract abi . By default truflle-contract network id is 1.

But I am using goreli network id 5. We need to setNetwork while loading contract `

            const contract = require('truffle-contract');   
            const MyContract = contract(MyContract);    
    
            MyContract.setProvider(web3.currentProvider);    
            MyContract.setNetwork(5) 

`

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.