11

So I'm using truffle and I notice that I seem to be able to deploy a contract's bytecode by calling deployer.deploy(MyContract);

But I've also seen people run:

myContract = await MyContract.new();

in a unit test without ever calling deployer.deploy().

Is my understanding correct? Do these bits of code do the same thing?

Thanks!

mark
  • 209
  • 1
  • 7

4 Answers4

5

They're both similar in that they deploy the contract. The difference is that .deploy() behaves like a singleton in that you can access the deployed instance with .deployed(). You typically use .new() in tests to avoid the possibility of any side-effects.

Here's an example:

Example.sol

pragma solidity ^0.4.23;

contract Example {
  uint256 public data;

  function set(uint256 _data) public {
    data = _data;
  }
}

Example.spec.js

const Example = artifacts.require('Example')

contract('Example', (accounts) => {
  let instance

  beforeEach('setup', async () => {
    instance = await Example.new()

    // second test will fail with `deployed()`
    //instance = await Example.deployed()
  })

  describe('test singleton', () => {
    it('should set data', async () => {
      assert.equal(await instance.data.call(), '0')
      const {receipt: {status}} = await instance.set(5)
      assert.equal(status, '0x01')
      assert.equal(await instance.data.call(), '5')
    })

    it('should not read previous data', async () => {
      // this will be `5` instead of `0` if using `deployed()`
      assert.equal(await instance.data.call(), '0')
    })
  })
})
Miguel Mota
  • 5,143
  • 29
  • 47
  • I've been using deployed in beforeEach and I had no inconsistency issues whatsoever. Could you elaborate on what are the fundamental differences, other than the singleton aspect? Or is that it? – Paul Razvan Berg Nov 20 '18 at 12:19
  • @PaulBerg that's the only difference that I know of. So you're saying that using deployed in beforeEach resets the contract? I just ran a quick test and that was not the case. See my updated answer – Miguel Mota Nov 20 '18 at 16:53
  • On a double check, no, it doesn't reset it! In my case, there's a mapping which is added a new object in beforeEach so I think that's why there are no side-effects. – Paul Razvan Berg Nov 20 '18 at 16:57
  • @PaulBerg makes sense – Miguel Mota Nov 20 '18 at 16:58
4

I think the difference is that new() simply deploys a new instance of the contract. But when a contract is deployed by deployer.deploy(), the new instance is saved in the migration for later use with MyContract.deployed(), etc.

sfmiller940
  • 498
  • 1
  • 3
  • 9
2

Both of the above functions are used to deploy the contract to the network.

deployer.deploy(myContract);

is used in our migration file.

We can deploy our own version to the network using the .new() function:

MetaCoin.new().then(function(instance) {

// do something

console.log(instance.address);

}).catch(function(err) {

// do something

});
Kashish Khullar
  • 1,563
  • 3
  • 14
  • 26
  • When the test suite starts, the contract deployment code in the /migrations folder is run automatically correct? This is important for testing side effects of your deployment code. – emkman May 15 '18 at 19:15
0

It seems reduntant because of the beforeEach and before, before already keeps it in memory as a singleton. beforeEach will create a new instance for each test. So confusing. Two ways of doing the same thing.

Bomberman
  • 39
  • 2
  • For some contracts it is useful to create and use multiple instances with .new(), something you can't do with .deploy(). – Ismael May 13 '21 at 03:43