Skip to content

Latest commit

 

History

History
215 lines (161 loc) · 7.3 KB

README.md

File metadata and controls

215 lines (161 loc) · 7.3 KB

HelloERC20

HelloERC20 is an example ERC20 token implemented in Solidity, designed for cross-chain operations without relying on traditional bridge mechanisms. Utilizing the VIA Labs package and MessageClient extension, it demonstrates a bridgeless approach to native token minting and burning across different blockchain networks.

Features

  • ERC20 Token Implementation: A standard ERC20 token with additional burnable functionality.
  • Cross-Chain Functionality: Native support for cross-chain interactions without using a bridge.
  • VIA Labs Integration: Leverages the VIA Labs package for seamless cross-chain communication.
  • Configurable on Multiple Networks: Can be deployed and configured across various blockchain networks.

Prerequisites

Before you begin, ensure you have the following installed:

Please visit node documentation link and the git install documentation for more information.

Installation

Please 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)

  1. Clone the Repository:
git clone https://github.com/VIALabs-io/hello-erc20.git
  1. Open in IDE: After cloning the repository, if using vscode or a similar IDE, you can now open the hello-erc20 in your IDE of choice.
code hello-erc20
  1. Install Dependencies: In vscode (Terminal -> New Terminal)
npm install
  1. 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
  1. Gas tokens: Make sure you have enough gas to complete the contract deployments and a couple test transactions

Deployment

Deploy the HelloERC20 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

  1. Ethereum Sepolia:
npx hardhat --network ethereum-sepolia deploy
  1. Polygon Testnet:
npx hardhat --network polygon-amoy deploy

Configuration

Edit the networks.ts file and include all of the networks the contract is deployed on.

[
    "ethereum-sepolia",
    "polygon-amoy"
]

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.

  1. Ethereum Sepolia:
npx hardhat --network ethereum-sepolia configure
  1. Polygon Testnet:
npx hardhat --network polygon-amoy configure

Usage

Checking Token Balance

To check the balance of tokens on a particular chain:

npx hardhat --network ethereum-sepolia get-token-balance

Bridging Tokens to Another Chain

To send tokens to another chain it is required to set the --dest parameter to the destination chain id. The example below uses the id for the Polygon Testnet. Chain IDs can be looked up in the Package documentation.

npx hardhat --network ethereum-sepolia bridge-token --dest 80002 --amount 50

Check Tokens on Destination Chain

You can now check the balance on the destination chain. Please give the transaction some time to process. You should see your balance increase on the destination chain:

npx hardhat --network polygon-amoy get-token-balance

Contract Breakdown of HelloERC20

This contract is an ERC20 token with additional functionalities for cross-chain operations. It inherits from ERC20Burnable for standard ERC20 functionality with burn capabilities and from MessageClient for handling cross-chain messages.

pragma solidity =0.8.17;

import "@vialabs-io/contracts/message/MessageClient.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";

contract HelloERC20 is ERC20Burnable, MessageClient {
    constructor() ERC20("HelloERC20", "HELLO") {
        _mint(msg.sender, 1_000_000 ether);
    }

    function bridge(uint _destChainId, address _recipient, uint _amount) external onlyActiveChain(_destChainId) {
        // burn tokens
        _burn(msg.sender, _amount);

        // send cross chain message
        _sendMessage(_destChainId, abi.encode(_recipient, _amount));
    }

    function messageProcess(uint, uint _sourceChainId, address _sender, address, uint, bytes calldata _data) external override  onlySelf(_sender, _sourceChainId)  {
        // decode message
        (address _recipient, uint _amount) = abi.decode(_data, (address, uint));

        // mint tokens
        _mint(_recipient, _amount);
    }
}

Constructor

constructor() ERC20("HelloERC20", "HELLO") {
    _mint(msg.sender, 1_000_000 ether);
}
  • Initializes the token with the name "HelloERC20" and symbol "HELLO".
  • Mints 1,000,000 tokens to the address deploying the contract.

Function: bridge

function bridge(
    uint _destChainId, 
    address _recipient, 
    uint _amount
) external onlyActiveChain(_destChainId) {
    // burn tokens
    _burn(msg.sender, _amount);

    // send cross chain message
    _sendMessage(_destChainId, abi.encode(_recipient, _amount));
}
  • Allows a user to send tokens to another chain.
  • Parameters:
    • _destChainId: The ID of the destination chain.
    • _recipient: The recipient's address on the destination chain.
    • _amount: The amount of tokens to send.
  • Process:
    • Burns the specified _amount of tokens from the sender's balance.
    • Encodes the _recipient address and _amount into bytes (_data).
    • Calls _sendMessage, a function from MessageClient, to send this encoded data to the destination chain.
  • Modifiers:
    • onlyActiveChain: A modifier restricts this function to be called only if the destination chain is active.

Function: messageProcess

function messageProcess(
    uint, 
    uint _sourceChainId, 
    address _sender, 
    address, 
    uint, 
    bytes calldata _data
) external override  onlySelf(_sender, _sourceChainId)  {
    // decode message
    (address _recipient, uint _amount) = abi.decode(_data, (address, uint));

    // mint tokens
    _mint(_recipient, _amount);
}
  • Handles incoming messages from other chains.
  • Parameters:
    • _sourceChainId: The ID of the source chain from where the message is sent.
    • _data: Encoded data containing the recipient's address and the amount.
  • Process:
    • Decodes _data to extract _recipient and _amount.
    • Mints _amount of tokens to _recipient's address on the current chain.
  • Modifiers:
    • onlySelf: A modifier restricts this function to be called only if the message was sent from the corresponding deployments of this contract on the source chain.