PatrickAlphaC / hardhat-smartcontract-lottery-fcc

MIT License
118 stars 183 forks source link

Lesson 9: unittesting checkUpkeep.not_enough_time_passed failing #95

Open pacmac0 opened 2 years ago

pacmac0 commented 2 years ago

The "returns false if not enough time has passed" test fails, because upkeepNeeded returns true for time changes to close to the chosen interval. With

await network.provider.send("evm_increaseTime", [interval - 3])

it works. It also works if I use [interval - 3] and comment out

await network.provider.request({ method: "evm_mine", params: [] })

Any ideas on how this might be caused? Could it maybe be that it takes too long locally, so that 2 blocks are mined and the state already changes before assertion?

it("returns false if not enough time has passed", async () => {
            await raffle.enterRaffle({ value: raffleEntranceFee })
            await network.provider.send("evm_increaseTime", [interval - 1])
            await network.provider.request({ method: "evm_mine", params: [] })
            const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x")
            //console.log(upkeepNeeded)
            assert(!upkeepNeeded)
        })
jksgfsdfd commented 2 years ago

You could check the mined blocks to figure out what is going on. In my case it works till [interval - 2]. When I checked the mined blocks I could see that the raffle contract was deployed in Block 3 and there was one another Block already mined before the evm_increaseTime method is called.Hence it is expected to pass the test when time is increased by interval-1.

pacmac0 commented 2 years ago

You could check the mined blocks to figure out what is going on. In my case it works till [interval - 2]. When I checked the mined blocks I could see that the raffle contract was deployed in Block 3 and there was one another Block already mined before the evm_increaseTime method is called.Hence it is expected to pass the test when time is increased by interval-1.

Thank you for your explanation, I will check for that and try to investigate the blocks.

NindoK commented 1 year ago

Anyone has more info on this? I'd like to understand better why it doesn't work on the edge case. Making it pass with interval - 2 seems like a quick fix. In the video it works with -1, and I'd like to achieve the same thing. I've been trying to mess with things, but haven't come up with a solution yet. If anyone is able to clarify this to me, I'd greatly appreciate it!

jksgfsdfd commented 1 year ago

Have you checked the mined blocks?

NindoK commented 1 year ago

Yes

Before mining:

  hash: '0xd17e0e029e7fdb7fa913e06688e9341eb01603767fabf996bd15c8a89cb1ed05',
  parentHash: '0x97784d89777349cd4c0c0782db14904727c7f3694ca668887e9ddc8dcb7d51f9',
  number: 6,
  timestamp: 1669575104,
  nonce: '0x0000000000000000',
  difficulty: 0,
  gasLimit: BigNumber { _hex: '0x01c9c380', _isBigNumber: true },
  gasUsed: BigNumber { _hex: '0x010dd3', _isBigNumber: true },
  miner: '0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E',
  extraData: '0x',
  transactions: [
    '0xe5f0e59e92c1aba324730f04d34022e0465a2cc72d9a5d3a42264f7eabf38442'
  ],
  baseFeePerGas: BigNumber { _hex: '0x1bc28693', _isBigNumber: true },
  _difficulty: BigNumber { _hex: '0x00', _isBigNumber: true }
}

After mining

{
  hash: '0x95bc186d43101c441e8cd9262cae5fa2e6300ec27ab4fee0960b6fab0caa58b6',
  parentHash: '0xd17e0e029e7fdb7fa913e06688e9341eb01603767fabf996bd15c8a89cb1ed05',
  number: 7,
  timestamp: 1669575133,
  nonce: '0x0000000000000000',
  difficulty: 0,
  gasLimit: BigNumber { _hex: '0x01c9c380', _isBigNumber: true },
  gasUsed: BigNumber { _hex: '0x00', _isBigNumber: true },
  miner: '0xC014BA5EC014ba5ec014Ba5EC014ba5Ec014bA5E',
  extraData: '0x',
  transactions: [],
  baseFeePerGas: BigNumber { _hex: '0x184e4cf9', _isBigNumber: true },
  _difficulty: BigNumber { _hex: '0x00', _isBigNumber: true }
}

I put await network.provider.send("evm_increaseTime", [interval.toNumber() - 1])  and in fact the timestamp coincide... This should be false when we evaluate:

bool timePassed = ((block.timestamp - s_lastTimeStamp) > i_interval);

That's why I'm not understanding... Am I missing something?