Incorrectness regarding batching calls in "Getting a Quote" tutorial
NoUJoe opened this issue · 1 comments
This is really minor, I will admit. However incorrect, is incorrect. And it bugged me enough so here it is.
https://docs.uniswap.org/sdk/v3/guides/quoting
Doc states:
We use a batch Promise call. This approach queries state data concurrently, rather than sequentially, to avoid out of sync data that may be returned if sequential queries are executed over the span of two blocks:
In reference to this code:
const [token0, token1, fee] = await Promise.all([
poolContract.token0(),
poolContract.token1(),
poolContract.fee(),
])
This bit:
to avoid out of sync data that may be returned if sequential queries are executed over the span of two blocks
Implies that it's guaranteed that all 3 contract calls will be on the same block. While highly likely, like 99% of the time, that this will be the case, it's not guaranteed. Between me and the eth RPC server, a lot can happen which can result in the 3 calls not being called on the same block. 3 separate requests means each one can be received at a different point in time.
*Now im going to explain why it annoyed me this much, so stop reading if you don't want to hear the ramblings of a mad man.*
I'm pretty new to eth/web3/blockchain programming. But not new to programming and web development. So at the moment, I'm on a mad reading, learning and experimenting spree. I'm back and forth reading a bunch of stuff. Part of my plan involves needing to query the blockchain for data (duh, what else?) and then store said data and reference said data as and when needs be. This is important to the issue at hand! At the same time, there's a million and one other things I need to do.
Blah blah blah, I'm re-reading the "Getting a Quote" tutorial as it's somewhere I remember seeing the blockchain being queried, and at the time, my current question was "Do I use web3.js or ethers.js?". So I read the bit about getting data from the same block, and that sticks out to me because, like I just mentioned, part of my plan involves querying the blockchain for data and indexing it etc.x So, I'm looking at the example thinking, "Well, how does this gurantee it's the same block? 3 promises, 3 RPCs. I've done this a million times, am I missing something?". Maybe I am.
So, I go to ethers.js docs, start reading there, with the thought "maybe internally, ethers gets the latest block number, sends that with the request by default. Doesn't really make sense but maybe". But no, it works how you'd expect, by default it's just the latest block of the node. You have to specify if you want it at a specific block using:
overrides.blockTag - a block tag to simulate the execution at, which can be used for hypothetical historic analysis; note that many backends do not support this, or may require paid plans to access as the node database storage and processing requirements are much higher
Which is not what the tutorial is doing.
And like I've said, I know its an edge case, but we all know edge cases can and will happen. And if the data you're requesting is something like pool data, you really can't be having data across multiple blocks returned.
I'm sure there's a way to truly send a batch request to a node, I'm about to find out either way!
You are right, but as you said the probability of this happening is very low and the probability of the data changing is probably also below 1%.
You can specify a block number with ethers like this specified here.
If you are querying large amounts of data, it can make sense to use a multicall Contract, for example this. You can read more about that here.
Some Uniswap Contracts also integrate Multicall.