Skip to content

Commit

Permalink
change implementation and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-nguy committed Aug 28, 2024
1 parent f75533d commit 96251bf
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 8 deletions.
4 changes: 4 additions & 0 deletions l1-contracts/contracts/common/L1ContractErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ error DiamondAlreadyFrozen();
error DiamondFreezeIncorrectState();
// 0xa7151b9a
error DiamondNotFrozen();
//
error DiamondFrozenByAdmin();
//
error DiamondNotFrozenByAdmin();
// 0xfc7ab1d3
error EmptyBlobVersionHash(uint256 index);
// 0x95b66fe9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,6 @@ struct ZkSyncHyperchainStorage {
uint128 baseTokenGasPriceMultiplierDenominator;
/// @dev The optional address of the contract that has to be used for transaction filtering/whitelisting
address transactionFilterer;
/// @dev Boolean for tracking when the hyperchain has been frozen by chain admin
bool frozenByAdmin;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {MAX_GAS_PER_TRANSACTION} from "../../../common/Config.sol";
import {FeeParams, PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol";
import {ZkSyncHyperchainBase} from "./ZkSyncHyperchainBase.sol";
import {IStateTransitionManager} from "../../IStateTransitionManager.sol";
import {Unauthorized, TooMuchGas, PriorityTxPubdataExceedsMaxPubDataPerBatch, InvalidPubdataPricingMode, ProtocolIdMismatch, ChainAlreadyLive, HashMismatch, ProtocolIdNotGreater, DenominatorIsZero, DiamondAlreadyFrozen, DiamondNotFrozen} from "../../../common/L1ContractErrors.sol";
import {Unauthorized, TooMuchGas, PriorityTxPubdataExceedsMaxPubDataPerBatch, InvalidPubdataPricingMode, ProtocolIdMismatch, ChainAlreadyLive, HashMismatch, ProtocolIdNotGreater, DenominatorIsZero, DiamondAlreadyFrozen, DiamondNotFrozen, DiamondFrozenByAdmin, DiamondNotFrozenByAdmin} from "../../../common/L1ContractErrors.sol";

// While formally the following import is not used, it is needed to inherit documentation from it
import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol";
Expand Down Expand Up @@ -164,19 +164,35 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin {
}
diamondStorage.isFrozen = true;

if (msg.sender == s.admin) {
s.frozenByAdmin = true;
}

emit Freeze();
}

/// @inheritdoc IAdmin
function unfreezeDiamond() external onlyStateTransitionManager {
Diamond.DiamondStorage storage diamondStorage = Diamond.getDiamondStorage();

// diamond proxy is not frozen
if (!diamondStorage.isFrozen) {
revert DiamondNotFrozen();
}
// diamond proxy is frozen by admin
if (s.frozenByAdmin) {
revert DiamondFrozenByAdmin();
}
diamondStorage.isFrozen = false;

emit Unfreeze();
}

/// @inheritdoc IAdmin
function allowUnfreezeDiamond() external onlyAdmin {
if (!s.frozenByAdmin) {
// diamond proxy needs to be previously frozen by admin
revert DiamondNotFrozenByAdmin();
}
s.frozenByAdmin = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ interface IAdmin is IZkSyncHyperchainBase {
function freezeDiamond() external;

/// @notice Unpause the functionality of all freezable facets & their selectors
/// @dev Both the admin and the STM can unfreeze Diamond Proxy
/// @dev Only the STM can unfreeze Diamond Proxy
function unfreezeDiamond() external;

/// @notice Allow to call unfreeze diamond if it was previously frozen by admin
/// @dev Only the current admin can use this function
function allowUnfreezeDiamond() external;

/// @notice Porter availability status changes
event IsPorterAvailableStatusUpdate(bool isPorterAvailable);

Expand Down
4 changes: 3 additions & 1 deletion l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ library Utils {
}

function getUtilsFacetSelectors() public pure returns (bytes4[] memory) {
bytes4[] memory selectors = new bytes4[](41);
bytes4[] memory selectors = new bytes4[](43);
selectors[0] = UtilsFacet.util_setChainId.selector;
selectors[1] = UtilsFacet.util_getChainId.selector;
selectors[2] = UtilsFacet.util_setBridgehub.selector;
Expand Down Expand Up @@ -299,6 +299,8 @@ library Utils {
selectors[38] = UtilsFacet.util_setTotalBatchesExecuted.selector;
selectors[39] = UtilsFacet.util_setL2LogsRootHash.selector;
selectors[40] = UtilsFacet.util_setBaseTokenGasPriceMultiplierNominator.selector;
selectors[41] = UtilsFacet.util_setFrozenByAdmin.selector;
selectors[42] = UtilsFacet.util_getFrozenByAdmin.selector;
return selectors;
}

Expand Down
8 changes: 8 additions & 0 deletions l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ contract UtilsFacet is ZkSyncHyperchainBase {
s.baseTokenGasPriceMultiplierNominator = _nominator;
}

function util_setFrozenByAdmin(bool _frozenByAdmin) external {
s.frozenByAdmin = _frozenByAdmin;
}

function util_getFrozenByAdmin() external view returns (bool) {
return s.frozenByAdmin;
}

// add this to be excluded from coverage report
function test() internal virtual {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import {Unauthorized} from "contracts/common/L1ContractErrors.sol";
contract FreezeDiamondTest is AdminTest {
event Freeze();

function test_revertWhen_calledByNonStateTransitionManager() public {
function test_revertWhen_calledByNonStateTransitionManagerOrAdmin() public {
address nonStateTransitionManager = makeAddr("nonStateTransitionManager");

vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, nonStateTransitionManager));


vm.startPrank(nonStateTransitionManager);
adminFacet.freezeDiamond();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity 0.8.24;

import {AdminTest} from "./_Admin_Shared.t.sol";
import {Unauthorized, DiamondFreezeIncorrectState, DiamondNotFrozen} from "contracts/common/L1ContractErrors.sol";
import {Unauthorized, DiamondFreezeIncorrectState, DiamondNotFrozen, DiamondFrozenByAdmin} from "contracts/common/L1ContractErrors.sol";

contract UnfreezeDiamondTest is AdminTest {
event Unfreeze();
Expand All @@ -26,4 +26,15 @@ contract UnfreezeDiamondTest is AdminTest {
vm.startPrank(admin);
adminFacet.unfreezeDiamond();
}

function test_revertWhen_diamondIsNotAllowedTobeUnfrozen() public {
address admin = utilsFacet.util_getStateTransitionManager();
utilsFacet.util_setIsFrozen(true);
utilsFacet.util_setFrozenByAdmin(true);

vm.expectRevert(DiamondFrozenByAdmin.selector);

vm.startPrank(admin);
adminFacet.unfreezeDiamond();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ contract AdminTest is Test {
facetCuts[0] = Diamond.FacetCut({
facet: address(new AdminFacet()),
action: Diamond.Action.Add,
isFreezable: true,
isFreezable: false,
selectors: getAdminSelectors()
});
facetCuts[1] = Diamond.FacetCut({
facet: address(new UtilsFacet()),
action: Diamond.Action.Add,
isFreezable: true,
isFreezable: false,
selectors: Utils.getUtilsFacetSelectors()
});

Expand Down

0 comments on commit 96251bf

Please sign in to comment.