Skip to content

Commit

Permalink
Merge pull request #11 from zkLinkProtocol/issue_8
Browse files Browse the repository at this point in the history
update initialization
  • Loading branch information
zkbenny authored Feb 2, 2024
2 parents 146114c + df4f0be commit 8b38c0e
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 84 deletions.
File renamed without changes.
73 changes: 56 additions & 17 deletions contracts/Arbitrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/se
import {DoubleEndedQueueUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/structs/DoubleEndedQueueUpgradeable.sol";
import {IArbitrator} from "./interfaces/IArbitrator.sol";
import {IL1Gateway} from "./interfaces/IL1Gateway.sol";
import {IAdmin} from "./zksync/l1-contracts/zksync/interfaces/IAdmin.sol";
import {IZkSync} from "./zksync/l1-contracts/zksync/interfaces/IZkSync.sol";
import "./zksync/l1-contracts/zksync/Storage.sol";

/// @title Arbitrator contract
/// @author zk.link
Expand All @@ -16,45 +19,81 @@ contract Arbitrator is IArbitrator, OwnableUpgradeable, UUPSUpgradeable, Reentra

/// @dev The gateway for sending message from ethereum to primary chain
IL1Gateway public primaryChainGateway;

/// @dev The gateway for sending message from ethereum to secondary chain
mapping(IL1Gateway => bool) public secondaryChainGateways;

/// @dev A message hash queue waiting to forward to all secondary chains
DoubleEndedQueueUpgradeable.Bytes32Deque public primaryChainMessageHashQueue;

/// @dev A message hash queue waiting to forward to primary chain
mapping(IL1Gateway => DoubleEndedQueueUpgradeable.Bytes32Deque) public secondaryChainMessageHashQueues;

/// @notice List of permitted relayers
mapping(address relayerAddress => bool isRelayer) public relayers;

/// @notice Primary chain gateway init
event InitPrimaryChain(IL1Gateway gateway);
/// @notice SecondaryChain's status changed
event SecondaryChainStatusUpdate(IL1Gateway gateway, bool isActive);
/// @notice Relayer's status changed
event RelayerStatusUpdate(address relayer, bool isActive);
/// @notice Validator's status changed
event ValidatorStatusUpdate(IL1Gateway gateway, address validatorAddress, bool isActive);
/// @notice Fee params for L1->L2 transactions changed
event NewFeeParams(IL1Gateway gateway, FeeParams newFeeParams);

/// @notice Checks if relayer is active
modifier onlyRelayer() {
require(relayers[msg.sender], "Not relayer"); // relayer is not active
_;
}

function initialize(
IL1Gateway _primaryChainGateway,
IL1Gateway[] memory _secondaryChainGateways,
address[] memory _relayers
) external initializer {
function initialize() external initializer {
__Ownable_init();
__UUPSUpgradeable_init();
__ReentrancyGuard_init();

primaryChainGateway = _primaryChainGateway;
for(uint i = 0; i < _secondaryChainGateways.length; ++i) {
secondaryChainGateways[_secondaryChainGateways[i]] = true;
}
for(uint i = 0; i < _relayers.length; ++i) {
relayers[_relayers[i]] = true;
}
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

/// @dev Set primary chain
function setPrimaryChainGateway(IL1Gateway _gateway) external onlyOwner {
require(address(primaryChainGateway) == address(0), "Duplicate init primary chain gateway");
primaryChainGateway = _gateway;
emit InitPrimaryChain(_gateway);
}

/// @dev Set secondary chain
function setSecondaryChainGateway(IL1Gateway _gateway, bool _active, bytes memory _adapterParams) external payable onlyOwner {
require(_gateway != primaryChainGateway, "Invalid secondary chain gateway");
secondaryChainGateways[_gateway] = _active;
bytes memory callData = abi.encodeCall(IZkSync.setSecondaryChainGateway, (address(_gateway), _active));
// Forward fee to send message
primaryChainGateway.sendMessage{value: msg.value}(0, callData, _adapterParams);
emit SecondaryChainStatusUpdate(_gateway, _active);
}

/// @dev Set relayer
function setRelayer(address _relayer, bool _active) external onlyOwner {
relayers[_relayer] = _active;
emit RelayerStatusUpdate(_relayer, _active);
}

/// @dev Set validator for a chain
function setValidator(IL1Gateway _gateway, address _validator, bool _active, bytes memory _adapterParams) external payable onlyOwner {
require(_gateway == primaryChainGateway || secondaryChainGateways[_gateway], "Invalid chain gateway");
bytes memory callData = abi.encodeCall(IAdmin.setValidator, (_validator, _active));
// Forward fee to send message
_gateway.sendMessage{value: msg.value}(0, callData, _adapterParams);
emit ValidatorStatusUpdate(_gateway, _validator, _active);
}

/// @dev Change fee params for a chain
function changeFeeParams(IL1Gateway _gateway, FeeParams calldata _newFeeParams, bytes memory _adapterParams) external payable onlyOwner {
require(_gateway == primaryChainGateway || secondaryChainGateways[_gateway], "Invalid chain gateway");
bytes memory callData = abi.encodeCall(IAdmin.changeFeeParams, (_newFeeParams));
// Forward fee to send message
_gateway.sendMessage{value: msg.value}(0, callData, _adapterParams);
emit NewFeeParams(_gateway, _newFeeParams);
}

function receiveMessage(uint256 _value, bytes memory _callData) external payable {
require(msg.value == _value, "Invalid msg value");
// store message hash for forwarding
Expand Down
60 changes: 47 additions & 13 deletions contracts/ZkLink.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {AddressAliasHelper} from "./zksync/l1-contracts/vendor/AddressAliasHelpe
import {IZkLink} from "./interfaces/IZkLink.sol";
import {IL2Gateway} from "./interfaces/IL2Gateway.sol";
import {IMailbox, TxStatus} from "./zksync/l1-contracts/zksync/interfaces/IMailbox.sol";
import {IAdmin} from "./zksync/l1-contracts/zksync/interfaces/IAdmin.sol";
import {IZkSync} from "./zksync/l1-contracts/zksync/interfaces/IZkSync.sol";
import {Merkle} from "./zksync/l1-contracts/zksync/libraries/Merkle.sol";
import "./zksync/l1-contracts/zksync/Storage.sol";
Expand All @@ -19,15 +20,7 @@ import "./zksync/l1-contracts/common/L2ContractAddresses.sol";

/// @title ZkLink contract
/// @author zk.link
contract ZkLink is IZkLink, IMailbox, OwnableUpgradeable, UUPSUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable {
/// @dev The sync status for priority op
/// @param hash The cumulative canonicalTxHash
/// @param amount The cumulative l2 value
struct SyncStatus {
bytes32 hash;
uint256 amount;
}

contract ZkLink is IZkLink, IMailbox, IAdmin, OwnableUpgradeable, UUPSUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable {
/// @notice The gateway is used for communicating with L1
IL2Gateway public gateway;
/// @notice List of permitted validators
Expand All @@ -44,7 +37,7 @@ contract ZkLink is IZkLink, IMailbox, OwnableUpgradeable, UUPSUpgradeable, Reent
/// @dev The total number of synced priority operations
uint256 public totalSyncedPriorityTxs;
/// @dev The sync status for each priority operation
mapping(uint256 priorityOpId => SyncStatus) public priorityOpSyncStatus;
mapping(uint256 priorityOpId => SecondaryChainSyncStatus) public priorityOpSyncStatus;
/// @notice Total number of executed batches i.e. batches[totalBatchesExecuted] points at the latest executed batch
/// (batch 0 is genesis)
uint256 public totalBatchesExecuted;
Expand All @@ -53,9 +46,21 @@ contract ZkLink is IZkLink, IMailbox, OwnableUpgradeable, UUPSUpgradeable, Reent
/// @dev Stored the l2 tx hash map from secondary chain to primary chain
mapping(bytes32 l2TxHash => bytes32 primaryChainL2TxHash) public l2TxHashMap;

/// @notice Gateway init
event InitGateway(IL2Gateway gateway);
/// @notice Contract's permit status changed
event ContractAllowStatusUpdate(address contractAddress, bool isPermit);
/// @notice Validator's status changed
event ValidatorStatusUpdate(address validatorAddress, bool isActive);
/// @notice Fee params for L1->L2 transactions changed
event NewFeeParams(FeeParams oldFeeParams, FeeParams newFeeParams);
/// @notice New priority request event. Emitted when a request is placed into the priority queue
event NewPriorityRequest(uint256 priorityOpId, ForwardL2Request l2Request);
/// @notice Emitted send sync status to primary chain.
event SyncL2Requests(uint256 totalSyncedPriorityTxs, bytes32 syncHash, uint256 forwardEthAmount);
/// @notice Emitted when receive batch root from primary chain.
event SyncBatchRoot(uint256 batchNumber, bytes32 l2LogsRootHash);
/// @notice Emitted when receive l2 tx hash from primary chain.
event SyncL2TxHash(bytes32 l2TxHash, bytes32 primaryChainL2TxHash);

/// @notice Check if msg sender is gateway
Expand Down Expand Up @@ -89,6 +94,35 @@ contract ZkLink is IZkLink, IMailbox, OwnableUpgradeable, UUPSUpgradeable, Reent
_unpause();
}

/// @dev Init gateway, can only be called by the owner
function setGateway(IL2Gateway _gateway) external onlyOwner {
require(address(gateway) == address(0), "Duplicate init gateway");
gateway = _gateway;
emit InitGateway(_gateway);
}

/// @dev Update the permit status of contract, can only be called by the owner
function setAllowList(address _contractAddress, bool _permitted) external onlyOwner {
allowLists[_contractAddress] = _permitted;
emit ContractAllowStatusUpdate(_contractAddress, _permitted);
}

function setValidator(address _validator, bool _active) external onlyGateway {
validators[_validator] = _active;
emit ValidatorStatusUpdate(_validator, _active);
}

function changeFeeParams(FeeParams calldata _newFeeParams) external onlyGateway {
// Double checking that the new fee params are valid, i.e.
// the maximal pubdata per batch is not less than the maximal pubdata per priority transaction.
require(_newFeeParams.maxPubdataPerBatch >= _newFeeParams.priorityTxMaxPubdata, "n6");

FeeParams memory oldFeeParams = feeParams;
feeParams = _newFeeParams;

emit NewFeeParams(oldFeeParams, _newFeeParams);
}

function l2TransactionBaseCost(
uint256 _gasPrice,
uint256 _l2GasLimit,
Expand Down Expand Up @@ -159,7 +193,7 @@ contract ZkLink is IZkLink, IMailbox, OwnableUpgradeable, UUPSUpgradeable, Reent
canonicalTxHash = keccak256(abi.encode(request));

// Accumulate sync status
SyncStatus memory syncStatus;
SecondaryChainSyncStatus memory syncStatus;
if (_totalPriorityTxs == 0) {
syncStatus.hash = canonicalTxHash;
syncStatus.amount = _l2Value;
Expand Down Expand Up @@ -221,11 +255,11 @@ contract ZkLink is IZkLink, IMailbox, OwnableUpgradeable, UUPSUpgradeable, Reent
require(_newTotalSyncedPriorityTxs <= totalPriorityTxs && _newTotalSyncedPriorityTxs > totalSyncedPriorityTxs, "Invalid newTotalSyncedPriorityTxs");

// Forward eth amount is the difference of two accumulate amount
SyncStatus memory lastSyncStatus;
SecondaryChainSyncStatus memory lastSyncStatus;
if (totalSyncedPriorityTxs > 0) {
lastSyncStatus = priorityOpSyncStatus[totalSyncedPriorityTxs - 1];
}
SyncStatus memory currentSyncStatus = priorityOpSyncStatus[_newTotalSyncedPriorityTxs - 1];
SecondaryChainSyncStatus memory currentSyncStatus = priorityOpSyncStatus[_newTotalSyncedPriorityTxs - 1];
uint256 forwardAmount = currentSyncStatus.amount - lastSyncStatus.amount;

// Update synced priority txs
Expand Down
9 changes: 5 additions & 4 deletions contracts/gateway/zksync/ZkSyncL1Gateway.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.0;

import {IZkSync} from "../../interfaces/zksync/IZkSync.sol";
import {IMailbox} from "../../zksync/l1-contracts/zksync/interfaces/IMailbox.sol";
import {IArbitrator} from "../../interfaces/IArbitrator.sol";
import {L1BaseGateway} from "../L1BaseGateway.sol";
import {IZkSyncL1Gateway} from "../../interfaces/zksync/IZkSyncL1Gateway.sol";
import {IZkSyncL2Gateway} from "../../interfaces/zksync/IZkSyncL2Gateway.sol";
import {BaseGateway} from "../BaseGateway.sol";
import "../../zksync/l1-contracts/zksync/Storage.sol";

contract ZkSyncL1Gateway is IZkSyncL1Gateway, L1BaseGateway, BaseGateway {
/// @notice ZkSync message service on local chain
IZkSync public messageService;
IMailbox public messageService;

/// @dev A mapping L2 batch number => message number => flag
/// @dev Used to indicate that zkSync L2 -> L1 message was already processed
Expand All @@ -20,7 +21,7 @@ contract ZkSyncL1Gateway is IZkSyncL1Gateway, L1BaseGateway, BaseGateway {
receive() external payable {
}

function initialize(IArbitrator _arbitrator, IZkSync _messageService) external initializer {
function initialize(IArbitrator _arbitrator, IMailbox _messageService) external initializer {
__L1BaseGateway_init(_arbitrator);
__BaseGateway_init();

Expand All @@ -36,7 +37,7 @@ contract ZkSyncL1Gateway is IZkSyncL1Gateway, L1BaseGateway, BaseGateway {
function finalizeMessage(uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes memory _message, bytes32[] calldata _merkleProof) external nonReentrant {
require(!isMessageFinalized[_l2BatchNumber][_l2MessageIndex], "Message was finalized");

IZkSync.L2Message memory l2ToL1Message = IZkSync.L2Message({
L2Message memory l2ToL1Message = L2Message({
txNumberInBatch: _l2TxNumberInBatch,
sender: remoteGateway,
data: _message
Expand Down
40 changes: 0 additions & 40 deletions contracts/interfaces/zksync/IZkSync.sol

This file was deleted.

8 changes: 8 additions & 0 deletions contracts/zksync/l1-contracts/zksync/Storage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,11 @@ struct FeeParams {
uint32 priorityTxMaxPubdata;
uint64 minimalL2GasPrice;
}

/// @dev The sync status for priority op of secondary chain
/// @param hash The cumulative canonicalTxHash
/// @param amount The cumulative l2 value
struct SecondaryChainSyncStatus {
bytes32 hash;
uint256 amount;
}
10 changes: 0 additions & 10 deletions contracts/zksync/l1-contracts/zksync/interfaces/IAdmin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ import {FeeParams} from "../Storage.sol";
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IAdmin {
/// @notice Starts the transfer of governor rights. Only the current governor can propose a new pending one.
/// @notice New governor can accept governor rights by calling `acceptGovernor` function.
/// @param _newPendingGovernor Address of the new governor
function setPendingGovernor(address _newPendingGovernor) external;

/// @notice Starts the transfer of admin rights. Only the current governor or admin can propose a new pending one.
/// @notice New admin can accept admin rights by calling `acceptAdmin` function.
/// @param _newPendingAdmin Address of the new admin
function setPendingAdmin(address _newPendingAdmin) external;

/// @notice Change validator status (active or not active)
/// @param _validator Validator address
/// @param _active Active flag
Expand Down
5 changes: 5 additions & 0 deletions contracts/zksync/l1-contracts/zksync/interfaces/IZkSync.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
pragma solidity ^0.8.0;

interface IZkSync {
/// @notice Update secondary chain status
/// @param _gateway The secondary chain gateway
/// @param _active Active flag
function setSecondaryChainGateway(address _gateway, bool _active) external;

/// @notice Receive sync status from secondary chain
/// @param _secondaryChainGateway The secondary chain gateway address
/// @param _newTotalSyncedPriorityTxs New sync point
Expand Down

0 comments on commit 8b38c0e

Please sign in to comment.