Audit the Deployment, Not Just the Code
ZKSwap experienced an exploit on July 9, 2024, resulting in an estimated loss of approximately $5 million at the time. The root cause of the exploit was the erroneous deployment of a smart contract. The deployed contract skipped the ZK proof verification step and simply returned ‘true’ for any proof submitted.
Overview
Attacker: https://etherscan.io/address/0x0a652decf9caca373e2b50607ecb7b069d71a7ba
Vulnerable Contract: https://etherscan.io/address/0x8eca806aecc86ce90da803b080ca4e3a9b8097ad
Transaction attack: https://etherscan.io/tx/0x5488f6bbfabf7f1ada8e529c23dfc1fd129b4237536e9b5500b47d63f773e054
Exploit Analysis
ZKSwap acts as a bridge for users to transfer assets between Ethereum L1 to ZKSwap rollup L2. Normally, users deposit assets into the L2 system, where they can make fast and cheap transactions. To move funds back to L1, they usually need a proof created by the system operator.
But in case something goes wrong—like the system going offline or the operator not responding—there’s a backup feature called Exodus Mode.
In Exodus Mode, users can withdraw on their own by sending proof directly to the Ethereum L1 contract, showing they owned certain balances in the last confirmed L2 state. This feature acts as a safety net, making sure users can always access their assets, even if the system fails.
To withdraw in Exodus Mode, user need to provide a proof to verifyExitProof function which will be cryptographic validated to prove that the user has enough balance to withdraw.
The problem is that the deployed smart contract is incorrect—it includes a return true statement at the very beginning of the function, which skips all cryptographic validation and accepts any submitted proof as valid.
This contract was likely used by the developers for testing withdrawals in Exodus Mode without requiring real ZK-proof verification. It’s a common practice for smart contract developers to create mock verifier contracts that bypass validation logic to test other parts of the system.
Unfortunately, the developers forgot to remove the return true statement and accidentally deployed this testing version. As a result, an attacker can exploit the contract by submitting fake proofs and withdrawing funds without proper verification.
Lesson learned
This incident highlights a critical gap in the development and deployment lifecycle of smart contracts: auditing must extend beyond the source code to include the actual deployed contract and configuration.
While the contract logic may be thoroughly reviewed and tested, mistakes can still occur at the deployment stage—such as deploying a mock contract intended only for internal testing, missing initialize invoke after upgrading. In this case, a single overlooked line (return true) in the deployed verifier contract led to a complete bypass of cryptographic proof checks, resulting in a severe security vulnerability.