HelloHOP
HelloHOP
is an example implementation designed to demonstrate the capabilities of Via Labs technology in facilitating cross-chain message passing. This sample contract illustrates the use of the Via Labs package for enabling messages to traverse multiple blockchain networks via a predefined sequence of chain IDs. It serves primarily as a technical showcase, highlighting the mechanics of cross-chain communication without external bridges in a multi-chain environment.
Prerequisites
Node.js and npm
# Install using APT
sudo apt update
sudo apt install nodejs npm
Git
# Install using APT
sudo apt install git
Testnet Tokens
- Ethereum Sepolia: Ethereum Testnet Faucet
- Polygon Amoy: Polygon Testnet Faucet
- Avalanche: Avalanche Testnet Faucet
- Ethereum Holesky: Ethereum Holesky Testnet Faucet
Installation
Open a terminal to run the following commands. You can use any terminal of your choice, including the built in terminal in (vscode) (Terminal -> New Terminal)
- Clone the Repository:
git clone https://github.com/VIALabs-io/hello-hop.git
- Change into Project Directory:
cd hello-hop
- Install Dependencies:
npm install
- Set Up Environment Variables:
Create a new.env
file to set your EVM private key for contract deployment or copy and edit the existing.env.example
to.env
PRIVATE_KEY=0000000000000000000000000000
Deployment
Deploy the HelloHOP contract to your desired networks. This must be done for each network you wish to operate on. You can see a list of our networks in the Package documentation.
- Ethereum Sepolia Testnet Deployment:
npx hardhat --network ethereum-sepolia deploy
- Polygon Testnet Deployment:
npx hardhat --network polygon-amoy deploy
- Avalanche Testnet Deployment:
npx hardhat --network avalanche-testnet deploy
- Ethereum Holesky Testnet Deployment:
npx hardhat --network ethereum-holesky deploy
Configuration
Edit the networks.ts
file and include all of the networks the contract is deployed on.
const networks = [
"avalanche-testnet",
"ethereum-holesky",
"ethereum-sepolia",
"polygon-amoy"
];
export default networks;
Once all contracts are deployed across the desired networks and listed in networks.ts
, configure them using the provided script. Remember, if a new network is added later, all contracts must be reconfigured.
- Ethereum Sepolia Testnet Configuration:
npx hardhat --network ethereum-sepolia configure
- Polygon Testnet Configuration:
npx hardhat --network polygon-amoy configure
- Avalanche Testnet Configuration:
npx hardhat --network avalanche-testnet configure
- Ethereum Holesky Testnet Configuration:
npx hardhat --network ethereum-holesky configure
Usage
Initiating a Message
To start a message off, the go()
method is called on any of the networks the contract is deployed on, and the path desired is set with the --path
parameter followed by a comma seperated list of Chain IDs. Chain IDs can be looked up in the Package documentation.
npx hardhat --network ethereum-sepolia go --path 80002,43113
Contract Breakdown
The HelloHOP
contract is a Solidity implementation designed for demonstrating cross-chain message passing using the Via Labs framework. It allows messages to be sent sequentially across multiple blockchain networks.
pragma solidity 0.8.17;
import "@vialabs-io/contracts/message/MessageClient.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract HelloHOP is MessageClient, Ownable {
event Go();
event Completed(uint _startChainId, uint hops);
event NextHop(uint startChainId, uint hops);
/**
* Kicks off the initial message, which will then be sent from chain to chain, following
* the path set in _chainlist which is a comma seperated list of chain ids
*
*/
function go(uint[] calldata _chainlist) external onlyOwner {
// create cross chain message
bytes memory _data = abi.encode(block.chainid, 1, _chainlist);
// send message
_sendMessage(_chainlist[0], _data);
emit Go();
}
/**
* This is where we handle the received message from the sending chain, and if there
* are still more hops to follow, execute another message to the next chain.
*
*/
function messageProcess(uint, uint _sourceChainId, address _sender, address, uint, bytes calldata _data) external override onlySelf(_sender, _sourceChainId) {
// decode message
(uint _startChainId, uint _hop, uint[] memory _chainlist) = abi.decode(_data, (uint, uint, uint[]));
if(_hop >= _chainlist.length) {
emit Completed(_startChainId, _hop);
} else {
// create cross chain message
bytes memory _newData = abi.encode(_startChainId, _hop+1, _chainlist);
// send message
_sendMessage(_chainlist[_hop], _newData);
emit NextHop(_startChainId, _hop+1);
}
}
}
Contract Overview
- Inheritance:
MessageClient
: Inherits from the Via Labs'sMessageClient
for handling cross-chain messages.Ownable
: Inherits from OpenZeppelin'sOwnable
, restricting certain functions to the contract owner.
Events
Go
: Emitted when the message passing process is initiated.Completed
: Emitted when the message has traversed all the specified chains.NextHop
: Emitted on each hop to the next chain in the sequence.
Function: go
function go(uint[] calldata _chainlist) external onlyOwner
- Purpose: Initiates the message passing process.
- Parameters:
_chainlist
- an array of chain IDs representing the path for the message. - Functionality:
- Encodes the current chain ID, hop number (starting at 1), and the chain list into a byte array
_data
. - Sends the message to the first chain in the list using
_sendMessage
. - Triggers the
Go
event.
- Encodes the current chain ID, hop number (starting at 1), and the chain list into a byte array
Function: messageProcess
function messageProcess(uint, uint _sourceChainId, address _sender, address, uint, bytes calldata _data) external override onlySelf(_sender, _sourceChainId)
- Purpose: Handles incoming messages and forwards them if there are more hops to follow.
- Parameters:
_sourceChainId
: Chain ID of the message sender._sender
: Address of the message sender._data
: Encoded data containing the start chain ID, hop count, and chain list.
- Functionality:
- Decodes
_data
to extract the start chain ID, hop count, and chain list. - If the current hop is the last one, emits the
Completed
event. - Otherwise, increments the hop count, encodes a new message, and sends it to the next chain in the list.
- Emits the
NextHop
event for each successful hop to the next chain.
- Decodes
Security and Modifiers
onlyOwner
Modifier (fromOwnable
): Restricts the execution of thego
function to the contract owner.onlySelf
Modifier: Ensures that themessageProcess
function is only callable by the contract itself, as part of the cross-chain message handling.