Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mantle #108

Merged
merged 4 commits into from
May 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions contracts/ZkLink.sol
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {AddressAliasHelper} from "./zksync/l1-contracts/vendor/AddressAliasHelper.sol";
import {IZkLink} from "./interfaces/IZkLink.sol";
import {IL2Gateway} from "./interfaces/IL2Gateway.sol";
@@ -35,6 +37,7 @@ contract ZkLink is
PausableUpgradeable
{
using UncheckedMath for uint256;
using SafeERC20 for IERC20;

/// @dev The forward request type hash
bytes32 public constant FORWARD_REQUEST_TYPE_HASH =
@@ -45,9 +48,6 @@ contract ZkLink is
/// @dev The length of withdraw message sent to secondary chain
uint256 private constant L2_WITHDRAW_MESSAGE_LENGTH = 108;

/// @dev Whether eth is the gas token
bool public immutable IS_ETH_GAS_TOKEN;

/// @notice The gateway is used for communicating with L1
IL2Gateway public gateway;
/// @notice List of permitted validators
@@ -148,8 +148,7 @@ contract ZkLink is
_;
}

constructor(bool _isEthGasToken) {
IS_ETH_GAS_TOKEN = _isEthGasToken;
constructor() {
_disableInitializers();
}

@@ -275,7 +274,7 @@ contract ZkLink is
address _refundRecipient
) external payable nonReentrant whenNotPaused returns (bytes32 canonicalTxHash) {
// Disable l2 value if eth is not the gas token
if (!IS_ETH_GAS_TOKEN) {
if (!gateway.isEthGasToken()) {
require(_l2Value == 0, "Not allow l2 value");
}
// Change the sender address if it is a smart contract to prevent address collision between L1 and L2.
@@ -365,7 +364,6 @@ contract ZkLink is
bytes calldata _message,
bytes32[] calldata _merkleProof
) external nonReentrant {
require(IS_ETH_GAS_TOKEN, "Not allow eth withdraw");
require(!isEthWithdrawalFinalized[_l2BatchNumber][_l2MessageIndex], "jj");

L2Message memory l2ToL1Message = L2Message({
@@ -461,7 +459,9 @@ contract ZkLink is
bytes32 _l2LogsRootHash,
uint256 _forwardEthAmount
) external payable onlyGateway {
require(msg.value == _forwardEthAmount, "Invalid forward amount");
if (gateway.isEthGasToken()) {
require(msg.value == _forwardEthAmount, "Invalid forward amount");
}
// Allows repeated sending of the forward amount of the batch
if (_batchNumber > totalBatchesExecuted) {
totalBatchesExecuted = _batchNumber;
@@ -477,7 +477,9 @@ contract ZkLink is
uint256 _forwardEthAmount
) external payable onlyGateway {
require(_toBatchNumber >= _fromBatchNumber, "Invalid range");
require(msg.value == _forwardEthAmount, "Invalid forward amount");
if (gateway.isEthGasToken()) {
require(msg.value == _forwardEthAmount, "Invalid forward amount");
}
bytes32 range = keccak256(abi.encodePacked(_fromBatchNumber, _toBatchNumber));
rangeBatchRootHashes[range] = _rangeBatchRootHash;
emit SyncRangeBatchRoot(_fromBatchNumber, _toBatchNumber, _rangeBatchRootHash, _forwardEthAmount);
@@ -644,12 +646,16 @@ contract ZkLink is
/// @notice Transfer ether from the contract to the receiver
/// @dev Reverts only if the transfer call failed
function _withdrawFunds(address _to, uint256 _amount) internal {
bool callSuccess;
// Low-level assembly call, to avoid any memory copying (save gas)
assembly {
callSuccess := call(gas(), _to, _amount, 0, 0, 0, 0)
if (gateway.isEthGasToken()) {
bool callSuccess;
// Low-level assembly call, to avoid any memory copying (save gas)
assembly {
callSuccess := call(gas(), _to, _amount, 0, 0, 0, 0)
}
require(callSuccess, "pz");
} else {
SafeERC20.safeTransfer(gateway.ethToken(), _to, _amount);
}
require(callSuccess, "pz");
}

function hashForwardL2Request(ForwardL2Request memory _request) internal pure returns (bytes32) {
4 changes: 1 addition & 3 deletions contracts/dev-contracts/DummyZkLink.sol
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ import {IL2Gateway} from "../interfaces/IL2Gateway.sol";
import {IZkLink} from "../interfaces/IZkLink.sol";

contract DummyZkLink is IZkLink, OwnableUpgradeable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
bool public immutable IS_ETH_GAS_TOKEN;
IL2Gateway public gateway;

event ReceiveBatchRoot(uint256 batchNumber, bytes32 l2LogsRootHash, uint256 forwardEthAmount);
@@ -26,8 +25,7 @@ contract DummyZkLink is IZkLink, OwnableUpgradeable, UUPSUpgradeable, Reentrancy
_;
}

constructor(bool _isEthGasToken) {
IS_ETH_GAS_TOKEN = _isEthGasToken;
constructor() {
_disableInitializers();
}

9 changes: 9 additions & 0 deletions contracts/gateway/L2BaseGateway.sol
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
pragma solidity ^0.8.0;

import {IL2Gateway} from "../interfaces/IL2Gateway.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

abstract contract L2BaseGateway is IL2Gateway {
/// @notice The zkLink contract
@@ -23,4 +24,12 @@ abstract contract L2BaseGateway is IL2Gateway {
constructor(address _zkLink) {
ZKLINK = _zkLink;
}

function isEthGasToken() external pure virtual returns (bool) {
return true;
}

function ethToken() external pure virtual returns (IERC20) {
return IERC20(address(0));
}
}
38 changes: 38 additions & 0 deletions contracts/gateway/optimism/MantleL2Gateway.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;

import {OptimismL2Gateway} from "./OptimismL2Gateway.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract MantleL2Gateway is OptimismL2Gateway {
using SafeERC20 for IERC20;

/// @dev The ETH token deployed on Mantle
IERC20 private constant BVM_ETH = IERC20(0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111);

constructor(address _zkLink) OptimismL2Gateway(_zkLink) {
_disableInitializers();
}

function isEthGasToken() external pure override returns (bool) {
return false;
}

function ethToken() external pure override returns (IERC20) {
return BVM_ETH;
}

function claimMessageCallback(
uint256 _ethValue,
bytes calldata _callData
) external payable override onlyMessageService onlyRemoteGateway {
if (_ethValue > 0) {
// Mantle L2CrossDomainMessenger will approve l2 gateway before the callback in `relayMessage`
SafeERC20.safeTransferFrom(BVM_ETH, address(MESSAGE_SERVICE), address(ZKLINK), _ethValue);
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = ZKLINK.call{value: 0}(_callData);
require(success, "Call zkLink failed");
}
}
2 changes: 1 addition & 1 deletion contracts/gateway/optimism/OptimismL2Gateway.sol
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ contract OptimismL2Gateway is L2BaseGateway, OptimismGateway {
function claimMessageCallback(
uint256 _value,
bytes calldata _callData
) external payable onlyMessageService onlyRemoteGateway {
) external payable virtual onlyMessageService onlyRemoteGateway {
require(msg.value == _value, "Invalid value");

// solhint-disable-next-line avoid-low-level-calls
5 changes: 5 additions & 0 deletions contracts/interfaces/IL2Gateway.sol
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
pragma solidity ^0.8.0;

import {IGateway} from "./IGateway.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IL2Gateway is IGateway {
/// @notice Emit when sending a message
@@ -11,4 +12,8 @@ interface IL2Gateway is IGateway {
/// @param _value The msg value
/// @param _callData The call data
function sendMessage(uint256 _value, bytes calldata _callData) external payable;

function isEthGasToken() external view returns (bool);

function ethToken() external view returns (IERC20);
}
30 changes: 2 additions & 28 deletions script/ChainConfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"ETHEREUM": {
"eth": true
},
"ZKSYNC": {
"eth": true,
"l2Gateway": {
"contractName": "ZkSyncL2Gateway",
"constructParams": [],
@@ -17,7 +15,6 @@
}
},
"SCROLL": {
"eth": true,
"l2Gateway": {
"contractName": "ScrollL2Gateway",
"constructParams": ["0x781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC"],
@@ -31,7 +28,6 @@
}
},
"LINEA": {
"eth": true,
"l2Gateway": {
"contractName": "LineaL2Gateway",
"constructParams": ["0x508Ca82Df566dCD1B0DE8296e70a96332cD644ec"],
@@ -45,7 +41,6 @@
}
},
"ZKPOLYGON": {
"eth": true,
"l2Gateway": {
"contractName": "ZkPolygonL2Gateway",
"constructParams": ["0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe"],
@@ -59,7 +54,6 @@
}
},
"ARBITRUM": {
"eth": true,
"l2Gateway": {
"contractName": "ArbitrumL2Gateway",
"constructParams": [],
@@ -73,7 +67,6 @@
}
},
"OPTIMISM": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -87,7 +80,6 @@
}
},
"MANTA": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -101,9 +93,8 @@
}
},
"MANTLE": {
"eth": false,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"contractName": "MantleL2Gateway",
"constructParams": [],
"initializeParams": []
},
@@ -115,7 +106,6 @@
}
},
"BLAST": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -129,7 +119,6 @@
}
},
"BASE": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -143,7 +132,6 @@
}
},
"METIS": {
"eth": false,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -156,14 +144,9 @@
"initializeParams": []
}
},
"GOERLI": {
"eth": true
},
"SEPOLIA": {
"eth": true
},
"ZKSYNCTEST": {
"eth": true,
"l2Gateway": {
"contractName": "ZkSyncL2Gateway",
"constructParams": [],
@@ -177,7 +160,6 @@
}
},
"SCROLLTEST": {
"eth": true,
"l2Gateway": {
"contractName": "ScrollL2Gateway",
"constructParams": ["0xBa50f5340FB9F3Bd074bD638c9BE13eCB36E603d"],
@@ -191,7 +173,6 @@
}
},
"LINEATEST": {
"eth": true,
"l2Gateway": {
"contractName": "LineaL2Gateway",
"constructParams": ["0x971e727e956690b9957be6d51Ec16E73AcAC83A7"],
@@ -205,7 +186,6 @@
}
},
"ZKPOLYGONTEST": {
"eth": true,
"l2Gateway": {
"contractName": "ZkPolygonL2Gateway",
"constructParams": ["0xF6BEEeBB578e214CA9E23B0e9683454Ff88Ed2A7"],
@@ -219,7 +199,6 @@
}
},
"ARBITRUMTEST": {
"eth": true,
"l2Gateway": {
"contractName": "ArbitrumL2Gateway",
"constructParams": [],
@@ -233,7 +212,6 @@
}
},
"OPTIMISMTEST": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -247,7 +225,6 @@
}
},
"MANTATEST": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -261,9 +238,8 @@
}
},
"MANTLETEST": {
"eth": false,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"contractName": "MantleL2Gateway",
"constructParams": [],
"initializeParams": []
},
@@ -275,7 +251,6 @@
}
},
"BLASTTEST": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
@@ -289,7 +264,6 @@
}
},
"BASETEST": {
"eth": true,
"l2Gateway": {
"contractName": "OptimismL2Gateway",
"constructParams": [],
Loading
Loading