On-chain requests

Requesting information from the Succinct on-chain
In the Getting Started Example, we detailed how to write a simple voting contract on L2 that requests a state query from Ethereum mainnet about a user's NFT balance and gates voting with the result. Here we detail the lifecycle of an on-chain request to the Succinct State Query protocol.
Below is a diagram showing the lifecycle of an L2Voting contract that requests L1 data from the Succinct state query protocol to gate voting by an L1 NFT balance, and then processes the result with a callback function.
Lifecycle of an on-chain request to the Succinct state query protocol
A visual representation of the lifecycle of an on-chain request to the Succinct state query protocol.

Making an on-chain request

We walk through the lifecycle in the diagram above step by step. Refer to the L2 voting contract in Getting Started Example for the contract that we are referencing throughout.
(1) A user calls vote which (2) calls the StateQueryGateway contract with a request for information about the user's NFT balance on L1, as the user should only be allowed to vote on L2 if they have at least 1 NFT on L1. Below is what example code for this logic might look like:
function vote(uint256 option) external {
require(option == 1 || option == 2, "Invalid option");
if (addrToVote[msg.sender] != 0) {
revert("Cannot vote twice");
StateQuery memory stateQuery = StateQuery({
chainId: 1,
blockNumber: SNAPSHOT_BLOCK,
fromAddress: address(0),
toAddress: ADDRESS_ERC721,
// Below we encode the calldata for requesting the user's balance
toCalldata: abi.encodeWithSelector(IERC721.balanceOf.selector, msg.sender)
L2VotingOnChainRequest.continueVote.selector, // Which function to call after async call is done
abi.encode(option, msg.sender) // What other data to pass to the callback
(3) In the StateQueryGateway, each request emits an event. The Succinct sequencer watches for events from the gateway and constructs batches of requests. The attestors poll the sequencer for these batches and process each request. In particular, for each request, they use the eth_call RPC method with the provided request parameters to get the result of the query for the desired chain and sign the request and the result. Then each attestors sends their signed attestation to an entity known as the Succinct sequencer.
(4) The Succinct sequencer is responsible for receiving attestations and aggregating them. Once enough attestations are gathered for a particular request (if > 2/3 of the attestors have signed off on it), the sequencer will relay the attestations and other necessary data to the StateQueryGateway contract.
(5) The StateQueryGateway contract verifies the attestations and in particular checks that > 2/3 of attestors have signed off on a request and the same result. If true, then the StateQueryGateway calls the callback specified in the request with 2 arguments: the result (as bytes) and also callbackExtraData.
In the voting example, the callback specified in the request is for continueVote which will handle the _requestResult and _callbackExtraData and only add the user's vote to the addrToVote mapping if the user's balance is >=1. Note that we also must check in the callback function that the call is coming from the StateQueryGateway.
function continueVote(bytes memory _requestResult, bytes memory _callbackExtraData) external {
require(msg.sender == STATE_QUERY_GATEWAY);
uint256 balance = abi.decode(_requestResult, (uint256));
(uint256 option, address msgSender) = abi.decode(_callbackExtraData, (uint256, address));
if (balance >= 1) {
addrToVote[msgSender] = option;
Batch Requests
Our state query protocol has a way of requesting multiple state queries and receiving all results in 1 callback. The request API looks very similar, to learn more read about it here: Batch Requests.
Contract Interfaces
The contract interfaces for interacting with the StateQueryGateway can be found in Contract Interfaces.
Contract References
The implementations for contracts mentioned above can be found at the links below:
  • StateQueryGateway: open-source coming soon!
  • L2Voting: open-source coming soon!