Getting Started
💡There is a basic demo interacting with the QueryDemo contract hosted at https://wormholelabs-xyz.github.io/example-queries-demo/
To get started, we will look at a simple eth_call
request to get the total supply of WETH on Ethereum.
RPC Basics
Before we dig into anything Queries specific, let’s look at how to make an eth_call against a public Ethereum RPC. Before we can make a request, we need some information about the contract we want to call.
to: the contract to call
data: the method identifier and ABI-encoded parameters
web3.eth.abi.encodeFunctionSignature("totalSupply()")
→0x18160ddd
block id: the block number, hash, or tag, like
latest
,safe
, orfinalized
Converting that result from hex gets us 3172615244782286193073777
. You can compare your result to the Read Contract tab in Etherscan. Your result will be different as WETH is minted/burned over time.
Construct a Query
For this part, we will use the Wormhole Query SDK along with axios for our RPC requests.
In order to make an EthCallQueryRequest
, we need a specific block number or hash as well as the call data to request.
To get the latest block, we can request it from a public node using eth_getBlockByNumber
.
Then construct the call data
Finally, put it all together in a QueryRequest
This request consists of one PerChainQueryRequest
, which is an EthCallQueryRequest
to Ethereum. You can log this out as JSON to see the structure.
Mock a Query
For easier testing, the Query SDK provides a QueryProxyMock
which will perform the request and sign the result with the devnet guardian key. The mock
call returns the same format as the Query Proxy.
This response is suited for on-chain use, but the SDK also includes a parser so we can read the results in the client.
Testing this all together might look like the following
Fork Testing
It is common to test against a local fork of mainnet with something like
In order for mock requests to verify against the mainnet Core bridge contract, we need to replace the current guardian set with the single devnet key used by the mock.
Here's an example for Ethereum mainnet, where the -a
parameter is the Core bridge address on that chain.
If you are using EthCallWithFinality
, you will need to mine additional blocks (32, on Anvil) after the latest transaction in order for it to become finalized. Anvil supports auto-mining with the -b
flag if you want to test code that waits naturally for the chain to advance. For integration tests, you may want to simply anvil_mine
with 0x20
.
Make a QueryRequest
A testnet Query Proxy is available at https://testnet.ccq.vaa.dev/v1/query
A mainnet Query Proxy is available at https://api.wormholelabs.xyz/v1/query
Verify a QueryResponse On-Chain
A QueryResponse abstract contract is provided to assist with verifying query responses. Simply forge install wormhole-foundation/wormhole-solidity-sdk
. Broadly, using a query response on-chain comes down to 3 steps.
Parse and verify the query response.
The
parseAndVerifyQueryResponse
handles verifying the Guardian signatures against the current guardian set stored in the Core bridge contract.
Validate the request details. This may be different for every integrator depending on their use case, but generally checks the following.
Is the request against the expected chain?
Is the request of the expected type? The
parseEthCall*
helpers perform this check when parsing.Is the resulting block number and time expected? Some consumers might require that a block number be higher than the last, or the block time be within the last 5 minutes.
validateBlockNum
andvalidateBlockTime
can help with the checks.Is the request for the expected contract and function signature? The
validateMultipleEthCallData
can help with non-parameter-dependent cases.Is the result of the expected length for the expected result type?
abi.decode
the result.
See the QueryDemo contract for an example and read the docstrings of the above methods for detailed usage instructions.
Submit a QueryResponse On-Chain
The QueryProxyQueryResponse
result requires a slight tweak when submitting to the contract to match the format of function parseAndVerifyQueryResponse(bytes memory response, IWormhole.Signature[] memory signatures)
. A helper function, signaturesToEvmStruct
, is provided in the SDK for this.
For example, submitting the transaction to the demo contract:
Last updated