Prepared by:
HALBORN
Last Updated 04/26/2024
Date of Engagement by: July 12th, 2023 - July 20th, 2023
No Reported Findings to Address
All findings
0
Critical
0
High
0
Medium
0
Low
0
Informational
0
This assessment was entirely focused on the new version of zkSync verifier which is a modified version of the Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge (PLONK) to optimize the proof system for zkSync Era circuits.
MatterLabs engaged Halborn to conduct a security assessment on their verifier smart contract beginning on 2023-07-12 and ending on 2023-07-20. The security assessment was scoped to the smart contract provided to the Halborn team.
Moreover, MatterLabs engaged Halborn to review a small update on their verifier smart contract (making the aggregative part to be optional depending on the verification keys) beginning on October 2nd, 2023 and ending on October 4th, 2023.
The team at Halborn was provided one week for the engagement and assigned a full-time security engineer to verify the security of the smart contract. The security engineer is a blockchain and smart-contract security expert with advanced penetration testing, smart-contract hacking, and deep knowledge of multiple blockchain protocols.
The purpose of this assessment is to:
Ensure that smart contract functions operate as intended
Identify potential security issues within the smart contract
In summary, Halborn did not identify any security risks within the verifier smart contract.
1. IN-SCOPE:
The security assessment was scoped to the following smart contract:
ethereum/contracts/verifier/Verifier.sol
Commit ID: f783f571e16a1b1adddb13db45db741f83b94812
And also to the following commit ID including the new update:
Commit ID: 4416321060c3ffac7d1d279602ca81809a259c18
Halborn performed a combination of manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of this assessment. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of the bridge code and can quickly identify items that do not follow security best practices. The following phases and associated tools were used throughout the term of the assessment:
Research into architecture and purpose.
Smart contract manual code review and walkthrough.
Graphing out functionality and contract logic/connectivity/functions. (solgraph
)
Manual assessment of use and safety for the critical Solidity variables and functions in scope to identify any arithmetic related vulnerability classes.
Manual testing by custom scripts.
Scanning of solidity files for vulnerabilities, security hotspots or bugs. (MythX
)
Static Analysis of security for scoped contract, and imported functions. (Slither
)
Testnet deployment. (Foundry
)
EXPLOITABILIY METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Attack Origin (AO) | Arbitrary (AO:A) Specific (AO:S) | 1 0.2 |
Attack Cost (AC) | Low (AC:L) Medium (AC:M) High (AC:H) | 1 0.67 0.33 |
Attack Complexity (AX) | Low (AX:L) Medium (AX:M) High (AX:H) | 1 0.67 0.33 |
IMPACT METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Confidentiality (C) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Integrity (I) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Availability (A) | None (A:N) Low (A:L) Medium (A:M) High (A:H) Critical (A:C) | 0 0.25 0.5 0.75 1 |
Deposit (D) | None (D:N) Low (D:L) Medium (D:M) High (D:H) Critical (D:C) | 0 0.25 0.5 0.75 1 |
Yield (Y) | None (Y:N) Low (Y:L) Medium (Y:M) High (Y:H) Critical (Y:C) | 0 0.25 0.5 0.75 1 |
SEVERITY COEFFICIENT () | COEFFICIENT VALUE | NUMERICAL VALUE |
---|---|---|
Reversibility () | None (R:N) Partial (R:P) Full (R:F) | 1 0.5 0.25 |
Scope () | Changed (S:C) Unchanged (S:U) | 1.25 1 |
Severity | Score Value Range |
---|---|
Critical | 9 - 10 |
High | 7 - 8.9 |
Medium | 4.5 - 6.9 |
Low | 2 - 4.4 |
Informational | 0 - 1.9 |
Critical
0
High
0
Medium
0
Low
0
Informational
0
Security analysis | Risk level | Remediation Date |
---|
The main goal of the manual testing performed during this assessment was to test that the verifier is properly working to verify the zk proofs generated by the zkSync Era circuits, focusing on the following points/scenarios:
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\endlastfoot\hline \textcolor{white}{Check that using any valid proof, the verifier is able to properly verify it and returns a true as a result } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if a maliciously forged serialized proof is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if less than 44 words for serialized proof is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if less than 4 words for recursive aggregation input is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier returns a true for a public input with dirty bits over Fr mask } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that the verifier returns a true having elliptic curve points over modulo } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that the verifier returns a true, having Fr over modulo } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if more than 1 public inputs is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if empty public inputs is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if more than 44 words for serialized proof is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if empty serialized proof is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if more than 4 words for recursive aggregation input is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if empty recursive aggregation input is sent } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that verifier reverts with proof is invalid if elliptic curve point at infinity is sent within the serialized proof } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that the verifier reverts with invalid quotient evaluation if an invalid public input is used } & \textcolor{green}{Pass} \ \hline
\end{longtable}
\small \begin{longtable}{| >{\raggedright}p{13cm} | c |}
\hline \rowcolor{darkgray} \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endfirsthead
\hline \multicolumn{1}{| c |}{\textbf{Test}} & \multicolumn{1}{| c |}{\textbf{Result}}\ \hline \endhead
\hline \textcolor{white}{Check that the verifier reverts with pairing failure if an invalid recursive aggregative input is used } & \textcolor{green}{Pass} \ \hline
\end{longtable}
Halborn used automated testing techniques to enhance the coverage of certain areas of the scoped contract. Among the tools used was Slither, a Solidity static analysis framework. After Halborn verified the contract in the repository and was able to compile it correctly into their ABI and binary formats, Slither was run on the verifier contract. This tool can statically verify mathematical relationships between Solidity variables to detect invalid or inconsistent usage of the contracts' APIs across the entire code-base.
ethereum/contracts/verifier/Verifier.sol
As a result of the tests carried out with the Slither tool, some results were obtained and reviewed by Halborn
. Based on the results reviewed, the vulnerabilities were determined to be false positives.
Halborn used automated security scanners to assist with detection of well-known security issues, and to identify low-hanging fruits on the targets for this engagement. Among the tools used was MythX, a security analysis service for Ethereum smart contracts. MythX performed a scan on the verifier contract and sent the compiled results to the analyzers to locate any vulnerabilities.
No major issues found by Mythx.
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed