zkSync Era - Topmark's results

General Information

Platform: Code4rena

Start Date: 07/03/2024

Pot Size: $250,000 USDC

Total HM: 5

Participants: 24

Period: 21 days

Judge: 0xsomeone

Total Solo HM: 3

Id: 347

League: ETH

zkSync

Findings Distribution

Researcher Performance

Rank: 19/24

Findings: 1

Award: $565.16

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
:robot:_07_group
duplicate-97

Awards

565.1582 USDC - $565.16

External Links

Lines of code

https://github.com/code-423n4/2024-03-zksync/blob/main/code/contracts/ethereum/contracts/state-transition/StateTransitionManager.sol#L165 https://github.com/code-423n4/2024-03-zksync/blob/main/code/contracts/ethereum/contracts/state-transition/chain-deps/facets/Admin.sol#L143

Vulnerability details

Impact

Denial of Service When State Transition Manager wants to Unfreeze Chain as the unfreeze function calls freezeDiamond() again instead of calling unfreezeDiamond()

Proof of Concept

 /// @dev freezes the specified chain
    function freezeChain(uint256 _chainId) external onlyOwner {
        IZkSyncStateTransition(stateTransition[_chainId]).freezeDiamond();
    }

>>>    /// @dev freezes the specified chain
    function unfreezeChain(uint256 _chainId) external onlyOwner {
>>>        IZkSyncStateTransition(stateTransition[_chainId]).freezeDiamond();
    }

The code above from the StateTransitionManager contract shows how freezing and unfreezing is done, however there is a mistake with the implementation of the unfreeze function, it calls freezeDiamond() instead of unfreezeDiamond() which will cause Denial of Service and unfreezing would never be possible again. The code provided below is from the Admin.sol contract, it shows there is indeed an implementation for both freezing and unfreezing which proves that the implementation in the unfreezeChain(...) function in the StateTransitionManager contract was indeed an error which would break protocol functionality.

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

        require(!diamondStorage.isFrozen, "a9"); // diamond proxy is frozen already
        diamondStorage.isFrozen = true;

        emit Freeze();
    }

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

        require(diamondStorage.isFrozen, "a7"); // diamond proxy is not frozen
        diamondStorage.isFrozen = false;

        emit Unfreeze();
    }

Tools Used

Manual Review

The protocol should make necessary correction as provided below

 /// @dev freezes the specified chain
    function freezeChain(uint256 _chainId) external onlyOwner {
        IZkSyncStateTransition(stateTransition[_chainId]).freezeDiamond();
    }

---    /// @dev freezes the specified chain
+++    /// @dev unfreezes the specified chain
    function unfreezeChain(uint256 _chainId) external onlyOwner {
---        IZkSyncStateTransition(stateTransition[_chainId]).freezeDiamond();
+++        IZkSyncStateTransition(stateTransition[_chainId]).unfreezeDiamond();
    }

Assessed type

Error

#0 - c4-judge

2024-04-02T17:02:29Z

alex-ppg marked the issue as duplicate of #97

#1 - c4-judge

2024-04-29T13:51:52Z

alex-ppg changed the severity to 2 (Med Risk)

#2 - c4-judge

2024-04-29T13:55:03Z

alex-ppg marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter