---
# System prepended metadata

title: ZKSYNC ERA

---

## Message传递

### L1 -> L2

The Mailbox only cares about transferring information from L2 to L1 and the other way but does not hold or transfer any assets (ETH, ERC20 tokens, or NFTs)

Mailbox只关心从L2到L1的消息传递，不持有或转移任何资产。

目前只用于L1 -> L2层的消息传递，或者用于实施多层协议。与L1 -> L2 message传递相关的函数为：

```
requestL2Transaction：L1至L2的ETH充值用到此方法。

l2TransactionBaseCost：估计从L1请求L2交易的ETH成本。

serializeL2Transaction：
```

> 注意：每一笔L1 -> L2层的交易，系统程序都会发送一条固定格式的L2 -> L1 log

实际操作：

L1至L2的桥合约一层牵涉两个合约，核心合约依旧是`MailBox`合约，核心方法为`requestL2Transaction`方法，最后会打印`NewPriorityRequest`事件。

| layer |    contractName    | contractAddress                                              |
| :---: | :----------------: | ------------------------------------------------------------ |
|  L1   | L1ERC20BridgeProxy | [0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063](https://etherscan.io/address/0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063#code) |
|  L1   | L1ERC20BridgeImpl  | [0x7e5E66B01fe43293545eaB98ec4D31784A5Efa84](https://etherscan.io/address/0x7e5E66B01fe43293545eaB98ec4D31784A5Efa84#code) |
|  L1   | MailboxFacetProxy  | [0x32400084C286CF3E17e7B677ea9583e60a000324](https://etherscan.io/address/0x32400084c286cf3e17e7b677ea9583e60a000324) |
|  L1   |  MailboxFacetImpl  | [0xb2097DBe4410B538a45574B1FCD767E2303c7867](https://etherscan.io/address/0xb2097dbe4410b538a45574b1fcd767e2303c7867) |

示例交易：[0x4f82205070222bc3a2149a73791f970eba511f421b1ed80daf0464cc0b0dfdec](https://etherscan.io/tx/0x4f82205070222bc3a2149a73791f970eba511f421b1ed80daf0464cc0b0dfdec)

bridge合约`deposit`方法通过调用Mailbox合约`requestL2Transaction`方法最后打印`NewPriorityRequest`事件完成交易。



### L2 -> L1

L2至L1的传输只基于information传输，不基于交易传输。

一个特殊的`zkEVM`操作码会将所有`l2ToL1Log`存储在 L2 block 中。当`validator`发送一个`L2 block to the L1`时，会发送所有的`l2ToL1Logs`。不久之后，用户能够在`L1`上看到自己的`l2ToL1logs`和证明。

在`L1`，每个`L2` block，都会计算出一个` Merkle root`，因此，用户可以为每一个`l2ToL1Logs`提供`Merkle proof`。

从官方给出的示例中，在L2层的`Receive`合约中，调用`proveL2MessageInclusion`方法。

```solidity
    /// @notice Prove that a specific arbitrary-length message was sent in a specific L2 block number
    /// @param _blockNumber The executed L2 block number in which the message appeared
    /// @param _index The position in the L2 logs Merkle tree of the l2Log that was sent with the message
    /// @param _message Information about the sent message: sender address, the message itself, tx index in the L2 block where the message was sent
    /// @param _proof Merkle proof for inclusion of L2 log that was sent with the message
    /// @return Whether the proof is valid
    function proveL2MessageInclusion(
        uint256 _blockNumber,
        uint256 _index,
        L2Message memory _message,
        bytes32[] calldata _proof
    ) public view returns (bool) {
        return _proveL2LogInclusion(_blockNumber, _index, _L2MessageToLog(_message), _proof);
    }
```

> L2至L1不能直接通信，需要经过zkSync服务器。首先在L2发起交易，经过服务器发起交易调用`MailboxFacet`合约`proveL2MessageInclusion`函数.其验证方式为merkle树验证二层某一区块内有需要验证的log。

```solidity
    bool success = zksync.proveL2MessageInclusion(
      _l2BlockNumber,
      _index,
      message,
      _proof
    );
    require(success, "Failed to prove message inclusion");
```





L2资金提取至L1有三种方式：

- Withdraw

  此种模式为正常交易模式，适用于有自己账户并且拥有私钥。

- ForcedExit

  此模式依旧为正常交易模式，适用于无法设置签名密钥的账户（智能合约）提款。

- FullExit

  此种模式为“优先操作”模式，此种模式从L1发起交易，此种模式下，即使节点停止工作，用户也可以提取资金。适用于遭到审查用户直接提取资金。

| layer | contractName |                       contractAddress                        |
| :---: | :----------: | :----------------------------------------------------------: |
|  L2   |  L2EthToken  | [0x000000000000000000000000000000000000800A](https://goerli.explorer.zksync.io/address/0x000000000000000000000000000000000000800A#contract) |
|  L1   |  未开源合约  | [0x4cCF429019abAa7e06AAB09Dbc2e05f33C11429c](https://goerli.etherscan.io/address/0x4ccf429019abaa7e06aab09dbc2e05f33c11429c#code) |

以Withdraw方法为例：

L2层发起Withdraw交易：[0x89cf50c8af20043514a30e99303a1e9f4ee791edcbed4b03993a86ce56c9197a](https://goerli.explorer.zksync.io/tx/0x89cf50c8af20043514a30e99303a1e9f4ee791edcbed4b03993a86ce56c9197a)

交易调用Withdraw方法，主要代码为：

```solidity
    /// @notice Initiate the ETH withdrawal, funds will be available to claim on L1 `finalizeEthWithdrawal` method.
    /// @param _l1Receiver The address on L1 to receive the funds.
    /// @dev The function accepts the `msg.value`. Since this contract holds the mapping of all ether
    /// balances of the system, the sent `msg.value` is added to the `this` balance before the call.
    /// So the balance of `address(this)` is always bigger or equal to the `msg.value`!
    function withdraw(address _l1Receiver) external payable override {
        uint256 amount = msg.value;

        // Silent burning of the ether
        unchecked {
            // This is safe, since this contract holds the ether balances, and if user
            // send a `msg.value` it will be added to the contract (`this`) balance.
            balance[address(this)] -= amount;
            totalSupply -= amount;
        }

        // Send the L2 log, a user could use it as proof of the withdrawal
        bytes memory message = _getL1WithdrawMessage(_l1Receiver, amount);
        L1_MESSENGER_CONTRACT.sendToL1(message);

        emit Withdrawal(msg.sender, _l1Receiver, amount);
    }

    /// @dev Get the message to be sent to L1 to initiate a withdrawal.
    function _getL1WithdrawMessage(address _to, uint256 _amount) internal pure returns (bytes memory) {
        return abi.encodePacked(IMailbox.finalizeEthWithdrawal.selector, _to, _amount);
    }
```

二层发起交易，从Goerli链上合约转移ETH至个人账户

示例交易：[0x21016f74e2cdc6e746815452e264ec059521ba943b3486a8bc235156b0aac2d2](https://goerli.etherscan.io/tx/0x21016f74e2cdc6e746815452e264ec059521ba943b3486a8bc235156b0aac2d2)

此合约并未开源，仅知道调用`finalizeWithdrawals(tuple[] requests)`函数。此函数在L1ERC20Bridge合约中也有出现，出现形式为`finalizeWithdrawal`,依旧为Merkle tree 验证log形式。

```solidity
    /// @notice Finalize the withdrawal and release funds
    /// @param _l2BlockNumber The L2 block number where the withdrawal was processed
    /// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message
    /// @param _l2TxNumberInBlock The L2 transaction number in a block, in which the log was sent
    /// @param _message The L2 withdraw data, stored in an L2 -> L1 message
    /// @param _merkleProof The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization
    function finalizeWithdrawal(
        uint256 _l2BlockNumber,
        uint256 _l2MessageIndex,
        uint16 _l2TxNumberInBlock,
        bytes calldata _message,
        bytes32[] calldata _merkleProof
    ) external nonReentrant senderCanCallFunction(allowList) {}
```

## 

## Github库

git@github.com:matter-labs/v2-testnet-contracts.git

git@github.com:matter-labs/era-contracts.git



#### NFT 跨链

Goerli： 0x23f59730F2416078546dfDE95CA5A8Ec6C4272f4

L2:0x1d3E15C85552F8B224125edb28D5180a9f5Cabc3

MInt NFT L2: [0x0a1b702b1021ede69ee8cc528e0cdce1247135e5958c1c850cd1d1d3448c7981](https://goerli.explorer.zksync.io/tx/0x0a1b702b1021ede69ee8cc528e0cdce1247135e5958c1c850cd1d1d3448c7981)

WithDraw NFT to L1: [0xcfdbd4ce95200144cfd386f558a3615cf430f642c849358271b92718ef3ba9ab](https://goerli.explorer.zksync.io/tx/0xcfdbd4ce95200144cfd386f558a3615cf430f642c849358271b92718ef3ba9ab)



