defi-wonderland / smock

The Solidity mocking library
MIT License
319 stars 40 forks source link

bug: fakes at addresses cannot be reset #101

Open mds1 opened 2 years ago

mds1 commented 2 years ago

Below are two ways you can reproduce the bug

// Helper class used below
class SnapshotManager {
  snapshots: { [id: string]: string } = {};

  async take(): Promise<string> {
    const id = await this.takeSnapshot();
    this.snapshots[id] = id;
    return id;
  }

  async revert(id: string): Promise<void> {
    await this.revertSnapshot(this.snapshots[id]);
    this.snapshots[id] = await this.takeSnapshot();
  }

  private async takeSnapshot(): Promise<string> {
    return (await network.provider.request({
      method: 'evm_snapshot',
      params: [],
    })) as string;
  }

  private async revertSnapshot(id: string) {
    await network.provider.request({
      method: 'evm_revert',
      params: [id],
    });
  }
}

export const snapshot = new SnapshotManager();

// Test suite
describe('Tests', async () => {
  async function setupFixture() {
     // test setup....
  }

  // Setup, approach 1: waffle fixtures
  beforeEach(async () => {
    ({ /* destructure params */ } = await loadFixture(setupFixture));
  });

  // Setup, approach 2: directly snapshot/revert
  let id: string;
  before(async () => {
    ({ /* destructure params */ } = await setupFixture());
    id = await snapshot.take();
  });
  beforeEach(async () => {
    await snapshot.revert(id);
  });

  // Tests
  it('pre mock', async () => {
    // This tests works as expected
    console.log('pre mock', await contract.myFunction());
  });  

  it('mock', async () => {
    // Configure and test the mock
    const fakeContract = await smock.fake('Contract', { address });
    fakeContract.myFunction.reverts();
    try {
      console.log('mock', await fakeContract.myFunction());
    } catch (e) {
      console.log('reverted as expected');
    }  

    // Call the reset method
    fakeContract.myFunction.reset();
  });  

  it('post mock', async () => {
   // This call reverts because the mock was not actually reset, but it should no longer revert
   console.log('post mock', await contract.myFunction());
  });
});
smartcontracts commented 2 years ago

Sorry for the delay here, I'm trying to reproduce this locally using the code snippet you provided but having issues doing so. Do you have a repository you can share where I can reproduce this issue?

mds1 commented 2 years ago

Huh interesting, I believe @0xGorilla and I saw issues with pretty much that exact snippet, but yea this test suite is where I was originally seeing the issue. You can add a .only modifier to the top-level describe block in that file and you should still see the issue: https://github.com/ScopeLift/cozy-triggers/blob/fe276f7be5a706c34aa452927793acc3816ecdd9/test/Convex.test.ts#L272-L275

nkuba commented 2 years ago

I'm looking forward to a fix, as we're experiencing the same problem in our tests.