Skip to content

Commit 1f14b84

Browse files
authored
Merge pull request 0xPolygon#313 from 0xPolygon/empieichO-docs-review
Update Matic.js doc - adding "Message" doc
2 parents 48dc6bc + f6ca06a commit 1f14b84

File tree

3 files changed

+254
-0
lines changed

3 files changed

+254
-0
lines changed
122 KB
Loading
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
This document shows you how to customize wrapped tokens using adapter contracts, transfer tokens between Ethereum and Polygon zkEVM networks, and how to use Matic.js to bridge assets from Ethereum to Polygon zkEVM and vice versa.
2+
3+
## Basic functions for error passing
4+
5+
We refer to Ethereum as the _root_ chain and zkEVM as the _child_ chain.
6+
7+
Below we provide the two basic functions used for _error passing_ in each of the two directions: L1 --> L2 and L2 --> L1.
8+
9+
**Message**
10+
11+
- From root to child
12+
13+
```jsx
14+
const bridgeTx = zkEvmClient.rootChainBridge.bridgeMessage(
15+
destinationNetwork: number,
16+
destinationAddress: string,
17+
forceUpdateGlobalExitRoot: boolean,
18+
permitData = '0x',
19+
option?: ITransactionOption
20+
);
21+
22+
const claimTx = zkEvmClient.childChainBridge.claimMessage(
23+
smtProof: string[],
24+
smtProofRollup: string[],
25+
globalIndex: string,
26+
mainnetExitRoot: string,
27+
rollupExitRoot: string,
28+
originNetwork: number,
29+
originTokenAddress: string,
30+
destinationNetwork: number,
31+
destinationAddress: string,
32+
amount: TYPE_AMOUNT,
33+
metadata: string,
34+
option: ITransactionOption
35+
);
36+
37+
// proof can be found from the proof gen API
38+
```
39+
40+
- From child to root
41+
42+
```jsx
43+
const bridgeTx = zkEvmClient.childChainBridge.bridgeMessage(
44+
destinationNetwork: number,
45+
destinationAddress: string,
46+
forceUpdateGlobalExitRoot: boolean,
47+
permitData = '0x',
48+
option?: ITransactionOption
49+
);
50+
51+
const claimTx = zkEvmClient.rootChainBridge.claimMessage(
52+
smtProof: string[],
53+
smtProofRollup: string[],
54+
globalIndex: string,
55+
mainnetExitRoot: string,
56+
rollupExitRoot: string,
57+
originNetwork: number,
58+
originTokenAddress: string,
59+
destinationNetwork: number,
60+
destinationAddress: string,
61+
amount: TYPE_AMOUNT,
62+
metadata: string,
63+
option: ITransactionOption
64+
);
65+
66+
// proof can be found from the proof gen API
67+
```
68+
69+
## Bridging customized ERC20 token
70+
71+
The existing zkEVM bridge uses the ERC-20 standard contract for creating wrapped tokens depending on the token's native network.
72+
73+
Often, organizations want to customise their wrapped tokens by extending some functionalities.
74+
75+
These functionalities could include: blacklisting, putting a cap on minting, or any sound auxiliary functionality.
76+
77+
This can be done by deploying adapter contracts that use the messaging layer of the bridge.
78+
79+
However, for the sake of maintaining consistency among wrapped tokens, strict standards must be followed when extending their functionalities.
80+
81+
## Standardizations
82+
83+
1. Adapter contracts need to implement the [Polygon bridge library](https://github.com/0xPolygonHermez/code-examples/blob/main/customERC20-bridge-example/contracts/base/PolygonERC20BridgeBase.sol) and expose `bridgeToken()` and `onMessageReceived()` functions.
84+
2. There should be two separate adapter contracts; `OriginChainBridgeAdapter` and `WrapperChainBridgeAdapter`.
85+
3. `bridgeToken` function should match the exact function signature and be similar to [this](https://github.com/maticnetwork/static/blob/master/network/mainnet/cherry/artifacts/zkevm/ZkEVMBridgeAdapter.json) ABI.
86+
87+
### Nice to have
88+
89+
Expose the following variables,
90+
91+
1. `originTokenAddress`: Address of the native token.
92+
2. `originTokenNetwork`: `networkId` of the chain to which the token is native.
93+
3. `wrappedTokenAddress`: Address of the wrapped token.
94+
95+
## What is an adapter?
96+
97+
An adapter is a wrapper contract that implements the [Polygon bridge library](https://github.com/0xPolygonHermez/code-examples/blob/main/customERC20-bridge-example/contracts/base/PolygonERC20BridgeBase.sol). An implementation example for ERC20 can be found [here](https://github.com/0xPolygonHermez/code-examples/blob/main/customERC20-bridge-example/contracts/lib/PolygonERC20BridgeLib.sol).
98+
99+
Ideally, the following adapter contracts are expected,
100+
101+
1. `OriginChainBridgeAdapter`
102+
2. `WrapperChainBridgeAdapter`
103+
104+
Irrespective of whether an ERC-20 token is Ethereum native (root chain) or ZkEvm native (child chain), an adapter contract should have the following functions (these are already part of the [library](https://github.com/0xPolygonHermez/code-examples/blob/main/customERC20-bridge-example/contracts/base/PolygonERC20BridgeBase.sol).
105+
106+
```solidity
107+
function bridgeToken(
108+
address destinationAddress,
109+
uint256 amount,
110+
bool forceUpdateGlobalExitRoot
111+
) external {}
112+
113+
function onMessageReceived(
114+
address originAddress,
115+
uint32 originNetwork,
116+
bytes memory data
117+
) external payable {}
118+
```
119+
120+
## How does it work?
121+
122+
`PolygonZkEVMBridge` is the main bridge contract. It exposes a `bridgeMessage()` function, which users can call in order to bridge messages from L1 to L2, or vice versa. The `claimMessage()` function can be called in the receiving chain to claim the sent message.
123+
124+
For example, a user who wants to bridge a message from Ethereum to zkEVM, can call `bridgeMessage()` in Ethereum and then call `claimMessage()` in zkEVM. Once the `claimMessage()` function is called, the bridge calls `onMessageReceived` in the destination address.
125+
126+
Adapter contracts are basically abstractions that uses `bridgeMessage()` to bridge and `onMessageReceived()` to process a `claimMessage()` in respective chains.
127+
128+
![Figure: Adapter contract](../../../img/learn/maticjs-adapter-contract-01.png)
129+
130+
## ERC-20 transfer
131+
132+
The transfer of ERC-20 tokens using each of the adapter contracts can be broken down as follows.
133+
134+
### OriginChainBridgeAdapter
135+
136+
The `bridgeToken()` function is called by the deployed adapter contract, to deposit an ERC-20 token from Ethereum to zkEVM.
137+
138+
The `onMessageReceived()` function is then called by the [PolygonZkEvmBridge.sol](https://github.com/0xPolygonHermez/zkevm-contracts/blob/main/contracts/PolygonZkEVMBridge.sol) contract when `claimMessage()` is called during withdrawal of tokens from zkEVM.
139+
140+
### WrapperChainBridgeAdapter
141+
142+
The `bridgeToken()` function is called by the deployed adapter contract to withdraw ERC20 from ZkEVM to Ethereum
143+
144+
The `onMessageReceived` function is called by the [PolygonZkEvmBridge.sol](https://github.com/0xPolygonHermez/zkevm-contracts/blob/main/contracts/PolygonZkEVMBridge.sol) contract when `claimMessage()` is called when tokens are deposited to ZkEVM.
145+
146+
### From Ethereum → zkEVM
147+
148+
1. Deploy your adapter contracts on both the root chain and the child chain. (Note the address, you’ll need it later!)
149+
2. Approve the tokens to be transferred by calling the `approve()` function (on the root token) with the address of the `originChainBridgeAdapter` and the token amount, as arguments.
150+
3. Proceed to call `bridgeToken()` while using as arguments: the recipient, amount, and setting `forceUpdateGlobalExitRoot` to `true` on the `originChainBridgeAdapter` in the root chain (i.e., Ethereum).
151+
4. Get the Merkle proof for this bridge transaction using the [proof api](https://proof-generator.polygon.technology/api/zkevm/testnet/merkle-proof?net_id=0&deposit_cnt=).
152+
5. Proceed to call `claimMessage()` with the respective arguments on the `PolygonZkEVMBridge.sol` contract in the child chain (i.e., zkEVM).
153+
154+
The bridge will call the `onMessageReceived` function in the `WrapperChainBridgeAdapter` contract. Which should ideally have the logic to mint wrapped tokens to the recipient.
155+
156+
Note: It is assumed, in the above steps, that the token being bridged is native to the root chain.
157+
158+
### From zkEVM → Ethereum
159+
160+
1. Deploy your adapter contracts on both the root chain and the child chain. (Note the address, you’ll need it later!)
161+
2. Approve the tokens to be transferred by calling the `approve()` function (on the wrapped token) with the address of the `wrapperChainBridgeAdapter` and the token amount as arguments.
162+
3. Proceed to call `bridgeToken()`, using as arguments: the recipient, amount, and setting `forceUpdateGlobalExitRoot` to `true` on the `WrapperChainBridgeAdapter` in the child chain (i.e., zkEVM). Ideally, this function should have the logic to burn the wrapped tokens.
163+
4. Get the Merkle proof for this bridge transaction using the [proof api](https://proof-generator.polygon.technology/api/zkevm/testnet/merkle-proof?net_id=0&deposit_cnt=).
164+
5. Proceed to call `claimMessage()` with the respective arguments on the `PolygonZkEVMBridge.sol` contract in the root chain (i.e., Ethereum).
165+
166+
The bridge will call the `onMessageReceived` function in the `OriginChainBridgeAdapter` contract. Which should Ideally have the logic to mint unwrapped tokens to the recipient.
167+
168+
Note: It is assumed, in the above steps, that the token being bridge is native to the root chain.
169+
170+
## How to list my token in the BridgeUI?
171+
172+
Note that it is important to follow standardizations for easy listing.
173+
174+
1. Add your token to this list [https://github.com/maticnetwork/polygon-token-list/blob/dev/src/tokens/zkevmPopularTokens.json]
175+
176+
Example:
177+
178+
```solidity
179+
{
180+
"chainId": 1101,
181+
"name": "Token Name",
182+
"symbol": "Token Symbol",
183+
"decimals": 6, // token decimal
184+
"address": "ZkEVM Address of the token",
185+
"logoURI": "Token logo url",
186+
"tags": ["zkevm", "stablecoin", "erc20, custom-zkevm-bridge"],
187+
"originTokenNetwork": 0, // 0 here is networkId of ethereum,
188+
"wrappedTokenNetwork": 1, // 1 here is networkId of zkEvm,
189+
"extensions": {
190+
"rootAddress": "Ethereum Address of the Token",
191+
"wrapperChainBridgeAdapter": "",
192+
"originChainBridgeAdapter": "",
193+
}
194+
},
195+
```
196+
Note: If the token is ethereum native then `originTokenNetwork` should be `0`. If the token is zkEVM native, then `originTokenNetwork` should be `1`. Similarly for the `wrappedTokenNetwork`.
197+
198+
2. Raise a PR 🚀
199+
200+
## How to use Matic.js to bridge using adapter contracts?
201+
202+
Deploy your `OriginChainBridgeAdapt` and `WrapperChainBridgeAdapter`.
203+
204+
Make sure you are using `matic.js version > 3.6.4`.
205+
206+
- Create an instance of the zkEVM client, passing the necessary parameters. Refer [here](./initialize.md) for more info.
207+
208+
```jsx
209+
const client = new ZkEvmClient();
210+
*await* client.init({})
211+
```
212+
213+
- Create an ERC-20 token instance which you would like to bridge,
214+
215+
```jsx
216+
*const* erc20Token = client.erc20("<tokenAddress>", "<isRootChain>", "<bridgeAdapterAddress>");
217+
```
218+
219+
### Bridge from Ethereum → zkEVM
220+
221+
1. **Deposit**
222+
223+
```jsx
224+
const depositTx = await erc20Token.depositCustomERC20("1000000000000000000", "recipent address",true);
225+
const txHash = await depositTx.getTransactionHash();
226+
console.log("Transaction Hash", txHash);
227+
```
228+
229+
2. **Claim Deposit**
230+
231+
```jsx
232+
const claimTx = await erc20.customERC20DepositClaim("<deposit tx hash>");
233+
const txHash = await claimTx.getTransactionHash();
234+
console.log("claimed txHash", ctxHash);
235+
```
236+
237+
### Bridge from zkEVM → Ethereum
238+
239+
1. **Withdraw**
240+
241+
```jsx
242+
const depositTx = await erc20Token.withdrawCustomERC20("1000000000000000000", "recipent address",true);
243+
const txHash = await depositTx.getTransactionHash();
244+
console.log("Transaction Hash", txHash);
245+
```
246+
247+
2. **Claim Deposit**
248+
249+
```jsx
250+
const claimTx = await erc20.customERC20WithdrawExit("<withdraw tx hash>");
251+
const txHash = await claimTx.getTransactionHash();
252+
console.log("claimed txHash", ctxHash);
253+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ nav:
455455
- zkEVM:
456456
- zkEVM client: tools/matic-js/zkevm/initialize.md
457457
- ERC20: tools/matic-js/zkevm/erc20.md
458+
- Message: tools/matic-js/zkevm/message.md
458459
- Common methods: tools/matic-js/zkevm/common-methods.md
459460
- Storage:
460461
- IPFS: tools/storage/ipfs.md

0 commit comments

Comments
 (0)