## 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)