Bridging Blockchains: How Harmony deploys tokens on LayerZero.
A step-by-step overview of how we pick and deploy tokens.
Token bridging allows the transfer of tokens between two different blockchain networks. In this case, bridging tokens from Binance Smart Chain to Harmony would enable users to access and utilize tokens on both networks. This would increase liquidity and utility for the token and provide users with more flexibility and options for using their tokens. Additionally, bridging tokens between networks can help reduce congestion and lower transaction costs on a particular blockchain by allowing users to move their transactions to another network with lower fees or better throughput.
Introduction to Bridge Architecture:
Harmony’s bridge architecture allows for the transferring of tokens or assets from one blockchain to another. The process involves signing an approve transaction that gives the ProxyERC20 contract permission to transfer the user's token. The user then calls estimateSendFee
to determine how much gas is needed on the destination side. The user then signs a sendFrom
with the gas fee calculated from the previous method. After validating this transaction, the ProxyHRC20 contract invokes the credit command, which mints the wrapped tokens to the user's wallet.
Brief summary of steps
Before deploying tokens on Harmony's LayerZero Bridge, a token is chosen based on factors such as the number of transfers, the value on Harmony, holders, activity, and market cap. The Solidity files required for the process can be found on the GitHub repository solidity-examples— a fork of Layer Zero’s solidity examples. The files ProxyERC20.sol
and ProxyHRC20.sol
are required. The Solidity files must be flattened using Hardhat, and all extra // SPDX-License-Identifier: ...
must be removed. The flattened code can then be moved into a Remix default workspace. Under Compiler > Compiler
, the latest release is selected, and under Compiler > Advanced Configurations
, Enable Optimization
is unchecked.
To deploy on the ERC20 side, select Injected Provider - MetaMask
as the Environment from the drop-down menu. This will prompt a MetaMask extension confirmation, and the network selected in MetaMask will be the network that Remix deploys to. For the contract, select ProxyERC20
. The BSC chain endpoint is copied into Remix under _lzEndpoint
, and the target token address is pasted into _proxyToken
. After clicking “Transact,” a MetaMask confirmation will pop up, and confirming in MetaMask should result in a success indicator in Remix. The gas fees can get relatively high when deploying on Ethereum, so it may be best to have approximately 500 USD worth of ETH in the MetaMask wallet.
A more detailed step-by-step process is laid out below.
Picking a token
A token is chosen to be implemented on our LayerZero Bridge. A token with a decent number of transfers, value on Harmony, holders, activity, and market cap would be a good candidate.
Getting ready to deploy (all of the installation and downloads)
The Solidity files that are implemented are available in a fork of Layer Zero’s solidity examples. For the process laid out in this article, the files ProxyERC20.sol
and ProxyHRC20.sol
are required. The two files are located in solidity-examples/contracts/token/oft/extension
.
In order to flatten the Solidity files, Hardhat needs to be installed [NOTE: Hardhat needs latest LTS node.js version to work which is currently 18.x].
Both ProxyERC20.sol
and ProxyHRC20.sol
need to be flatted via:
As a result of the flattening process, there are many many licenses listed throughout both files. To be compiled properly, all extra // SPDX-License-Identifier: ...
other than the first have to be deleted.
This flattened code can now be moved into a Remix default workspace.
Under Compiler > Compiler , use the latest release. At the time of writing, this is v0.8.18. Under Compiler > Advanced Configurations, ensure that Enable Optimization is un-checked.
Attempt to compile ProxyERC20.sol. If this is successful, move on.
Deploying on ERC20 side
Under Deploy & Run Transactions
, select Injected Provider - MetaMask
as the Environment from the drop down menu. This will prompt a MetaMask extension confirmation.
The network selected in MetaMask will be the network that Remix deploys to.
For contract, select ProxyERC20.
The LayerZero Technical Reference lists the BSC chain endpoint under “Layer Zero Infrastructure.”
BSC Endpoint: 0x3c2269811836af69497E5F486A85D7316753cf62
The endpoint is copied into Remix under _lzEndpoint.
The target token address is pasted into _proxyToken.
After clicking “Transact,” a MetaMask confirmation will pop up. This will charge a gas fee, so ensure there are sufficient native coin funds in the MetaMask wallet. Confirming in MetaMask should result in a success indicator in Remix. [NOTE: The gas fees can get quite high when deploying on Ethereum so it may be best to have approximately 500USD worth of ETH in the MetaMask wallet. These prices can also significantly vary.]
Best Practice (Verifying the contract on BscScan)
Copy the deployed contract’s address listed under “Deployed Contracts” in Remix and search for it in BscScan. Select “Contract” and then the “Verify and Publish” link.
The following should be selected:
Contract Address: Auto-populated
Compiler Type: Solidity (Single file)
Compiler Version: Most recent version (same as the one selected in Remix)
Open Source License Type: 3) MIT License (MIT)
After clicking continue, the flattened Solidity code should be copied into BscScan. Don’t be a robot and click “Verify.” The contract is now verified and published on the BscScan explorer.
Deploying on the HRC20 side
Do the same with the flattened ProxyHRC20.sol as was done with the ProxyERC20.sol up until deploying. To recap, open the flattened code in Remix, remove all but the first license, compile with the latest version, and ensure optimization is off.
On the Deploy page, select “Injected Provider - MetaMask” as the Environment and ensure that the MetaMask account is switched to the Harmony Mainnet. This should be reflected in remix.
The contract type should be ProxyHRC20 - ProxyHRC20.sol
. Under deploy, the parameters should be the following:
_lzEndpoint: The Harmony endpoint listed here under “Layer Zero Infrastructure.”
_proxyToken: The token address from the Harmony side.
_multisig: The “Multisig (on Harmony)” address listed here.
_bridgeManager: The “BSC Bridge Manager (on Harmony)” address listed here.
Transacting this will pop up the same MetaMask confirmation as the deploy on the ERC20 side. This will require a small amount of native ONE tokens in the MetaMask account.
Good Practice (Verifying the contract on Harmony Explorer)
Once the HRC20 proxy contract has been deployed, take the transaction id and find it in the Harmony Explorer. Verify the contract with the following parameters:
Contract Name: The name of the file (ex. ProxyHRC20)
Compiler: The version of the compiler used to compile in Remix
Paste in the ProxyHRC20 code from Remix and then click “paste arguments from tx input” to auto-populate the Constructor Arguments. The contract can now be verified.
Connecting the proxies together
For the contracts, expand the following drop down under “Deploy & run transactions.” The goal is to connect the ProxyERC20 to Harmony chain and the ProxyHRC20 to Binance chain via setTrustedRemoteAddress
.
For ProxyHRC20, put in the address of the ProxyERC20 contract and the chainID of BSC. For ProxyERC20, put in the address of the ProxyHRC20 contract and the chainID of Harmony. The chainIDs can be found in Harmony docs here. Hitting transact on both contracts will pop up a MetaMask confirmation. After confirming, there should be a success notification in Remix.
Setting custom parameters
The following methods need to be called to set custom parameters for the ProxyERC20 contract. LayerZero, by default, uses 200k gas which is not sufficient to mint wrapped tokens via the multi-sig contract (at least 300k gas is needed). Therefore, the minimum gas must be raised to 300k.
Final steps
Contract ownership is verified to be under the controlling multi-sig, and the proxies are whitelisted by the controlling multi-sig. The backend and frontend of the bridge website are updated, and finally, the token is available for bridging on https://bridge.harmony.one/one.
Conclusion
Bridging tokens from Ethereum to Harmony requires several steps, including selecting a suitable token to be implemented on the LayerZero Bridge, installing and downloading required Solidity files, flattening the code, and compiling the code in the Remix default workspace. After successful compilation, the ProxyERC20 contract must be deployed on the Ethereum side, and the ProxyHRC20 contract must be deployed on the Harmony side. The bridging process involves signing an approve transaction, estimating gas fees with the estimateSendFee
method, signing a sendFrom
transaction with the calculated gas fee, and invoking the credit command to mint wrapped tokens to the user's wallet. Good practice includes verifying the deployed contract on the Harmony Explorer. This process requires technical knowledge of Solidity, Remix, and MetaMask and a good understanding of gas fees and blockchain infrastructure.