hardhat icon indicating copy to clipboard operation
hardhat copied to clipboard

Fixture composition is broken sometimes

Open krzysztof-cywinski opened this issue 3 years ago • 4 comments
trafficstars

Hi. I'm having a similar issue to #2980 despite using the proposed solution from https://github.com/NomicFoundation/hardhat/issues/2980#issuecomment-1208451537

Minimal steps to reproduce:

  1. npm init
  2. npm install hardhat
  3. create sample project and install its dependencies
  4. in test/Lock.ts add:
  async function testFixture() {
    const { lock, unlockTime, lockedAmount, owner, otherAccount } = await deployOneYearLockFixture();
    // do anything or nothing here. doesn't matter.
    return { lock, unlockTime, lockedAmount, owner, otherAccount };
  }

add two sets of test cases:

    describe("B", function () {
      it("B", async function () {
        const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
          testFixture
        );
      });
    });

    describe("A-B", function () {
      it("A", async function () {
        const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
          deployOneYearLockFixture
        );
      });

      it("B", async function () {
        const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
          testFixture
        );
      });
    });

the second B fails with:

FixtureSnapshotError: There was an error reverting the snapshot of the fixture.

This might be caused by using nested loadFixture calls in a test, for example by using multiple beforeEach calls. This is not supported yet.
      at loadFixture (/private/tmp/test-hardhat/node_modules/@nomicfoundation/hardhat-network-helpers/src/loadFixture.ts:47:15)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at async Context.<anonymous> (/private/tmp/test-hardhat/test/Lock.ts:147:59)
  
      Caused by: InvalidSnapshotError: Trying to restore an invalid snapshot.
          at Object.restore (/private/tmp/test-hardhat/node_modules/@nomicfoundation/hardhat-network-helpers/src/helpers/takeSnapshot.ts:33:15)
          at processTicksAndRejections (node:internal/process/task_queues:96:5)
          at async loadFixture (/private/tmp/test-hardhat/node_modules/@nomicfoundation/hardhat-network-helpers/src/loadFixture.ts:44:7)
          at async Context.<anonymous> (/private/tmp/test-hardhat/test/Lock.ts:147:59)

The pattern seems to be that when you have a fixture A and a fixture B that calls A internally:

function A() {
  // deploy
}

function B() {
  const { token } = await A();

  // make a TX

  return { ... }
}

Then when you make a test with fixture B, then with fixture A, and then with B again, the second B always fails. If you remove the A test from between the two B tests it works and both B tests pass. It's as if the call to fixture A after the call to fixture B broke fixture B somehow.

krzysztof-cywinski avatar Sep 09 '22 12:09 krzysztof-cywinski

This issue is also being tracked on Linear.

We use Linear to manage our development process, but we keep the conversations on Github.

LINEAR-ID: 58268639-24f7-40c7-9939-f8ed9267ef9f

github-actions[bot] avatar Sep 09 '22 12:09 github-actions[bot]

Thank you for using Hardhat.

Fixture composition is not currently supported. It seems that perhaps you misunderstood https://github.com/NomicFoundation/hardhat/issues/2980#issuecomment-1208451537 . The code snippet shown there is a sketch of a hypothetical usage, but support for it is not currently implemented.

feuGeneA avatar Sep 13 '22 22:09 feuGeneA

I may have indeed misunderstood. My understanding was that using loadFixture inside a fixture broke stuff, but directly calling another fixture function should be ok.

I re-read that thread and still think that @fvictorio suggested to use that pattern instead of using loadFixture inside a fixture function and that it should work.

It's also reiterated here: https://github.com/NomicFoundation/hardhat/issues/2980#issuecomment-1221421848

Can you please confirm that? Right now I have a lot of copypasta in my fixtures and if I need to change something in one of the earlier fixtures I need to change every dependent fixture as well. It's bad design.

krzysztof-cywinski avatar Sep 15 '22 12:09 krzysztof-cywinski

Agree, the reproduction shown seems like something that should work.

fvictorio avatar Sep 20 '22 18:09 fvictorio

I'm facing similar issue, in my case the structure is:

async function deployContract(param) {
 // deployment code
}

async function deployContractA() {
  return await deployContract("A");
}

async function deployContractB() {
  return await deployContract("B");
}

After a few times using one or another (A or B) it fails with the nested error code.

santiac89 avatar Oct 19 '22 10:10 santiac89

Facing the same issue with exact same setup. When loading fixtures in order B -> A -> B, second B load always fails.

ZumZoom avatar Nov 01 '22 15:11 ZumZoom

Came across this having the same setup facing the same issue.

itinance avatar Nov 01 '22 21:11 itinance

I believe this was fixed in v1.0.7.

Tentatively closing it, let me know if you are still running into something like that.

fvictorio avatar Dec 27 '22 12:12 fvictorio