Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Before verifying the state, you need to fetch the event proof from Sepolia using the correct block number that has already been propagated to Hashi. This block number ensures that Hashi can verify the proof against the block header stored on Chiado.
Fetching the Proof
Use the following curl
command to fetch the account and storage proof for the USDC total supply on Optimism:
chainId: 11155111 (Sepolia).
txHash: The tx hash that emitted the Transfer event on Sepolia: .
logIndex: The log index for the event.
blockNumber: The block number on Sepolia, 7016999, which must have already been propagated to Chiado via Hashi for the proof to be valid.
This curl
command / script returns the event proof for the Transfer event on Sepolia, which will be used for verification on Chiado.
The Quick Start guide will walk you through two core use cases of Hashi: verifying storage proofs or event proofs against a block header and pushing messages across chains. We’ll start with reading foreign state via storage proofs, followed by pushing a message to another chain. Both examples will help you understand the core functionality of Hashi and how to implement it in your projects.
The code can be found in Hashi template. This repository serves as a template for developers to kickstart a Hashi project using Hardhat/Foundry.
The first step is to understand what we’re trying to do:
You want to check if a specific Transfer event has been emitted from an ERC20 contract on Sepolia from Chiado.
We’ll do this by using HashiProver, which will verify the event from an ERC20 contract on Sepolia.
The proof will be verified using the latest block header that was relayed to Hashi from Sepolia to Chiado.
Here’s what we need to accomplish:
Fetch the event proof for Transfer event from Sepolia.
Deploy a contract on Chiado that will verify the event proof using HashiProver.
Submit the proof to this contract to validate the event on Sepolia.
In this example, you will verify the Transfer event of an ERC20 contract on Sepolia from Chiado using an event proof. The proof will be fetched via an API call and fed to a contract deployed on Chiado. The contract will use the HashiProver helper library to validate the proof against the last reported block header stored in Hashi.
In this example, we’ll send a message from a contract on Sepolia to another contract on Chiado, using Hashi to relay and execute the message. The callback will be triggered and validated on Chiado using the provided onMessage
function.
The first step is to understand what we’re trying to do:
You want to check the total supply of USDC on Optimism from Gnosis Chain.
We’ll do this by using HashiProver, which will verify the state of a specific storage slot (holding the USDC total supply) on Optimism.
The proof will be verified using the latest block header that was relayed to Hashi from Optimism to Gnosis Chain.
Here’s what we need to accomplish:
Fetch the storage proof for the USDC total supply from Optimism.
Deploy a contract on Gnosis Chain that will verify the storage proof using HashiProver.
Submit the proof to this contract to validate the total supply on Optimism.
Once you’ve fetched the proof, you can now verify it using a contract on Gnosis Chain. The contract will use the HashiProver helper library to check the proof against the block header stored on Gnosis Chain.
Deploying the Verification Contract on Gnosis Chain
Here is the contract that you will deploy on Gnosis Chain to read and verify the USDC total supply on Optimism:
Explanation:
This contract uses HashiProver to verify the storage proof fetched earlier from Optimism.
It checks that the proof is from Optimism (chain ID 10), and that the USDC contract address and storage key match the expected values.
The verifyForeignStorage
function validates the proof against the block header stored on Gnosis Chain, which was relayed from Optimism.
If the proof is valid, the contract emits the total supply of USDC on Optimism.
Submitting the Proof
Once the contract is deployed on Gnosis Chain, you can submit the proof fetched from the API using the following command:
This will trigger the contract to verify the proof using the block header stored in Hashi from Optimism. If the proof is valid, the total supply of USDC will be emitted.
Once you’ve fetched the proof, you can now verify it using a contract on Chiado. The contract will use the HashiProver helper library to check the proof against the block header stored on Chiado.
Deploying the Verification Contract on Chiado
Here is the contract that you will deploy on Chiado to read and verify the Transfer event on Sepolia:
For quick start, we've deployed HashiProver & ShoyuBashi on a list of networks that you can call from your Prover contract (check #shoyubashi-and-hashi-prover). If you wish to configure your own oracle sets for your Hashi Prover, simply deploy a new ShoyuBashi contract, inherit Hashi Prover contract and configure your oracle sets in the ShoyuBashi contract.
In this example, pass the Hashi Prover contract on Chiado, ERC20Contract address on Sepolia that the Transfer event is emitted from, and chain ID of the ERC20Contract (Sepolia: 11155111)
Explanation:
This contract uses HashiProver to verify the event proof fetched earlier from Sepolia.
It checks that the proof is from Sepolia (chain ID 11155111), and rlpEncodedEvent returns from HashiProver.verifyForeignEvent matches the expectedRlpEncodedEvent that we passed as the function argument. To create the expectedRlpEncodedEvent, check out the helper script from Hashi-template.
The verifyForeignEvent
function validates the event proof against the block header stored on Chiado, which was relayed from Sepolia.
If the proof is valid, the contract emits the TransferEventVerified
event. You may defie your own logic after the proof has been verified.
In this example, you will verify the total supply of USDC on Optimism from Gnosis Chain using a storage proof. The proof will be fetched via an API call and fed to a contract deployed on Gnosis Chain. The contract will use the HashiProver helper library to validate the proof against the last reported block header stored in Hashi.
Now, we’ll write the callback function on Chiado using the onMessage
implementation you provided. This contract will handle the message sent from Sepolia.
Explanation:
The onMessage
function implements the callback, which is triggered when the Yaru contract on Chiado relays the message.
The function checks that the Yaru contract on Chiado is the sender, that the chainId, sender address, and threshold match what was expected, and that the list of adapters matches the expected hash.
After the validations pass, the message is decoded and stored in the contract.
Deployment:
Deploy this contract on Chiado. Ensure that the values like SOURCE_SENDER_ADDRESS (Sepolia sender contract), EXPECTED_THRESHOLD, and ADAPTERS are correctly configured.
Before verifying the state, you need to fetch the storage proof from Optimism using the correct block number that has already been propagated to Hashi. This block number ensures that Hashi can verify the proof against the block header stored on Gnosis Chain.
Fetching the Proof
Use the following curl
command or javascript script to fetch the account and storage proof for the USDC total supply on Optimism:
chainId: 10 (Optimism).
address: The address of the USDC contract on Optimism: 0x0b2c639c533813f4aa9d7837caf62653d097ff85
.
storageKeys: The storage key for the USDC total supply: 0xb
.
blockNumber: The block number on Optimism, 126086800, which must have already been propagated to Gnosis Chain via Hashi for the proof to be valid.
This curl
command returns the account and storage proof for the USDC total supply, which will be used for verification on Gnosis Chain.
Here’s how you write a contract on Sepolia that dispatches a message using Hashi’s Yaho contract. This message will be relayed to Chiado and trigger the callback.
Explanation:
The contract interacts with the Yaho contract on Sepolia to dispatch a message to Chiado using dispatchMessageToAdapters
.
The sendMessageToChiado
function takes the target chain ID(10200 for Chiado), target address (ChiadoReceiver contract on Chiado), and the message to be sent.
The reporters, adapters, and threshold are passed into the Yaho contract for cross-chain message validation and relaying.
Deployment:
Deploy this contract on Sepolia, passing the reporters, adapters, and threshold into the constructor.
Threshold
must equal to expectedThreshold
in Receiver contract.
Yaru address with respect to the source chain can be found in
A list of adapters on the target chain can be found in
A list of reporters and adapters contract can be found in:
Yaho contract address can be found in
Here’s what happens after you send the message:
Message Dispatch on Sepolia:
When sendMessageToChiado
is called on the SepoliaSender contract, the message is dispatched through Yaho on Sepolia.
The message is sent with the targetChainId, threshold, reporters, and adapters, and the data (in this case, the message string).
Oracles and Relaying:
Hashi’s oracles pick up the message and relay it to Chiado.
The oracles validate the message and check the block headers for consensus.
Message Receipt and Callback on Chiado:
On Chiado, the Yaru contract receives the message and triggers the onMessage
function on the ChiadoReceiver contract.
The callback validates the message by ensuring that the message is from the expected Yaru contract, the source chain, and the correct sender.
After validation, the message is decoded and stored in the contract.
You deploy SepoliaSender on Sepolia and configure it with the appropriate Yaho contract and oracle parameters.
You deploy ChiadoReceiver on Chiado to handle the incoming message and validate it against Hashi’s oracle system.
When you call sendMessageToChiado
from SepoliaSender, the message is dispatched to Chiado, where the callback function processes it and updates the state.