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
Rank: 19/24
Findings: 1
Award: $565.16
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0x11singh99
Also found by: Bauchibred, Dup1337, Topmark, XDZIBECX, bctester, bin2chen, erebus, forgebyola, oakcobalt, rvierdiiev, yashar, zhanmingjing
565.1582 USDC - $565.16
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
Denial of Service When State Transition Manager wants to Unfreeze Chain as the unfreeze function calls freezeDiamond() again instead of calling unfreezeDiamond()
/// @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(); }
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(); }
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