Skip to main content

Plasma Using Metamask

This tutorial is a brief introduction on how to transfer tokens between Ethereum and Polygon on Plasma using matic.js SDK and Metamask. Polygon-Ethereum bridge provides a cross-chain channel using which users can transfer tokens from Ethereum to Polygon and vice-versa. More details on using the bridge can be found here. This tutorial mainly focuses on using the bridge from a front end perspective. We will be using MetaMask for this purpose.

The most important thing to be understood from this tutorial is the proper usage of the web3 provider in the matic.js instance we create. Whether using PoS or Plasma, certain actions need to be performed on Polygon and some on Ethereum. Due to this reason, different providers are required in different scenarios. Hence correctly setting the providers is necessary.

  1. An example react app that demonstrates the usage of the Plasma and PoS bridge can be found here .
  2. Install the dependencies using npm install.
  3. Replace the token addresses in src/config.json with your corresponding token addresses
posRootERC20: ERC20 root token address on pos bridge
posChildERC20: ERC20 child token address on pos bridge
posWETH: PoS Weth
rootChainWETH: WETH deployed on root chain
plasmaWETH: Plasma WETH
plasmaRootERC20: ERC20 root token deployed on plasma
plasmaChildERC20: ERC20 child token deployed on plasma
MATIC_RPC: RPC for child chain,
ETHEREUM_RPC: RPC for root chain,
VERSION: network version,
NETWORK: "testnet" or "mainnet"
MATIC_CHAINID: Chain ID of child chain,
ETHEREUM_CHAINID: Chain ID of root chain
  1. Run the project using npm start.

Example using Plasma ERC20

note

For the mainnet, Ethereum is the root chain and Polygon Mainnet is the child chain and for the testnet, Goerli is the root chain and Mumbai is the child chain. The values in the config.json file should be set accordingly. Goerli and Mumbai networks are used as the root and child chain in this tutorial.

getMaticPlasmaParent() and getMaticPlasmaChild() are used to initialize the root and child chain matic.js objects for the Plasma bridge. Code snippets mentioned below, under each step, can be found in the tutorial repo as well.

Deposit

To deposit ERC20 tokens, an approve function call has to be made before calling the deposit function. Upon clicking the deposit button, MetaMask will first ask to approve the transfer of a specified number of tokens and after the confirmation of the approval transaction, MetaMask will ask to confirm the deposit transaction. Make sure the root chain network is selected in MetaMask for deposit functionality.

const erc20RootToken = plasmaClient.erc20(<root token address>, true);

// approve 100 amount
const approveResult = await erc20Token.approve(100);

During deposit of ERC20 tokens, providers are specified as below

maticProvider: maticprovider

parentProvider: window.web3

note

Deposits from Ethereum to Polygon happen using a state sync mechanism and takes about ~22-30 minutes After waiting for this time interval, it is recommended to check the balance using web3.js/matic.js library or using Metamask.

The explorer will show the balance only if at least one asset transfer has happened on the child chain. This link explains how to track the deposit events.

Transfer

Once deposited, the token can be transfered to any other account on the Matic chain. During Transfer, only the maticProvider needs to be set as window.web3.

const erc20Token = plasmaClient.erc20(<token address>);

const result = await erc20Token.transfer(<amount>,<to>);

const txHash = await result.getTransactionHash();

const txReceipt = await result.getReceipt();

MATIC is native token on Polygon. We support transfer of MATIC tokens without any token address.

// initialize token with null means use MATIC tokens
const erc20Token = plasmaClient.erc20(null);

const result = await erc20Token.transfer(<amount>,<to>);

const txHash = await result.getTransactionHash();

const txReceipt = await result.getReceipt();

Initiate Withdraw

For withdrawing tokens back to root chain, tokens have to be first burnt on child chain. Make sure child chain network is selected in metamask.

const erc20ChildToken = plasmaClient.erc20(<child token address>);

// start withdraw process for 100 amount
const result = await erc20ChildToken.withdrawStart(100);

const txHash = await result.getTransactionHash();

const txReceipt = await result.getReceipt();

During burning of ERC20 tokens, providers are specified as below

maticProvider: window.web3

parentProvider: ethereumprovider

Confirm Withdraw

Withdrawal of funds is initiated from the child chain. A checkpoint interval of 30 mins (around 10 minutes for testnet) is set, where all the blocks on the Polygon block layer are validated. Once the checkpoint is submitted to the root chain, the withdraw function can be triggered.

Once the withdraw function is successful, an NFT Exit (ERC721) token is created. The withdrawn funds can be claimed back to your account on the root chain using a process-exit which is explained in the next step.

In the confirm withdraw step, providers are specified as below:

maticProvider: maticprovider

parentProvider: window.web3

The _withdrawConfirm_ function in Plasma bridge involves block proof generation by querying the child chain multiple times and hence it may take 4-5 seconds for MetaMask to popup as it consumes time to build the transaction object.

const erc20Token = plasmaClient.erc20(<token address>, true);

const result = await erc20Token.withdrawConfirm(<burn tx hash>);

const txHash = await result.getTransactionHash();

const txReceipt = await result.getReceipt();

You can use the _withdrawConfirmFaster_ method which is faster because it generates proof in the backend. Fore more details to use this please visit this guide.

Withdraw Exit

The exit process takes place on the root chain and upon confirmation on the root chain, an equivalent amount of tokens burned on child chain is released to the users account. Make sure the root chain network is selected in Metamask.

const erc20RootToken = plasmaClient.erc20(<root token address>, true);

const result = await erc20Token.withdrawExit();

const txHash = await result.getTransactionHash();

const txReceipt = await result.getReceipt();

In the process exit step, providers are specified as below:

maticProvider: maticprovider

parentProvider: window.web3