Ethers.js: Don't return the internal max block number

Created on 13 Nov 2020  路  3Comments  路  Source: ethers-io/ethers.js

There's this line in BaseProvider:

https://github.com/ethers-io/ethers.js/blob/e0b1d0e1e0280af860aaa593744a1a177f828397/packages/providers/src.ts/base-provider.ts#L614

that causes a problem in Hardhat (https://github.com/nomiclabs/hardhat/issues/1015)

The problem is that Hardhat Network supports resetting the network in runtime, making the block number go back to 0. But if you called getBlockNumber before, then the returned block number after the reset will be the max response before the reset instead of the correct value of 0.

I guess changing this could be considered a breaking change, so an alternative that would work for us would be having some public method that lets us reset or ignore this _maxInternalBlockNumber (or anything that helps us on fixing the problem on our side). Right now the only alternative I see is making something like

(provider as any)._maxInternalBlockNumber = -1024

before each request, which doesn't seem like a very good idea.

Most helpful comment

Yeah, keep in mind the ethers is not an interface to the JSON-RPC API. It happens to support talking over it, but the goal is to provide an interface to the Blockchain itself, not just what a node thinks.

This is important for the highly distributed nature of blockchains and making it easier for developers, otherwise every application would need all that code that lives in ethers as boilerplate they would need to add to get a consistent view.

And because of this, it is easier (i.e. possible) to piggy back on the Provider API to create things like the FallbackProvider which can operate across many backends, or even services like INFURA which also run many instances behind a single endpoint so that a slightly out-of-sync aspect does not cause applications to behave erratically.

All 3 comments

You could create a BaseProvider sub-class which stores an instance of a BaseProvider, which all calls to perform are just passed through. And on reset, create a new instance and replace it.

This would be a very specific Provider to Hardhat though, since it won鈥檛 support any of the consistency attempts made by ethers, but I鈥檓 guessing this is largely for testing? I鈥檓 not too familiar with Hardhat though...

You could create a BaseProvider sub-class which stores an instance of a BaseProvider, which all calls to perform are just passed through. And on reset, create a new instance and replace it.

Yes, I think we'll need to do that.

This would be a very specific Provider to Hardhat though, since it won鈥檛 support any of the consistency attempts made by ethers

That's probably right. My personal opinion is that ethers shouldn't do this: as a user I would expect that getBlockNumber just gives me the value returned by the node. But I guess your mind is made up on this :slightly_smiling_face:

but I鈥檓 guessing this is largely for testing?

Yes, that's right. I think there's a chance in like a bazillion that the mainnet reorgs and goes back some blocks, but it's probably a very unlikely scenario.

Yeah, keep in mind the ethers is not an interface to the JSON-RPC API. It happens to support talking over it, but the goal is to provide an interface to the Blockchain itself, not just what a node thinks.

This is important for the highly distributed nature of blockchains and making it easier for developers, otherwise every application would need all that code that lives in ethers as boilerplate they would need to add to get a consistent view.

And because of this, it is easier (i.e. possible) to piggy back on the Provider API to create things like the FallbackProvider which can operate across many backends, or even services like INFURA which also run many instances behind a single endpoint so that a slightly out-of-sync aspect does not cause applications to behave erratically.

Was this page helpful?
0 / 5 - 0 ratings