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

Gateway compatibility #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
61 changes: 38 additions & 23 deletions l1-contracts/src/ProtocolUpgradeHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
pragma solidity 0.8.24;

import {IZKsyncEra} from "./interfaces/IZKsyncEra.sol";
import {IStateTransitionManager} from "./interfaces/IStateTransitionManager.sol";
import {IChainTypeManager} from "./interfaces/IChainTypeManager.sol";
import {IBridgeHub} from "./interfaces/IBridgeHub.sol";
import {IPausable} from "./interfaces/IPausable.sol";
import {IProtocolUpgradeHandler} from "./interfaces/IProtocolUpgradeHandler.sol";

Expand Down Expand Up @@ -66,14 +67,20 @@ contract ProtocolUpgradeHandler is IProtocolUpgradeHandler {
/// @dev ZKsync smart contract that used to operate with L2 via asynchronous L2 <-> L1 communication.
IZKsyncEra public immutable ZKSYNC_ERA;

/// @dev ZKsync smart contract that is responsible for creating new hyperchains and changing parameters in existent.
IStateTransitionManager public immutable STATE_TRANSITION_MANAGER;
/// @dev ZKsync smart contract that is responsible for creating new ZK Chains and changing parameters in existent.
IChainTypeManager public immutable CHAIN_TYPE_MANAGER;

/// @dev Bridgehub smart contract that is used to operate with L2 via asynchronous L2 <-> L1 communication.
IPausable public immutable BRIDGE_HUB;
IBridgeHub public immutable BRIDGE_HUB;

/// @dev The shared bridge that is used for all bridging.
IPausable public immutable SHARED_BRIDGE;
/// @dev The nullifier contract that is used for bridging.
IPausable public immutable L1_NULLIFIER;

/// @dev The asset router contract that is used for bridging.
IPausable public immutable L1_ASSET_ROUTER;

/// @dev Vault holding L1 native ETH and ERC20 tokens bridged into the ZK chains.
IPausable public immutable L1_NATIVE_TOKEN_VAULT;

/// @notice The address of the Security Council.
address public securityCouncil;
Expand Down Expand Up @@ -103,9 +110,11 @@ contract ProtocolUpgradeHandler is IProtocolUpgradeHandler {
address _emergencyUpgradeBoard,
address _l2ProtocolGovernor,
IZKsyncEra _ZKsyncEra,
IStateTransitionManager _stateTransitionManager,
IPausable _bridgeHub,
IPausable _sharedBridge
IChainTypeManager _chainTypeManager,
IBridgeHub _bridgeHub,
IPausable _l1Nullifier,
IPausable _l1AssetRouter,
IPausable _l1NativeTokenVault
) {
// Soft configuration check for contracts that inherit this contract.
assert(STANDARD_LEGAL_VETO_PERIOD() <= EXTENDED_LEGAL_VETO_PERIOD);
Expand All @@ -121,9 +130,11 @@ contract ProtocolUpgradeHandler is IProtocolUpgradeHandler {

L2_PROTOCOL_GOVERNOR = _l2ProtocolGovernor;
ZKSYNC_ERA = _ZKsyncEra;
STATE_TRANSITION_MANAGER = _stateTransitionManager;
CHAIN_TYPE_MANAGER = _chainTypeManager;
BRIDGE_HUB = _bridgeHub;
SHARED_BRIDGE = _sharedBridge;
L1_NULLIFIER = _l1Nullifier;
L1_ASSET_ROUTER = _l1AssetRouter;
L1_NATIVE_TOKEN_VAULT = _l1NativeTokenVault;
}

/*//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -381,20 +392,22 @@ contract ProtocolUpgradeHandler is IProtocolUpgradeHandler {
/// rare case where the execution could get stuck at a particular ID for some unforeseen reason.
function reinforceFreezeOneChain(uint256 _chainId) external {
require(block.timestamp <= protocolFrozenUntil, "Protocol should be already frozen");
STATE_TRANSITION_MANAGER.freezeChain(_chainId);
CHAIN_TYPE_MANAGER.freezeChain(_chainId);
emit ReinforceFreezeOneChain(_chainId);
}

/// @dev Freeze all ZKsync contracts, including bridges, state transition managers and all hyperchains.
/// @dev Freeze all ZKsync contracts, including bridges, state transition managers and all ZK Chains.
function _freeze() internal {
uint256[] memory hyperchainIds = STATE_TRANSITION_MANAGER.getAllHyperchainChainIDs();
uint256 len = hyperchainIds.length;
uint256[] memory zkChainIds = BRIDGE_HUB.getAllZKChainChainIDs();
uint256 len = zkChainIds.length;
for (uint256 i = 0; i < len; ++i) {
try STATE_TRANSITION_MANAGER.freezeChain(hyperchainIds[i]) {} catch {}
try CHAIN_TYPE_MANAGER.freezeChain(zkChainIds[i]) {} catch {}
}

try BRIDGE_HUB.pause() {} catch {}
try SHARED_BRIDGE.pause() {} catch {}
try L1_NULLIFIER.pause() {} catch {}
vladbochok marked this conversation as resolved.
Show resolved Hide resolved
try L1_ASSET_ROUTER.pause() {} catch {}
try L1_NATIVE_TOKEN_VAULT.pause() {} catch {}
}

/// @dev Unfreezes the protocol and resumes normal operations.
Expand Down Expand Up @@ -425,20 +438,22 @@ contract ProtocolUpgradeHandler is IProtocolUpgradeHandler {
/// rare case where the execution could get stuck at a particular ID for some unforeseen reason.
function reinforceUnfreezeOneChain(uint256 _chainId) external {
require(protocolFrozenUntil == 0, "Protocol should be already unfrozen");
STATE_TRANSITION_MANAGER.unfreezeChain(_chainId);
CHAIN_TYPE_MANAGER.unfreezeChain(_chainId);
emit ReinforceUnfreezeOneChain(_chainId);
}

/// @dev Unfreeze all ZKsync contracts, including bridges, state transition managers and all hyperchains.
/// @dev Unfreeze all ZKsync contracts, including bridges, state transition managers and all ZK Chains.
function _unfreeze() internal {
uint256[] memory hyperchainIds = STATE_TRANSITION_MANAGER.getAllHyperchainChainIDs();
uint256 len = hyperchainIds.length;
uint256[] memory zkChainIds = BRIDGE_HUB.getAllZKChainChainIDs();
uint256 len = zkChainIds.length;
for (uint256 i = 0; i < len; ++i) {
try STATE_TRANSITION_MANAGER.unfreezeChain(hyperchainIds[i]) {} catch {}
try CHAIN_TYPE_MANAGER.unfreezeChain(zkChainIds[i]) {} catch {}
}
vladbochok marked this conversation as resolved.
Show resolved Hide resolved

try BRIDGE_HUB.unpause() {} catch {}
try SHARED_BRIDGE.unpause() {} catch {}
try L1_NULLIFIER.unpause() {} catch {}
vladbochok marked this conversation as resolved.
Show resolved Hide resolved
try L1_ASSET_ROUTER.unpause() {} catch {}
try L1_NATIVE_TOKEN_VAULT.unpause() {} catch {}
}

/*//////////////////////////////////////////////////////////////
Expand Down
15 changes: 10 additions & 5 deletions l1-contracts/src/TestnetProtocolUpgradeHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ pragma solidity 0.8.24;

import {ProtocolUpgradeHandler} from "./ProtocolUpgradeHandler.sol";
import {IZKsyncEra} from "./interfaces/IZKsyncEra.sol";
import {IStateTransitionManager} from "./interfaces/IStateTransitionManager.sol";
import {IChainTypeManager} from "./interfaces/IChainTypeManager.sol";
import {IBridgeHub} from "./interfaces/IBridgeHub.sol";
import {IPausable} from "./interfaces/IPausable.sol";

/// @title Testnet Protocol Upgrade Handler
Expand All @@ -26,9 +27,11 @@ contract TestnetProtocolUpgradeHandler is ProtocolUpgradeHandler {
address _emergencyUpgradeBoard,
address _l2ProtocolGovernor,
IZKsyncEra _ZKsyncEra,
IStateTransitionManager _stateTransitionManager,
IPausable _bridgeHub,
IPausable _sharedBridge
IChainTypeManager _stateTransitionManager,
IBridgeHub _bridgeHub,
IPausable _l1Nullifier,
IPausable _l1AssetRouter,
IPausable _l1NativeTokenVault
)
ProtocolUpgradeHandler(
_securityCouncil,
Expand All @@ -38,7 +41,9 @@ contract TestnetProtocolUpgradeHandler is ProtocolUpgradeHandler {
_ZKsyncEra,
_stateTransitionManager,
_bridgeHub,
_sharedBridge
_l1Nullifier,
_l1AssetRouter,
_l1NativeTokenVault
)
{}
}
11 changes: 11 additions & 0 deletions l1-contracts/src/interfaces/IBridgeHub.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

import {IPausable} from "./IPausable.sol";

/// @author Matter Labs
/// @custom:security-contact security@matterlabs.dev
interface IBridgeHub is IPausable {
function getAllZKChainChainIDs() external view returns (uint256[] memory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ pragma solidity 0.8.24;

/// @author Matter Labs
/// @custom:security-contact security@matterlabs.dev
interface IStateTransitionManager {
interface IChainTypeManager {
function freezeChain(uint256 _chainId) external;

function unfreezeChain(uint256 _chainId) external;

function getAllHyperchainChainIDs() external view returns (uint256[] memory);
}
47 changes: 30 additions & 17 deletions l1-contracts/test/ProtocolUpgradeHandler.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import {Test, stdStorage, StdStorage} from "forge-std/Test.sol";

import {Callee} from "./utils/Callee.t.sol";
import {EmptyContract} from "./utils/EmptyContract.t.sol";
import {StateTransitionManagerMock} from "./mocks/StateTransitionManagerMock.t.sol";
import {ChainTypeManagerMock} from "./mocks/ChainTypeManagerMock.t.sol";
import {BridgeHubMock} from "./mocks/BridgeHubMock.t.sol";

import {IProtocolUpgradeHandler} from "../../src/interfaces/IProtocolUpgradeHandler.sol";
import {IZKsyncEra} from "../../src/interfaces/IZKsyncEra.sol";
import {IStateTransitionManager} from "../../src/interfaces/IStateTransitionManager.sol";
import {IChainTypeManager} from "../../src/interfaces/IChainTypeManager.sol";
import {IBridgeHub} from "../../src/interfaces/IBridgeHub.sol";
import {IPausable} from "../../src/interfaces/IPausable.sol";

import {ProtocolUpgradeHandler} from "../../src/ProtocolUpgradeHandler.sol";
Expand All @@ -30,9 +32,11 @@ contract TestProtocolUpgradeHandler is Test {
address emergencyUpgradeBoard;
address l2ProtocolGovernor;
IZKsyncEra zksyncAddress;
IStateTransitionManager stateTransitionManager;
IPausable bridgeHub;
IPausable sharedBridge;
IChainTypeManager chainTypeManager;
IBridgeHub bridgeHub;
IPausable l1Nullifier;
IPausable l1AssetRouter;
IPausable l1NativeTokenVault;

ProtocolUpgradeHandler handler;
uint256[] chainIds;
Expand Down Expand Up @@ -69,12 +73,13 @@ contract TestProtocolUpgradeHandler is Test {
function _expectFreezeAttempt() internal {
for (uint256 i = 0; i < chainIds.length; i++) {
vm.expectCall(
address(stateTransitionManager),
abi.encodeWithSelector(IStateTransitionManager.freezeChain.selector, (chainIds[i]))
address(chainTypeManager), abi.encodeWithSelector(IChainTypeManager.freezeChain.selector, (chainIds[i]))
);
}
vm.expectCall(address(bridgeHub), abi.encodeWithSelector(IPausable.pause.selector));
vm.expectCall(address(sharedBridge), abi.encodeWithSelector(IPausable.pause.selector));
vm.expectCall(address(l1Nullifier), abi.encodeWithSelector(IPausable.pause.selector));
vm.expectCall(address(l1AssetRouter), abi.encodeWithSelector(IPausable.pause.selector));
vm.expectCall(address(l1NativeTokenVault), abi.encodeWithSelector(IPausable.pause.selector));
}

function _emptyProposal(bytes32 _salt) internal returns (IProtocolUpgradeHandler.UpgradeProposal memory) {
Expand Down Expand Up @@ -151,20 +156,24 @@ contract TestProtocolUpgradeHandler is Test {
emergencyUpgradeBoard = makeAddr("emergencyUpgradeBoard");
l2ProtocolGovernor = makeAddr("l2ProtocolGovernor");
zksyncAddress = IZKsyncEra(address(new EmptyContract()));
stateTransitionManager = IStateTransitionManager(address(new StateTransitionManagerMock(chainIds)));
chainTypeManager = IChainTypeManager(address(new ChainTypeManagerMock(chainIds)));

bridgeHub = IPausable(address(new EmptyContract()));
sharedBridge = IPausable(address(new EmptyContract()));
bridgeHub = IBridgeHub(address(new BridgeHubMock(chainIds)));
l1Nullifier = IPausable(address(new EmptyContract()));
l1AssetRouter = IPausable(address(new EmptyContract()));
l1NativeTokenVault = IPausable(address(new EmptyContract()));

handler = new ProtocolUpgradeHandler(
securityCouncil,
guardians,
emergencyUpgradeBoard,
l2ProtocolGovernor,
zksyncAddress,
stateTransitionManager,
chainTypeManager,
bridgeHub,
sharedBridge
l1Nullifier,
l1AssetRouter,
l1NativeTokenVault
);
}

Expand All @@ -182,18 +191,22 @@ contract TestProtocolUpgradeHandler is Test {
emergencyUpgradeBoard,
l2ProtocolGovernor,
zksyncAddress,
stateTransitionManager,
chainTypeManager,
bridgeHub,
sharedBridge
l1Nullifier,
l1AssetRouter,
l1NativeTokenVault
);
assertEq(testHandler.securityCouncil(), securityCouncil);
assertEq(testHandler.guardians(), guardians);
assertEq(testHandler.emergencyUpgradeBoard(), emergencyUpgradeBoard);
assertEq(testHandler.L2_PROTOCOL_GOVERNOR(), l2ProtocolGovernor);
assertEq(address(testHandler.ZKSYNC_ERA()), address(zksyncAddress));
assertEq(address(testHandler.STATE_TRANSITION_MANAGER()), address(stateTransitionManager));
assertEq(address(testHandler.CHAIN_TYPE_MANAGER()), address(chainTypeManager));
assertEq(address(testHandler.BRIDGE_HUB()), address(bridgeHub));
assertEq(address(testHandler.SHARED_BRIDGE()), address(sharedBridge));
assertEq(address(testHandler.L1_NULLIFIER()), address(l1Nullifier));
assertEq(address(testHandler.L1_ASSET_ROUTER()), address(l1AssetRouter));
assertEq(address(testHandler.L1_NATIVE_TOKEN_VAULT()), address(l1NativeTokenVault));
}

function test_StateUpgradeIncorrectProof() public {
Expand Down
18 changes: 18 additions & 0 deletions l1-contracts/test/mocks/BridgeHubMock.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

contract BridgeHubMock {
uint256[] chainIds;

constructor(uint256[] memory _chainIds) {
chainIds = _chainIds;
}

function getAllZKChainChainIDs() external view returns (uint256[] memory) {
return chainIds;
}

// add this to be excluded from coverage report
function test() internal virtual {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

pragma solidity 0.8.24;

contract StateTransitionManagerMock {
contract ChainTypeManagerMock {
uint256[] chainIds;

constructor(uint256[] memory _chainIds) {
chainIds = _chainIds;
}

function getAllHyperchainChainIDs() external view returns (uint256[] memory) {
return chainIds;
}

function freezeChain(uint256 _chainId) external {
for (uint256 i = 0; i < chainIds.length; i++) {
if (_chainId == chainIds[i]) {
Expand Down