Building Cross-Chain Bridge Dapp

Iā€™m building Cross-Chain Bridge Dapp following the tutorial: https://www.youtube.com/watch?v=UkWj7rwOGGc and I have several questions like:

  • The order for deployment of contract
  • Where can I get the gateway address and whatā€™s it for bridge contract deployment (Code below)

The Code for 2 bridge contract:

  • Main Bridge
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

//Remix style import
//import { IERC20 } from "@openzeppelin/[email protected]/token/ERC20/IERC20.sol";

//Brownie style import
import { IERC20 } from "OpenZeppelin/[email protected]/contracts/token/ERC20/IERC20.sol";


contract MainBridge {

    IERC20 private mainToken;

    address gateway;

    event TokensLocked(address indexed requester, bytes32 indexed mainDepositHash, uint amount, uint timestamp);
    event TokensUnlocked(address indexed requester, bytes32 indexed sideDepositHash, uint amount, uint timestamp);

    constructor (address _mainToken, address _gateway) {
        mainToken = IERC20(_mainToken);
        gateway = _gateway;
    }

    function lockTokens (address _requester, uint _bridgedAmount, bytes32 _mainDepositHash) onlyGateway external {
        emit TokensLocked(_requester, _mainDepositHash, _bridgedAmount, block.timestamp);
    }

    function unlockTokens (address _requester, uint _bridgedAmount, bytes32 _sideDepositHash) onlyGateway external {
        mainToken.transfer(_requester, _bridgedAmount);
        emit TokensUnlocked(_requester, _sideDepositHash, _bridgedAmount, block.timestamp);
    }

    modifier onlyGateway {
      require(msg.sender == gateway, "only gateway can execute this function");
      _;
    }
}
  • Side Bridge
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { IERC20Child } from "./IERC20Child.sol";

contract SideBridge {

    event BridgeInitialized(uint indexed timestamp);
    event TokensBridged(address indexed requester, bytes32 indexed mainDepositHash, uint amount, uint timestamp);
    event TokensReturned(address indexed requester, bytes32 indexed sideDepositHash, uint amount, uint timestamp);
    
    IERC20Child private sideToken;
    bool bridgeInitState;
    address owner;
    address gateway;


    constructor (address _gateway) {
        gateway = _gateway;
        owner = msg.sender;
    }

    function initializeBridge (address _childTokenAddress) onlyOwner external {
        sideToken = IERC20Child(_childTokenAddress);
        bridgeInitState = true;
    }

    function bridgeTokens (address _requester, uint _bridgedAmount, bytes32 _mainDepositHash) verifyInitialization onlyGateway  external {
        sideToken.mint(_requester,_bridgedAmount);
        emit TokensBridged(_requester, _mainDepositHash, _bridgedAmount, block.timestamp);
    }

    function returnTokens (address _requester, uint _bridgedAmount, bytes32 _sideDepositHash) verifyInitialization onlyGateway external {
        sideToken.burn(_bridgedAmount);
        emit TokensReturned(_requester, _sideDepositHash, _bridgedAmount, block.timestamp);
    }

    modifier verifyInitialization {
      require(bridgeInitState, "Bridge has not been initialized");
      _;
    }
    
    modifier onlyGateway {
      require(msg.sender == gateway, "Only gateway can execute this function");
      _;
    }

    modifier onlyOwner {
      require(msg.sender == owner, "Only owner can execute this function");
      _;
    }
}

Thanks a lot!

For description of what is the _gateway you will need to rewatch the video. It is a separate Ethereum address that you control and that you need to generate, then yo use that one in the cloud code. (As explained in the video this is not production architecture but an illustration, so it is not safe).

The contracts you need are, deployed in that order.

  1. Main token contract
  2. Main bridge
  3. Side bridge
  4. Child token contract
2 Likes

Thanks for the effort in creating a starting point for a bridge using Moralis. Question: if we already have a trading token, the open zep erc 20 import has a mint function, and we already have a supply, how would we utilize for an existing token?

Can you reclarify your question please?

Certainly. There is a tutorial from Daniel from Morales. In the files he has in the repository he clones the open zepplin standard erc 20 contract which has a mint function.
We already have an existing token we wish to bridge to binance.
Question: If a dev has existing tokens what would be the proper contract to utilize instead of the ā€œtokenContract.sol

Certainly. There is a tutorial from Daniel from Morales. In the files he has in the repository he clones the open zepplin standard erc 20 contract which has a mint function.
We already have an existing token we wish to bridge to binance.
Question: If a dev has existing tokens what would be the proper contract to utilize instead o

If you would to bridge an existing ERC20 token you could just redeploy the same contract on another chain. Or are you saying your existing contract doesnā€™t have a mint function?

Existing tERC20 Token has fixed supply and is trading. We want holders to be able to send those tokens to a bridge, lock them, and
mint the same amt on another chain. and do the same in reverse.

Iā€™m not sure how the reverse can happen if the supply is fixed. Is your existing contract upgradeable? If not you may have to create another token contract to migrate existing holders.

Thereā€™s a few discussions about this like this.

You can post this issue in the #solidity-help channel on the Moralis Discord if you havenā€™t already.

Hi, Nashton.

I would explain the process, but want to warn you. The tutorial is for educational purposes only. It is not production code, and you are advised to not use this in production.

Having said that, your original ERC-20 is not needed to be re-deployed, and is not part of the logic. It was deployed in the video because it is needed for the demo.

The contracts that are needed are the two bridges (one in the origin and the other in the destination chain), and the child token contract, this should be deployed in the destination chain.

You are not supposed to already have an equivalent token in the destination chain, if you do, then you cannot create a bridge since you will be duplicating your supply.

Best Regards

Daniel

Hey Daniel ā€¦ could you please explain why one needs to init the sidebridge instead of just deploying it

Iā€™m having issues when deploying side bridge on remix get this error

Check your IERC20Child.sol import path, make sure this contract exists.

Itā€™s completely copied from
You guys YouTube video from GitHub from this link https://github.com/DanielMoralisSamples/27_ERC20_Bridge_POC/blob/master/solidity/SideBridge.sol

I know itā€™s got to
Be something silly the main bridge went right thru and deployed

Feel like something has to be missing or updated very odd Any and all help would be so amazing Iā€™ve spent 7 hrs trying to figure it out getting no where

It looks like you need two contracts, that one that is imported, you have to handle it somehow. You could copy itā€™s in tire source or make that import work.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { IERC20Child } from ā€œ./IERC20Child.solā€;

contract SideBridge {

event BridgeInitialized(uint indexed timestamp);
event TokensBridged(address indexed requester, bytes32 indexed mainDepositHash, uint amount, uint timestamp);
event TokensReturned(address indexed requester, bytes32 indexed sideDepositHash, uint amount, uint timestamp);

IERC20Child private sideToken;
bool bridgeInitState;
address owner;
address gateway;


constructor (address _gateway) {
    gateway = _gateway;
    owner = msg.sender;
}

function initializeBridge (address _childTokenAddress) onlyOwner external {
    sideToken = IERC20Child(_childTokenAddress);
    bridgeInitState = true;
}

function bridgeTokens (address _requester, uint _bridgedAmount, bytes32 _mainDepositHash) verifyInitialization onlyGateway  external {
    sideToken.mint(_requester,_bridgedAmount);
    emit TokensBridged(_requester, _mainDepositHash, _bridgedAmount, block.timestamp);
}

function returnTokens (address _requester, uint _bridgedAmount, bytes32 _sideDepositHash) verifyInitialization onlyGateway external {
    sideToken.burn(_bridgedAmount);
    emit TokensReturned(_requester, _sideDepositHash, _bridgedAmount, block.timestamp);
}

modifier verifyInitialization {
  require(bridgeInitState, "Bridge has not been initialized");
  _;
}

modifier onlyGateway {
  require(msg.sender == gateway, "Only gateway can execute this function");
  _;
}

modifier onlyOwner {
  require(msg.sender == owner, "Only owner can execute this function");
  _;
}

}

This is the part Iā€™m getting the error from its not finding the import info on remeix Iā€™ve tryed for past 12 hrs now to figure out how to get right import import { IERC20Child } from ā€œ./IERC20Child.solā€;

You can try to copy its contents directly if you donā€™t find a way to import it.