Truffle Tests not being run against contract deployed to Ganache instead uses another contract address

I have truffle set up with Ganache. I am running tests on my solidity contract that involve sending ether to the contract and withdrawing it from the contract. Now, my tests are PASSING, but when I look, none of the transactions are being done against the actual address of my deployed contract as shown in Ganache and Truffle.

In other words, when I run migrate in Truffle, a contract address is shown as the deployed address. Let’s call that . When I look in the Ganache UI, under contracts, it shows the migrations contract and the contract - same as in Truffle. OK, so far so good.

Now, when I run my tests, they seems to run fine (no errors). And in Ganache the balances of the affected accounts are changing their amounts as expected, and the transactions are showing in Ganache transactions tab. BUT, the transactions are being sent to an entirely different contract address!!

I have no idea where that address is coming from or why my tests think it is the contract address when Truffle and Ganace seem to think otherwise.

Here is my test file, in case you’re curious about it:

const CoinFlip = artifacts.require("CoinFlip");
const truffleAssert = require('truffle-assertions');

contract("CoinFlip", async function(accounts) {

  it("should make sure the bet is not less than 0.1 ether", async function(){
    let instance = await CoinFlip.deployed();
    console.log(instance.address);
    await truffleAssert.fails(instance.bet(0, {from: accounts[1], value: web3.utils.toWei("1000000000000000", "wei")}),
    truffleAssert.ErrorType.REVERT);
  });

  it("should make sure the bet is not more than 10 ether", async function(){
    let instance = await CoinFlip.deployed();
    console.log(instance.address);
    await truffleAssert.fails(instance.bet(0, {from: accounts[1], value: web3.utils.toWei("9", "ether")}),
    truffleAssert.ErrorType.REVERT);
  });

  it("should reject a bet if not enough in contract to cover it", async function(){
    let instance = await CoinFlip.deployed();
    console.log(instance.address);
    await truffleAssert.fails(instance.bet(0, {from: accounts[2], value: web3.utils.toWei("2", "ether")}),
    truffleAssert.ErrorType.REVERT);
  });

 it("should accept a bet if there is enough in contract to cover it", async function(){
    let instance = await CoinFlip.deployed();
    console.log(instance.address);
    console.log(CoinFlip.address);
    await web3.eth.sendTransaction({from: accounts[0], to: instance.address, value: web3.utils.toWei("15", "ether")});
    await truffleAssert.passes(instance.bet(0, {from: accounts[1], value: web3.utils.toWei("2", "ether")}),
    truffleAssert.ErrorType.REVERT);
  });


});
1 Like

I do not have the contract CoinFlip, so I do not test your file, I think you can remove other test cases, just test the final case to see what would happen.

1 Like

All the cases have the same problem, not just the last.

Here is the contract code:

// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity 0.7.4;

contract CoinFlip {
  uint public contractBalance;
  address owner;

  constructor() {
    owner = msg.sender;
    contractBalance = 0;
  }

  modifier onlyOwner {
    require(msg.sender == owner);
    _;
  }

  // 0 is HEADS and 1 is TAILS
  function bet(uint chosenSide) public payable returns (bytes4 resultBack) {
    // Must be no less than 0.01 ETH and no more than 10 ETH in value
    require(msg.value >= 10000000000000000 && msg.value <= 10000000000000000000, "Improper amount entered.");

    // Contract must have enough funds to cover paying the bet, if won - plus some extra for gas
    contractBalance += msg.value;
    require(contractBalance >= msg.value * 2 + 100000000000000000, "Sorry, the contract cannot cover this bet.");

    uint side = block.timestamp % 2;
    bytes4 result;

    if (side == chosenSide) {
      result = "won";
      uint winnings = msg.value * 2;
      contractBalance -= winnings;
      (bool success, ) = msg.sender.call{value: winnings}("");
      require(success, "Ether send failed");
      return result;
    } else {
      result = "lost";
      return result;
    }
  }

  fallback() external payable {}
  receive() external payable { contractBalance += msg.value; }

  function withdrawAll() public onlyOwner returns(uint) {
      uint toSend = address(this).balance;
      contractBalance = 0;
      (bool success, ) = msg.sender.call{value: toSend}("");
      require(success, "Ether send failed");
      return toSend;
  }

}
1 Like

OK, some more info… this is not an issue with only this project. I just went back and tried with another project that we did on my solidity course. The exact same issue is there. The transactions are going to a different address than the stated contract address in truffle and ganache. I just didn’t notice it before.

So this issue is a deeper on between truffle and ganache - not about my project.

Can anyone else confirm on any project of theirs whether the contract shown on individual transactions in ganache is the same as the contract address shown on the contract tab in ganache?

1 Like

Sorry, I have tested on my local env, and it seems like all things are in the order(I only ran the last test case),
The deployed contract in the truffle:

and the deployed contract in the ganache:


BTW, it is in the second block, the first block also has a contract, but it is the default contract: Migrations.sol

Please look in your transactions tab. Is the same address showing on the transactions? THAT is the thing to check.

1 Like

This one?

1 Like

YES, thanks. OK, so the issue is on my system and not yours. Thanks for verifying.

I actually noticed that EVERY TIME I run the test file, the contract it sends the transactions to is changing.

Currently the address showing in truffle during compile and showing in ganache is:
0xe7a3b28db108176887f730Eb66F222fa0E451205

But take a look at this from running the test file multiple times:

Obviously there must be some kind of misconfiguration on my system but I have no idea what.

1 Like

I think you ran the test case twice or on the different env, I am not sure.

1 Like

Yeah I ran the test file twice, but the address is not the address in ganache AND it keeps changing every time I run the test file.

1 Like

Hi @CryptoEatsTheWorld,

Welcome to the community :wave:

I just wanted to add one thing to @Skyge’s excellent responses and running your test! (Thanks as always @skyge :pray: ).

Currently in your tests you are testing the deployed contract. This means that each test builds on the previous test as you are using the same deployed contract.

I would suggest that you deploy a new contract per test (in a beforeEach so that you are testing your contract independent to other tests.

See the example in the Learn guides where there are multiple tests:

Thanks, yes, I know about using ‘beforeeach’. I just didn’t have a need for using that yet in my testing on this contract.

1 Like

Hi @CryptoEatsTheWorld,

My understanding is that when you run truffle test it also runs the migrations scripts each time, so the tests can either interact with a clean deployed contract (as part of the test) or you can deploy a new contract.

To show this, I created a simple project.

Box.sol

From: https://docs.openzeppelin.com/learn/developing-smart-contracts#box-contract

// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Box {
    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

Box.test.js

Based on: https://docs.openzeppelin.com/learn/writing-automated-tests#writing-unit-tests

// test/Box.test.js
// Load dependencies
const { expect } = require('chai');

// Load compiled artifacts
const Box = artifacts.require('Box');

// Start test block
contract('Box', function () {
  beforeEach(async function () {
    // Deploy a new Box contract for each test
    this.deployedBox = await Box.deployed();
    console.log(`Deployed Box: ${this.deployedBox.address}`);

    this.box = await Box.new();
  });

  // Test case
  it('retrieve returns a value previously stored', async function () {
    // Store a value
    await this.box.store(42);

    // Test if the returned value is the same one
    // Note that we need to use strings to compare the 256 bit integers
    expect((await this.box.retrieve()).toString()).to.equal('42');
  });
});

2_deploy.js

const Box = artifacts.require("Box");

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

Migrate

$ npx truffle migrate

...

2_deploy.js
===========

   Deploying 'Box'
   ---------------
   > transaction hash:    0x12187b4cafff7eb2247a90d148c17486b39668beec9c75ed7689a375525170b3
   > Blocks: 0            Seconds: 0
   > contract address:    0xCfEB869F69431e42cdB54A4F4f105C19C080A601
...

Running Tests

The deployed address is different from the contract manually migrated

$ npx truffle test
Using network 'development'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



  Contract: Box
Deployed Box: 0x9561C133DD8580860B6b7E504bC5Aa500f0f06a7
    ✓ retrieve returns a value previously stored (99ms)


  1 passing (233ms)

Second run (new deployed address)

$ npx truffle test
Using network 'development'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



  Contract: Box
Deployed Box: 0x2612Af3A521c2df9EAF28422Ca335b04AdF3ac66
    ✓ retrieve returns a value previously stored (94ms)


  1 passing (221ms)

Thanks for your time on this, but I am aware of the ability to deploy as NEW on some truffle tests. The thing is, I have not specified this in my testing file, so it should not be doing it. If there is some unknown setting causing this to happen without my consent I;d like to know where I can adjust it.

Also I noticed you are using “development” as your network. I am using Ganache, which is the setup where I am noticing the issue.

Chris

1 Like

Hi @CryptoEatsTheWorld,

When we run truffle test it deploy new contracts using migrations. It doesn’t use existing deployments (unless we tell the deployer not to).

To use the existing deployed contracts we need to use overwrite: false when calling deploy in our migrations scripts.
See Truffle documentation for details: https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations#deployer-deploy-contract-args-options-

// 2_deploy.js

const Box = artifacts.require("Box");

module.exports = async function (deployer) {
  await deployer.deploy(Box, {overwrite: false});
  this.deployedBox = await Box.deployed();
  console.log(`Migrations deployed Box: ${this.deployedBox.address}`);
};

// Box.test.js

// test/Box.test.js
// Load dependencies
const { expect } = require('chai');

// Load compiled artifacts
const Box = artifacts.require('Box');

// Start test block
contract('Box', function () {
  beforeEach(async function () {
    // Deploy a new Box contract for each test
    this.deployedBox = await Box.deployed();
    console.log(`Deployed Box: ${this.deployedBox.address}`);
  });

  // Test case
  it('retrieve returns a value previously stored', async function () {
    // Store a value
    await this.deployedBox.store(42);

    // Test if the returned value is the same one
    // Note that we need to use strings to compare the 256 bit integers
    expect((await this.deployedBox.retrieve()).toString()).to.equal('42');
  });
});

Deploy

$ npx truffle migrate
...
Starting migrations...
======================
> Network name:    'development'
> Network id:      1605164995484
> Block gas limit: 6721975 (0x6691b7)


1_initial_migration.js
======================
...
2_deploy.js
===========

   Deploying 'Box'
   ---------------
   > transaction hash:    0x770ac33ee180217983cf64fc8f85dea37ec9e21fd0157abbcbc142b3ae9b6fb9
   > Blocks: 0            Seconds: 0
   > contract address:    0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6
   > block number:        21
   > block timestamp:     1605166801
   > account:             0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
   > balance:             99.96235378
   > gas used:            108291 (0x1a703)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00216582 ETH

Migrations deployed Box: 0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6

...

Testing

When running a test the existing deployment is used. 0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6

$ npx truffle test
Using network 'development'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.

Migrations deployed Box: 0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6


  Contract: Box
Deployed Box: 0xb09bCc172050fBd4562da8b229Cf3E45Dc3045A6
    ✓ retrieve returns a value previously stored (100ms)


  1 passing (163ms)

Testing with overwrite: true in migrations

A new contract is deployed by migrations when testing.

$ npx truffle test
Using network 'development'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.

Migrations deployed Box: 0x5017A545b09ab9a30499DE7F431DF0855bCb7275


  Contract: Box
Deployed Box: 0x5017A545b09ab9a30499DE7F431DF0855bCb7275
    ✓ retrieve returns a value previously stored (100ms)


  1 passing (171ms)

Thanks but I’m confused. I see no file in my project containing this deploy code you are referencing above. Is it supposed to be there or is this something I need to add?

1 Like

Hi @CryptoEatsTheWorld,

I assume that you have a Migrations script (in the migrations directory: https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations#migration-files) to deploy your contract?

It is this Migrations script that I was referring to that you could modify to add {overwrite: false}

Yes but my migrations files are already bare-bones, such as:

const CoinFlip = artifacts.require("CoinFlip");

module.exports = function (deployer) {
  deployer.deploy(CoinFlip);
};
1 Like

Hi @CryptoEatsTheWorld,

The default behaviour is to deploy a new contract every time you run your tests. If you don’t want this and you want to use the existing deployed contracts we need to use overwrite: false when calling deploy in our migrations scripts. (From the Truffle documentation: https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations#deployer-deploy-contract-args-options-)

So your migrations script would become:

const CoinFlip = artifacts.require("CoinFlip");

module.exports = function (deployer) {
  deployer.deploy(CoinFlip, {overwrite: false});
};

Thanks, that worked!

1 Like