# ZKSYNC1-2021-01 Post Mortem
# Summary
On July 26, 2021, we were notified of a critical vulnerability in zkSync’s smart contracts that was introduced in zkSync’s Version 5.1 upgrade (opens new window) on July 1. The fix was deployed (opens new window) on July 27, and all funds are safe. At the time of the report, zkSync had $8.5m USD in total value locked and was the only severe vulnerability in the zkSync protocol since genesis to date.
# Technical Details
# The Vulnerability
To initialize new upgrades, the initialize (opens new window) function inside the zkSync main contract is called:
This function can be external because the Proxy contract which uses this contract as a target for delegatecalls
intercepts all calls of the function with such signature. However, this meant initialize could be called on the target
contract with any parameters at any time, allowing anyone to set additionalZkSync
in the target contract storage to
any address.
If the attacker sets additionalZkSync
to an address that would execute the SELFDESTRUCT
opcode on any entry, and
then call any function on the zkSync main contract that uses logic from additionalZkSync
via delegatecall, the main
zkSync target contract could have been destroyed and all funds would have been frozen.
Funds could not be stolen because the Proxy contract owns the rollup assets and it did not contain a vulnerability, only the code of the Proxy’s target.
# The Fix
Because there is a 3-day timelock from the initialization of the upgrade and the execution, we introduced the fix in a way that those who checked the code diff during the upgrade would not find the vulnerability.
To fix the vulnerability, we updated the initializeReentrancyGuard
function to the new OpenZeppelin version and added
a check that makes it impossible to reinitialize ReentrancyGuard and the main contract’s target consequently. For the
updated version, we initialized zkSync’s target contract while deploying, so no one can reinitialize it.
# Bug Bounty
In accordance with our Bug Bounty Policy, we have paid the person who made the disclosure our maximum bounty of $500,000 due to the severity of the bug found.
# Conclusion
Following this vulnerability, we have conducted a thorough internal review of our security approach and processes, introducing a number of systematic improvements not only to fix the root cause, but also to make our entire system more robust in bug prevention and reaction.
To better manage the security of a rapidly upgrading protocol, we: upgraded our security council to allow for instant upgradability with 9/15 signatures, improved our bug bounty program and are partnering with ImmuneFi. These improvements are explored in depth in this article (opens new window).
In the security section of our documentation, we have also added a JSON-formatted list of known bugs and updated our vulnerability disclosure policy.