Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Hashi is an EVM Hash Oracle Aggregator, designed to facilitate a principled approach to cross-chain bridge security.
The primary insight being that the vast majority of bridge-related security incidents could have had minimal impact if the systems relying on them had built in some redundancy. In other words, it's much more secure to require messages be validated by multiple independent mechanisms, rather than by just one.
Hashi aims to create “additive security” to cross-chain messages by aggregating block headers from different sources. A block header will be considered valid only when a number of block sources (oracles) above a certain threshold report the same result. Hashi is the first step towards a principled approached to bridges and will play a key role in the Gnosis Chain interoperability roadmap.
Apart from block header, Hashi also provides arbitrary message relaying option. Check out Message Dispatching with Yaho and Yaru for more details.
Oracles consists of the bridge solutions available in the market, such as AMB, Telepathy, Dendreth, etc. To provide an universal interface for Hashi, an adapter contract is designed specifically for each oracle. Some of the oracles require header reporter to report block header in certain slot.
Existing oracle adapters:
Cross Chain Alliance: https://github.com/crosschain-alliance
Repository: github.com/gnosis/hashi
Intro discussion: ethresear.ch/t/hashi-a-principled-approach-to-bridges
panDA is an abstraction layer for Data Availability (DA) layers, built with additive security in mind. By using it, Layer 2 solutions and rollup ecosystems can scale efficiently and securely, leveraging different DAs as if they were one.
The cross-chain ecosystem has suffered greatly due to its reliance on non-adaptable solutions that were built without redundancy in mind and with lock-in to specific vendors - panDA helps addressing that from the start, ultimately enabling a future proof L2 ecosystem.
Flexibility: panDA is created to provide seamless integration with different DA layers, and future-proofing capabilities, effectively eliminating the constraints of vendor lock-ins. This flexibility ensures that Layer 2 solutions and rollapps can adapt to the evolving landscape of Data Availability without being locked to specific platforms. If a new innovative DA gets invented your L2 can use it by simply changing the panDA configuration, with no additional changes required.
Redundancy: panDA offers redundancy, giving the option to replicate data across multiple DA layers. This strategy mitigates the liveness risks associated with individual DAs, ensuring uninterrupted access and reliability when it matter the most.
Additive Security: Drawing inspiration from the Hashi approach of additive security, panDA provides a robust framework for verifying data commitments across different chains. It is much safer than traditional solution as a bridging stack for propagating your state across chains.
Efficiency: The platform allows to easily swap between DA layers, letting users modifying their panDA configuration in response to changing network conditions. This dynamic adaptability optimizes resource utilization, for example in case of network congestion.
panDA consists of three main components:
the Dispersion Service which allows for the submission of the same data on different DA layers (namely Ethereum, Gnosis, Avail DA and Celestia)
the Inclusion Proofs Collection Service which generates for specific blockchains different types of proofs that demonstrate the submission of data on the selected DA layers
the library which allows for the verification of the proofs; for example, we have built Inclusion Proof Adapters (IPAs) for the verification of different proof types on-chain.
We have used Avail DA as one of the supported DA layers and its bridge to create the IPA for verifying on Ethereum the submission of data on Avail DA.
We have used also Celestia as one of the supported DA layers, and Blobstream X to create the IPA for verifying on Ethereum the submission of data on Celestia.
We have also used the POINT_EVALUATION_PRECOMPILE_ADDRESS (introduced by EIP-4844) for the verification of KZG Proofs, which demonstrates the data availability of a blob.
Finally, we have used Axiom for the verification on different chains of ZK proofs of data availability on Ethereum.
Source code: https://github.com/crosschain-alliance/panDA
Hashi integration of Hyperlane ISM
Hyperlane Interchain Security Module (ISM) is part of the modular security provided by Hyperlane. Users can define their own ISM for their security preferences.
This is a PoC of Hashi as Hyperlane ISM. With Hashi as ISM, the security is guaranteed by the Hashi Adapters.
Deployment of contracts
HashiRegistry: A registry for Hashi Adapters pair and their corresponding fee.
Hashi Hook: A hook contract deployed on source chain.
Hashi ISM: An ISM contract deployed on destination chain.
User calls Mailbox.quoteDispatch()
to get the fee and call Mailbox.dispatch()
with provided fee.
Mailbox calls HashiHook._postDispatch()
to invoke cross-chain message passing.
Hashi calls source chain message relays to pass the message hash w.r.t message Id and the message hash is stored on destination chain adapters.
HashiISM owner calls HashiISM.verifyMessageHash()
with matching Hashi Message Id and Hyperlane Message Id, source and destination domain as parameters.
User calls Mailbox.process()
to check the execute the message.
Mailbox calls HashiISM.verify()
to check whether the message has been verified by Hashi ISM.
Hashi ISM source code: https://github.com/crosschain-alliance/hashi-ism/tree/main
Source Chain: Ethereum Destination Chain: Gnosis Chain, Polygon, BNB Chain, Optimism, Arbitrum, Avalanche
Avalanche
Source Chain: Goerli Destination Chain: Chiado, Gnosis Chain, Optimism Goerli, BSC Testnet.
For the current configuration, we validate a Goerli block hash with 4 oracles, every ~15 mins.
The 4 oracles includes Telepathy Light Client, Dendreth Light Client, Gnosis AMB, and Sygma. Threshold in ShoyuBashi is set to 2.
How to use it? Call getThresholdHash(domain, blockNo) in ShoyuBashi. By using domain=5 and blockNo a blockNumber that has been reported by the oracles, you get back the blockHash if at least 2 of the oracles have reported the same hash.
For the current deployment, only AMB and Telepathy oracles are supported.
Goerli
Optimism Goerli
BSC Testnet
Deploy xERC20 Contracts: Start by deploying xERC20 contracts as outlined in the xERC20 documentation.
Obtain xERC20 Token: For a specific token, acquire the corresponding xERC20 token on the native chain by locking the native token in the xERC20 Lockbox.
Use SJRouter for Cross-Chain Actions: Leverage SJRouter contracts and their xTransfer
function for cross-chain minting/burning. This function burns the chosen amount of tokens and uses Hashi to send a cross-chain message containing all necessary parameters for calculating the xERC20 token address on the destination chain.
Message Dispatch Through Hashi: Hashi dispatches the message to all the selected adapters.
Message Processing by Bridges: Each bridge involved processes the message and stores the message hash in their respective adapters.
Execution of Hashi Message: After all bridges have processed the message, Hashi executes the message.
Final Minting Process: Once the message is executed, the host SJRouter trustlessly calculates the xERC20 token address and proceeds to mint the designated quantity of xERC20 tokens. Additionally, there's a provision where a Market Maker might offer an advance on the tokens to the user, for a fee. This service is particularly useful for users who prefer immediate token access, bypassing the waiting period required for all bridges to process the message.
By using Axiom, we decreased by approximately at least 2x the cost to execute a cross chain Safe operation.
This is a PoC of how Axiom can be used on top of our original Safe with Hashi project. Leveraging Axiom's V2 query and ZK verification on chain, any transaction initiated from the Main Safe can be executed trustlessly on the Secondary Safe.
Begin by deploying two Safes - the Main Safe and the Secondary Safe. Attach a module called AxiomControllerModule
to the Secondary Safe.
Users wishing to execute a cross-chain transaction should call execTransaction
on the Peripheral
contract through the MainSafe which will emit Operation
event and listened by Off chain relayer. The data
field in the event consists of the calldata to be executed by Secondary Safe.
Relayer call sendQuery
on AxiomV2Query contract, to prove that the event is emitted on source chain.
AxiomV2Query contract emits QueryInitiatedOnChain
event and triggers Axiom Prover to generate the ZK proof with respect to the query.
Once the ZK proof is generated, Axiom will call fulfillQuery
on AxiomV2Query contract, which will eventually call AxiomControllerModule to execute the transaction on behalf of Secondary Safe using execTransactionFromModule.
Hashi integration of Layer Zero v2 DVN
Layer Zero v2 DVN provides customizable security stacks for developer to choose from. Developers can specify one or more DVNs for their Oapp according to their security preference. Learn how to configure DVN for your Oapp here.
Hashi, which aims to create "additive security" for cross-chain message bridging enable developers to choose which Hashi Adapters to use for their dapp's security preference. Message hash is relayed through Hashi Message Relay and stored cross-chain in Hashi Adapter contract.
This is a PoC of Hashi integration of LayerZero v2 DVN.
This is the end to end workflow of how a Hashi DVN Adapter will be used by an Oapp
In order to use Hashi DVN for your Oapp, Oapp developer need to register the DVN in the source endpoint's config.
Oapp calls Endpoint.setConfig
to add HashiDVN as one of the DVN. url
Underlying Hashi DVN is a combination of Hashi Message Relay and it's corresponding adapter. The addresses and fee is registered in HashiRegistry.sol.
set eid to chainID mapping
set Hashi Registry for hashi adapters addresses and fee.
Source chain workflow
Sender calls LzEndpoint (or Oapp that will call LzEndpoint eventually).
LzEndpoint calls SendLib (default to ULN302)
SendLib calls HashiDVNAdapter assignJob
and pay HashiDVN fee (fee is fetched from HashiRegistry. getFee
)
HashiDVNAdapter calls yaho.dispatchMessageToAdapters
to relay the messageHash.
Hashi DVN will listen to the following events and call HashiDVNAdapter.sol on destination chain.
Listen to PacketSent
(to get payload) and DVNFeedPaid
event
Listen to MessageDispatched
(for messageId) event
To verify the message, Hashi DVN owner will call HashiDVNAdapter.verifyMessageHash()
, with messageId
from Yaho contract, and payload
of the corresponding LayerZero packet. There are two steps of verification:
1st verification: If the messageHash stored in Hashi Adapters are matched.
2nd verification: If the messageHash from 1st verification matches the corresponding LayerZero's payloadHash.
Destination chain workflow
call HashiDVNAdapter.verifyMessageHash(messageId, payload)
HashiDVNAdapterl calls Hashi.getHash
to check if all adapters agree on the same hash for 1st verification.
If true, check for 2nd verificaiton and calls ReceiveLib.verify
to set verify mapping to true.
Executor calls commitAndExecute
message
You may call a block header reporter to report and store the block hash, if the block you are looking for is not yet stored by the adapter.
Navigate to or contract.
Select Contract and Write Contract.
Connect your wallet and switch to the correct network.
Click reportHeaders and input blockNumbers (uint256 []), and gas.
For relaying arbitrary message between Ethereum/Goerli and Gnosis Chain, several contracts need to be deployed on top of the : Yaho, Yaru, AMB Message Relay, AMB Adapter, and Hashi. The addresses from this article are for Goerli <-> Gnosis Chain.
For Goerli->Gnosis Direction:
Deploy on Goerli, and on Gnosis Chain, with constructor _hashi: Hashi address on Gnosis Chain, _yaho: Yaho address on Goerli, _chainId: 5
.
Optional: Deploy for Safe that will be called by Yaru, i.e. Safe on Gnosis Chain.
Deploy on Goerli, with constructor _amb: AMB address on Goerli, _yaho: Yaho address on Goerli
.
Deploy on Gnosis Chain, with constructor _amb: AMB address on Gnosis Chain, _reporter: AMB Message Relay on Goerli, _chainId: bytes32(5)
.
In the current deployment,
gas
is added as a parameter indispatchMessagesToAdapters()
to justify the . It is not added into the official hashi code at the moment as . Please be aware that these contracts might be changed anytime.
User calls Yaho.dispatchMessagesToAdapters
.
Yaho calls AMB Message Relay relayMessages
which will eventually calls storeHashes
from AMB Adapter on Gnosis Chain.
AMB Message Relay calls AMB requireToPassMessage
, and the message will be relayed to AMB on Gnosis Chain.
Once the AMB Adapter storeHashes
is called, MessageDispatched
event will be emitted and user need messageId
data from the event.
User calls Yaru.executeMessages
with messageId
and message
as parameters.
Create function calldata for the contract you want to call on Gnosis Chain.
Optional: Create transaction calldata for Hashi Module.
Create message with format below: With Safe:
Without Safe:
Call Yaho.dispatchMessagesToAdapters([message],[AMB_Message_Relay_Address],[AMB_Adapter_Address])
using Safe or EOA.
After the message is relayed to Gnosis Chain by AMB bridge, you can proceed to claim your transaction. Make sure that your message is stored by checking if the AMB Adapter contract emits HashStored
event with the correct message Id
.
Call Yaru.executeMessages([message],[messageId],[Safe_from_Goerli or EOA from Goerli that calls Yaho],[AMB_Adapter_Address on Gnosis Chain])
For a successful message execution to happen, the contract specified as message recipient on the destination chain must implement a hook to process correctly the message.data
. The hook must revert unless the msg.sender
matches the expected Yaru
contract, Yaru.sender()
matches the expected sender, and Yaru.adapters()
matches the desired set of oracles that must have agreed on the reported hash.
Yaho calls AMB Message Relay relayMessages
which will eventually calls storeHashes
from AMB Adapter on Gnosis Chain.
AMB Message Relay calls AMB requireToPassMessage
, and UserRequestsForSignature
event will be emitted.
Safe Crosschain is a mechanism crafted to empower users with the ability to control a Safe across different blockchains using Hashi. The idea is to have a main Safe that controls secondary Safes deployed abroad using storage proofs verification against a block header propagated using Hashi.
Begin by deploying two Safes - the main Safe and the Secondary Safe. Attach a module called ControllerModule
to the Secondary Safe.
Users wishing to execute a cross-chain transaction should call execTransaction
on the Peripheral
Safe through the MainSafe which just writes in storage a commitment corresponding to the used function parameters.
After the transaction is included in a block, a relayer propagates the corresponding block header to the chain where the Secondary Safe is deployed.
Once all bridges have stored the block header in their corresponding adapters, the user can call execTransaction
on the ControllerModule
, providing the storage proof. The ControllerModule
verifies the proof against the block header propagated with Hashi, and subsequently calls execTransaction
on the Secondary Safe using execTransactionFromModule
.
What's new in Hashi v2.0?
Hashi v2.0 introduces several enhancements focusing on increased security and improved developer experience. Below are the detailed changes:
1. Enhanced Message Structure
Hashi v2.0 Message Structure
The new Message
struct in v2.0 has been expanded to include more specific details, making each message request more comprehensive, customizable, and secure.
nonce: A unique number for each transaction to prevent replay attacks and ensure uniqueness.
targetChainId: The chain ID of the target chain (previously toChainId).
threshold: The minimum number of reporters needed to validate the message.
sender: The address initiating the message.
receiver: The address receiving the message.
data: The message data in bytes.
IReporter[] reporters: An array of reporters that relay the message hash.
IAdapter[] adapters: An array of adapters that handle message hash storage.
The new structure ensures that messages are not only unique but can also be verified by multiple independent reporters, enhancing security.
2. Improved Message Hash Calculation
In v2.0, the calculation has been simplified to improve efficiency and reduce potential errors. The hash is now computed by ABI encoding and hashing the entire Message
struct.
3. Renaming for Clarity
OracleAdapters to Adapters:
The term "OracleAdapters" has been renamed to "Adapters" for better readability and understanding.
4. Unified Reporter Role
Adapter: A role that store hashes from reporter on the destination chain. Internal function _storeHash
is called eventually to store hashes from reporters.
Hashi v2.0 focuses on enhancing security and developer experience by:
Introducing a more detailed and secure Message
struct.
Simplifying message hash calculation.
Renaming components for clarity.
Unifying roles to streamline operations and reduce complexity.
Reference
Integrating a new adapter into Hashi enhances the security of the overall architecture.
There are two contracts need to be created:
Header Reporter contract on source chain
Adapter contract on destination chain
Header reporter contract will be called by user or bot to pass block header of certain block(s) from source chain.
Create a public function called reportHeaders
.
In the reportHeaders
function, define the bridging logic and make sure three requirements are met:
i. Call storeBlockHeaders()
from HeaderStorage contract
ii. Bridge block headers returned from the above step with encoded data that will call the function to store block headers in adapter contract on destination chain
iii. Emit HeaderReported()
event.
Create a new adapter contract for your oracle that can store block headers and fetched by Hashi.
Inherit OracleAdapter.sol
and BlockHashOracleAdapter.sol
.
Create a storeHash
function that will call _storeHash
with the following parameter:
domain
(uint256): Identifier for the domain, i.e. chain id.
id
(uint256): Identifier for the ID of the hash, i.e. block number.
hash
(bytes3): block hash(block header).
Calling _storeHash
willl emit Hashstored(id,hash)
event.
Block header querying enables one to check whether a block has been dispatched from source chain and stored in destination chain.
There are three ways to query block header
Using event filter
Using Hashi Explorer (available soon)
Interacting with Hashi contract
Block header is dispatched from source chain through a reporter contract dispatchBlocks
function, and emit BlockDispatched
event.
The reporter relay block header through the oracle and call adapter contract's setHashes
function, and emit HashStored
event.
Using event filter method allows you to target a specific oracle's BlockDispatched
and HashStored
events. If you need to check block header from multiple oracles, consider calling Hashi contract directly.
In this tutorial, we are going to use as source chain, and check whether Base's block header has been dispatched to other destination chains.
We are using in this example, alternatives are , .
Create a public client for .
Create event filters:
address: reporter address on Base (available on )
abi: ABI of the event to filter from. In this case, it is the BlockDispatched
event.
eventName: BlockDispatched
args (optional): args field target the exact parameter you want to query, if there is no available log that matches the args, it will return empty array.
targetChainId: Chain ID of the destination chain that the block header will be relayed to. Comply with standard. You may check the chain ID using. i.e. Polygon's Chain ID 137.
blockNumber: The block number from source chain. i.e. Block Number from Base 18012478.
fromBlock: Block to start including logs from.
toBlock: Block to stop including logs from.
For more info, check .
Create event filters:
abi: ABI of the event to filter from. In this case, it is the HashStored
event.
eventName: HashStored
args (optional): args field target the exact parameter you want to query, if there is no available log that matches the args, it will return empty array.
id: block number from the source chain.
hash: block header with respect to the block number (id).
fromBlock: Block to start including logs from.
toBlock: Block to stop including logs from.
Read contract function.
domain
: Chain ID of the source chain. i.e. 1 for Ethereum, 8453 for Base.
id
: block number of the source chain. (Message ID of the message in the case of Message Dispatching)
adapters
: adapter contract to query from. You may query specific adapter or multiple adapters.
threshold
: In checkHashWithThresholdFromAdapters
function, threshold
argument is the number of hash stored by adapters
agreed upon. I.e. If there are 3 adapters
and 2 as threshold
, the function will return true if 2/3 of the adapters store the same hash w.r.t the same id
.
checkHashWithThresholdFromAdapters
: Return boolean, check whether the threshold amount of adapters store the same hash w.r.t the same domain & id.
getHash
: Return bytes32 hash, check whether all the adapters store the same hash w.r.t the same domain & id.
getHashFromAdapter
: Return bytes32 hash, check whether a specific adapter store hash w.r.t a domain & id.
getHashesFromAdapters
: Return bytes32[] hash, check hash from each adapters w.r.t the same domain & id.
To check if a block number has been dispatched, you need to filter out the BlockDispatched
from the reporter contract of the source chain. For a specific target chain, includes targetChainId
in the filter argument.
Once you get the logs, you can check which block number has been dispatched from the source reporter contract to your destination adapter contract in the indexed block number event argument.
Incidents might happen where the source reporter contract dispatches block and event BlockDispatched
event correctly, but the block hash is not stored on the destination adapter contract, due to error from the oracle. You can check the status of the oracle by using tool provided by the oracles, for example:
Contract addresses on mainnet and testnet.
Note:
Current deployments on mainnet involves only general message passing based oracles, while zk Light Client based oracle will be available soon. ZK light client based oracle is already available on testnet.
More chain connections will be available soon.
*Arbitrum uses ArbHeaderStorage.sol instead of HeaderStorage.sol
Reporter dispatches blocks or messages from source chain, and Adapter stores hash on the destination chain.
Source Chain: Ethereum
Destination Chain: Gnosis Chain
Note:
Light Client based oracle doesn't require a reporter contract on source chain to dispatch Message or block headers, it only need a adapter contract on destination chain. Proof will be generated off chain and submitted to adapter contract for verification. Once verification is valid, hash will be stored.
Hashi is a stateless contract that acts as an entry point for other adapter contracts. It retrieves hashes associated with specific message IDs from designated adapter contracts and checks whether a predefined threshold is met.
Source code:
Yaho contract is deployed on the source chain to send messages to reporter contracts. When using the Yaho contract, you can define the security parameters of a message, including the reporter on the source chain, the adapter on the destination chain, and the threshold. You can also specify message-related data, such as the target chain ID, receiver address on the destination chain, and calldata.
For Light Client-based oracles (like DendrETH, Spectre, etc.), the reporter address should be set to the zero address, and only the adapter address on the destination chain needs to be specified.
Each message has a unique nonce to prevent double-spending attacks.
Source code:
Yaru contract is deployed on the destination chain and is used to execute messages. It checks if the threshold from a set of designated adapters is met by interacting with the Hashi contract. If the threshold is met, Yaru continues to call the receiver contract to execute the message.
Source code:
Oracles consist of on-chain and off-chain components that help relay hashes or messages. These oracles can be general message-passing bridges like Hyperlane, LayerZero, AMB, etc., or Light Client-based oracles like DendrETH, Spectre, Telepathy, etc.
For general message-passing bridges, the oracle includes a reporter contract on the source chain and an adapter contract on the destination chain. For Light Client-based oracles, only an adapter contract on the destination chain is needed.
FRAGOLA is a framework to create cross-chain GHO facilitators, allowing for the secure minting/burning of GHO on Ethereum while depositing the collateral on a different chain.
FRAGOLA is a GHO facilitator framework helping GHO go cross-chain! FRAGOLA stands for "FRAmework for GhO cross-Ledger Access". This framework can be used to accept on different blockchains a variety of tokens as collateral to mint GHO, as long as the price oracle for assessing the assets’ worth is properly configured. For the hackathon-specific use case, FRAGOLA allows for the minting/burning of GHO on Ethereum while depositing/withdrawing collateral on a different chain, namely Gnosis Chain.
The following is a description of the minting flow. A user deposits liquidity in a pool and receives the corresponding LP token. This allows for the generalisation of our use case since the LP tokens can be of different types (aTokens, cTokens, Univ2 LP Tokens, ERC721…), making it possible to mint GHO with different kinds of collateral. For our example, the liquidity (ETH) is deposited on Gnosis chain. On Gnosis Chain, the user locks the tokenized collateral in a smart contract called “Vault”. Having the tokens locked in a Vault is necessary to ensure the position is over-collateralized. A storage proof of the deposit is created off-chain. The Vault authorizes the minting of GHO in Ethereum. Hashi is a chain-agnostic oracle aggregator that allows for additive security. It has adapters for several cross-chain rails (including oracles, bridges, CCIPs, zk light clients) so that multiple security mechanisms can be used to verify cross-chain transfers. On Gnosis, Hashi is used to propagate block headers to Ethereum. On Ethereum, Hashi waits for the majority of the oracles to reach a consensus on the block in which there is the minting authorization. FRAGOLA then verifies the storage proof against the block header propagated by Hashi, and, if matching, proceeds to mint GHO on Ethereum. It can easily be configured to use simple message passing via the underlying bridges rather than block header-based verification, if desired.
Conversely, in the burning flow, the burn function is called through the facilitator (which creates the storage proof of the request), the authorization request is sent to Hashi and the oracles verify the existence of the request on Ethereum and propagate the block headers to Gnosis. On Gnosis, once consensus is reached, the Vault verifies the storage proofs against the block header propagated by Hashi and, if matching, GHO is burned and the relative LP tokens are given back to the user.
In the case of liquidation, the lifecycle is very similar to the one for burning GHO. The only difference is that the liquidated user’s LP tokens are transferred to the liquidator.
In building this project, we primarily focused on enabling GHO minting depositing collateral on different blockchains. The core technology we used is a combination of Hashi's block header propagation and the Chainlink Cross-Chain Interoperability Protocol (CCIP) through the Hashi adapter. This setup is crucial for verifying storage proofs, which confirm that a user has deposited the necessary collateral in the vault for GHO minting.
The project's architecture is centred around the FRAGOLA base framework and the reference facilitator, which mints GHO. The facilitator operates on a verification mechanism that uses storage proofs. These proofs are cross-checked against a block propagated through Hashi, ensuring the collateral deposit in the Vault is valid and on record. This approach simplifies the user experience, as the collateral is managed on various chains, not just Ethereum.
The most notable technical aspect of our project is how it simplifies the GHO minting process. By using cross-chain data verification, we've managed to facilitate GHO minting more directly, reducing complexity for users who wish to use assets from different blockchains as collateral. This directly addresses a key limitation in the current GHO framework, expanding its usability across diverse blockchain environments.
In summary, our project’s approach relies on efficiently utilising existing technologies like Hashi and Chainlink CCIP for a specific, practical purpose in the DeFi space – facilitating straightforward, cross-chain interactions for GHO minting.
1. Deploy two SJLZEndpoints
, one on each of the source and destination chains. SJLZEndpoint acts as a Layer Zero compatible endpoint, utilizing Hashi for cross-chain message propagation.
3. Execute xTransfer
on the SJToken to start a cross-chain minting or burning process. Ensure you approve the required token amount for wrapping if you are on the native chain.
4. The xTransfer
function internally calls _send
, a function defined in the OFT standard. This function, in turn, invokes the send
function on SJLZEndpoint
with a specific payload.
5. The SJLZEndpoint
employs Yaho
to relay the message across chains using the Hashi Message Relays.
6. Each involved bridge processes the message and stores the hash of the message in its adapter.
7. After all bridges have processed the message, Hashi executes it.
8. Upon execution, Yaru
calls SJLZEndpoint.receivePayload
, which then calls lzReceive
on the host SJToken. The lzReceive
implemented within the OFT contract, mints the corresponding amount of tokens.
Contract | Address |
---|---|
Contract | Deployed on | Address |
---|---|---|
Contract | Deployed on | Address |
---|---|---|
This step is only needed when is used.
Once the transaction is created, you need to collect messsage Id
from emitted from Yaho.
Contract | Address | Chain |
---|
User calls Yaho.dispatchMessagesToAdapters
.
User calls AMB Helper contract's getSignature
with the encodedData
as parameters obtained from step3, the function will return signature.
User calls AMB on Goerli's executeSignature
with encodedData
and signature
as parameters. The storeHashes
from AMB Adapter will be called, MessageDispatched
event will be emitted and user need messageId
data from the event.
User calls Yaru.executeMessages
with messageId
and message
as parameters.
Contract | Address | Chain |
---|
Reporter: A role that can relay both block headers and message hashes from the source chain. dispatchBlocks
function relays block headers from reporter, while dispatchMessages
function relays arbitrary message hashes. Internal function _dispatch
is called and are free to define their message passing logic in this function.
Github:
In this example, we check the adapter contract on if block header from Base has been dispatched.
Create a public client for .
address: adapter address on Base (available on )
For more info, check .
Find the Hashi contract in
For more details about the Hashi contract, check out .
LayerZero:
AMB:
Hyperlane:
Chain | Hashi | Header Storage | Yaho | Yaru |
---|
Chain | Reporter Address | Supported Destination Chain |
---|
Chain | Adapter Address | Supported Source Chain |
---|
Reporter:
Adapter:
Contract | Address |
---|
Contract | Address |
---|
Contract | Address |
---|
Contract | Address |
---|
Light Client based oracle: , , , etc.
General Message Passing (GMP) oracle: , , , , etc.
Source code:
A reporter contract inherits interface. It calls the underlying bridge contracts to relay a block header or a message.
An adapter contract inherits interface. For general message-passing bridges, the adapter contract is called by the bridge contract to store the hash of a message or block. For Light Client-based oracles, it is called when submitting proof of a block header or dispatched message event for verification. The hash is stored if the proof is valid.
"Block header" or "Block hash" are used interchangeably throughout this doc. It is the 32bytes hash of an execution block in an EVM chain, which is fetched from Solidity's function.
Live demo:
Source Code:
UI:
Video demo:
2. Deploy two SJToken
contracts, following the OFT
(Omnichain Fungible Token) standard. One contract on the source chain and the other on the destination chain. Reference the for guidance.
HeaderStorage
Yaho
AMB Header Reporter
AMB Message Relay
AxelarHeaderReporter - BNB Chain
WormholeHeaderReporter
WormholeMessageRelay
L1CrossDomainMessengerHeaderReporter…
L1CrossDomainMessengerMessageRelay…
ConnextHeaderReporter - Gnosis
CelerHeaderReporter - Polygon
LayerZeroHeaderReporter - Avalanche
HyperlaneHeaderReporter - BNB Chain
CCIPHeaderReporter - Avalanche
SygmaHeaderReporter - Gnosis
Contract
Address
Hashi
ShoyuBashi
GiriGiriBashi
Yaru - Mainnet
AMB Adapter - Header Report
AMB Adapter - Message Relay
TelepathyAdapter
WormholeAdapter - Header Report
WormholeAdapter - Message Relay
ConnextAdapter - Header Report
SygmaAdapter - Header Report
Hashi
ShoyuBashi
GiriGiriBashi
Yaru - Mainnet
TelepathyAdapter
Axelar Adapter
WormholeAdapter - Header Report
WormholeAdapter - Message Relay
CelerAdapter - Header Report
Contract
Address
Hashi
ShoyuBashi
GiriGiriBashi
Yaru - Mainnet
TelepathyAdapter
Axelar Adapter - Header Report
WormholeAdapter - Header Report
WormholeAdapter - Message Relay
HyperlaneAdapter - Header Report
LayerZeroAdapter- Header Report
Contract
Address
Hashi
ShoyuBashi
GiriGiriBashi
Yaru - Mainnet
TelepathyAdapter
Axelar Adapter
WormholeAdapter - Header Report
WormholeAdapter - Message Relay
L2CrossDomainMessengerAdapter - Header Report
L2CrossDomainMessengerAdapter - Message Relay
Hashi
ShoyuBashi
GiriGiriBashi
Yaru - Mainnet
Axelar Adapter
Telepathy Adapter
Contract
Address
Hashi
ShoyuBashi
GiriGiriBashi
Yaru - Mainnet
WormholeAdapter - Header Report
WormholeAdapter - Message Relay
LayerZeroAdapter - Header Report
CCIPAdapter - Header Report
Hashi
Gnosis Chain
ShoyuBashi
Gnosis Chain
HeaderStorage
Gnosis Chain
AMB Adapter
Gnosis Chain
AMB
Gnosis Chain
Telepathy Adapter
Gnosis Chain
Telepathy Light Client
Gnosis Chain
Sygma Adapter
Gnosis Chain
Sygma
Gnosis Chain
Dendreth Adapter
Gnosis Chain
Dendreh Light Client
Gnosis Chain
HeaderStorage
Goerli
AMB Header Reporter
Goerli
AMB
Goerli
Sygma Header Reporter
Goerli
Sygma
Goerli
Yaho
Goerli
Hashi
Chiado
ShoyuBashi
Chiado
AMB Adapter
Chiado
AMB
Chiado
Telepathy Adapter
Chiado
Telepathy Light Client
Chiado
HeaderStorage
Goerli
AMB Header Reporter
Goerli
AMB
Goerli
Contract
Address
Yaho
L1CrossDomainMessengerHeaderReporter
L1CrossDomainMessengerMessageRelay
WormholeHeaderReporter
WormholeMessageRelay
Contract
Address
Hashi
0xE64902307d04C377B6D8D428D99153881eD7E705
L2CrossDomainMessengerAdapter - HeaderReporter
0x856dcc80f75a9737D9D498266E1Af013668316Fb
L2CrossDomainMessengerAdapter - MessageRelay
0x04413A4795dD1f5347eAD1CD7C76Bd9E5e48b461
Contract
Address
Hashi
Yaru - Goerli
WormholeAdapter - HeaderReporter
WormholeAdapter - MessageRelay
Yaho | Goerli |
AMB Message Relay | Goerli |
AMB Adapter for Message Relay | GC |
Yaru | GC |
Yaho | GC |
AMB Message Relay | GC |
AMB Helper | GC |
AMB Adapter for Message Relay | Goerli |
Yaru | Goerli |
Hashi | Goerli |
Ethereum |
Gnosis Chain |
Polygon |
BNB |
Base |
Arbitrum* |
Optimism |
LUKSO |
Ethereum | Polygon, BNB, Optimism, Gnosis Chain |
Gnosis Chain | Ethereum, Polygon, BNB, Arbitrum, Optimism, Base |
Polygon | Gnosis Chain, BNB, Arbitrum, Optimism, Base |
BNB | Gnosis, Polygon, Arbitrum, Optimism, Base |
Arbitrum | Gnosis, Polygon, BNB, Optimism, Base |
Optimism | Gnosis, Polygon, BNB, Arbitrum, Base |
Base | Gnosis, Polygon, BNB, Arbitrum, Optimism |
Ethereum | Gnosis Chain |
Gnosis Chain | Ethereum, Polygon, BNB, Arbitrum, Optimism, Base |
Polygon | Ethereum, BNB, Arbitrum, Optimism, Base |
BNB | Ethereum, Gnosis Chain, Polygon, Arbitrum, Optimism, Base |
Arbitrum | Gnosis Chain, Polygon, BNB, Optimism, Base |
Optimism | Ethereum, Gnosis Chain, Polygon, BNB, Arbitrum, Base |
Base | Gnosis Chain, Polygon, BNB, Arbitrum, Optimism |
HeaderStorage |
Hashi |
Yaho |
Yaru (listen to Yaho from Chiado) |
Yaru (listen to Yaho from Lukso testnet) |
Yaru (listen to Yaho from Holesky) |
AMBReporter |
CCIP Reporter |
Wormhole Reporter |
AMBAdapter |
DendrETH Adapter (updates block header from Chiado) |
DendrETH Light Client |
Spectre Adapter (listens MessageDispatched event from Chiado's Yaho) |
Hashi |
HeaderStorage |
Yaho |
Yaru (listen to Yaho from Sepolia) |
HeaderStorage |
Hashi |
Yaho |
Yaru (listen to Yaho from Sepolia) |
AMBReporter |
AMBAdapter |
CCIP Adapter |
Wormhole Adapter |
DendrETH Adapter (updates block header from Sepolia) |
DendrETH Light Client |
Spectre Adapter (listens MessageDispatched event from Sepolia's Yaho) |
HeaderStorage |
Hashi |
Yaho |
Yaru (listen to Yaho from Sepolia) |
DendrETH (updates block header from Sepolia) |
DendrETH Light Client |
g0 (Mar 24)
To query a block header from Hashi, navigate to ShoyuBashi contract on gnosisscan.
Click getThresholdHash
function.
Enter the domain (chain ID, i.e. 5 for Goerli) and id (block number from domain) for the block you want to query. The result will be the block hash that has passed the threshold from adapters (i.e. 2 out of 4 in Goerli <-> GC). Not every block will be stored by the adapters and reach threshold, if no threshold has been reached, the result will be bytes32(0). You can utilize Adapters Dashboard to check which block has been stored.
You may double check if the block hash is correct by searching your block hash in Adapters Dashboard.
100: 42:
1:
1: