Introduction
We express our gratitude to the Sig.Network team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Chain signatures is an MPC service that facilitates the ability to sign arbitrary payloads by calling into a smart contract and eventually getting back a signature. This signature can be used for various purposes such as deriving new public keys associated to foreign chains (Ethereum, Bitcoin, etc.).
Document | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for Sig.Network |
| Audited By | Reshma Fareed; Tanuj Soni; Ivan Bondar |
| Approved By | Grzegorz Trawinski |
| Website | https://sig.network/→ |
| Changelog | 07/02/2025 - Preliminary Report |
| 21/02/2025 - Final Report | |
| Platform | Ethereum |
| Language | Solidity |
| Tags | Proxy; Upgradable; Signatures |
| Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Sig.Network
- Audited By
- Reshma Fareed; Tanuj Soni; Ivan Bondar
- Approved By
- Grzegorz Trawinski
- Website
- https://sig.network/→
- Changelog
- 07/02/2025 - Preliminary Report
- 21/02/2025 - Final Report
- Platform
- Ethereum
- Language
- Solidity
- Tags
- Proxy; Upgradable; Signatures
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
|---|---|
| Repository | https://github.com/sig-net/mpc/tree/develop/chain-signatures/contract-eth→ |
| Commit | 797aa4b |
| Retest Commit | e0ca660 |
Review Scope
- Commit
- 797aa4b
- Retest Commit
- e0ca660
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are detailed.
Project overview is detailed
All roles in the system are described.
Use cases are described and detailed.
For each contract, all futures are described.
All interactions are described.
Technical description is detailed.
Run instructions are provided.
Technical specification is provided.
The NatSpec documentation is sufficient.
Code quality
The development environment is configured.
Test coverage
Code coverage of the project is 58.33% (branch coverage).
Deployment and basic user interactions are covered with tests.
Negative cases coverage is missed.
System Overview
Chain Signatures is an MPC service that enables users to request and receive cryptographic signatures for arbitrary payloads on-chain. The protocol leverages secp256k1 elliptic curve cryptography to facilitate secure, decentralized signing operations, supporting key derivation and signature verification across multiple blockchain networks.
Files in Scope
ChainSignatures.sol - Manages the full lifecycle of signature requests, from submission to response validation.
Key Features
Initialization
The contract is initialized with an MPC-controlled account (
_mpc_network) that has administrative privileges.A configurable deposit amount (
signatureDeposit) is required for submitting signing requests, preventing spam and ensuring commitment.
Request Handling
Users submit signing requests with payload details, a specified key version, and a required deposit.
The contract emits a
SignatureRequestedevent containing the payload, derivation path, algorithm, destination, and additional parameters.Requests are linked to the sender’s address and the current blockchain (
chainId).
Signature Response
Responses are submitted off-chain and later broadcast to the network.
Upon receiving a signature response, the contract emits a
SignatureRespondedevent containing the request ID and the provided signature.In case of an error, responders can emit a
SignatureErrorevent with an associated error message.
Financial Safeguards
Deposits ensure financial commitment from requesters and can be adjusted by the MPC-controlled account.
An administrative role allows withdrawals from the contract’s balance to prevent fund accumulation.
Key Changes
Several functionalities were removed during the remediation phase of the audit. Public key management and key derivation functions are no longer included, along with epsilon derivation. The system no longer tracks signature requests, checks for duplicate requests, or validates payload limits. Signature verification using ecrecover() has been removed, as well as the deposit refund mechanism and dynamic deposit calculation.
Privileged Roles
Chain Signatures employs role-based access control through OpenZeppelin’s AccessControl:
Administrative Control
The
_mpc_networkis granted theDEFAULT_ADMIN_ROLE, allowing it to:Adjust the
signatureDepositamount.Withdraw contract funds.
User-driven Interactions
Signing requests and responses are open to all users, ensuring decentralized operation.
Signature validity must be verified off-chain before usage, as the contract does not enforce cryptographic checks internally.
Potential Risks
Unrestricted Response Functions: The respond and respondError functions are unrestricted, allowing any address to emit signature responses. Given that the MPC participants are dynamic and unpredictable, each signature must be verified on the client side through integrated tooling as detailed in the documentation.
Insufficient Permissioning and Documentation: Inadequate permissions or incomplete documentation around role assignments and access controls could enable unauthorized access or unintended operations, complicating issue resolution and heightening security risks.
Dependency on Off-Chain Signature Verification: The contract offloads signature validation and key derivation to off-chain systems. Inadequate integration or misconfiguration of these external processes can result in unauthorized transactions or vulnerabilities that are not directly mitigated on-chain.
Absence of Time-lock Mechanisms for Critical Operations: Without time-locks on operations such as updating the signature deposit or withdrawing funds, there is no buffer period to review or cancel potentially harmful actions, increasing the risk of rapid exploitation.
Dynamic Array Iteration Gas Limit Risks: Iterating over arrays in the respond and respondError functions may lead to high gas consumption when processing large input arrays, potentially causing out-of-gas errors and impacting contract usability.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2025-8657 | Denial of Service via Push Refund Mechanism in Respond Function | fixed | High | |
| F-2025-8679 | Improper Implementation of ecrecover allows the risk of Signature Malleability | fixed | Medium | |
| F-2025-8676 | Potential Replay Attacks possible due to Missing Chain ID in Path Derivation | fixed | Medium | |
| F-2025-8663 | Premature Deletion of Request Data Causes Refund Failure | fixed | Medium | |
| F-2025-8655 | Unbounded Deposit Growth Leads to Economic Denial of Service | fixed | Medium | |
| F-2025-8677 | Missing Curve Order Range Check in Elliptic Curve Scalar Multiplication | fixed | Low | |
| F-2025-8675 | Lack of Key Version Upgradability Mechanism | fixed | Low | |
| F-2025-8659 | Deterministic Request ID Generation and Usage of abi.encodePacked Prevents Reuse of Identical Signing Requests | fixed | Low | |
| F-2025-8656 | Lack of Request Cancellation Mechanism Leads to Locked Deposits and Inflation of Deposit Requirements | fixed | Low | |
| F-2025-8654 | Hard Dependency on Fixed Gas Costs via transfer() in Refund Mechanism | fixed | Low |
Appendix 1. Definitions
Severities
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
|---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
Potential Risks
The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
|---|---|
| Repository | https://github.com/sig-net/mpc/tree/develop→ |
| Commit | 797aa4b8e6a040f28e53d37628ad111e4b90825d |
| Retest Commit | e0ca660fdb84955f28d907180a9013067d5aa083 |
| Whitepaper | N/A |
| Requirements | https://github.com/sig-net/mpc/blob/develop/README.md→ |
| Technical Requirements | https://github.com/sig-net/mpc/blob/develop/chain-signatures/contract-eth/README.md→ |
Scope Details
- Commit
- 797aa4b8e6a040f28e53d37628ad111e4b90825d
- Retest Commit
- e0ca660fdb84955f28d907180a9013067d5aa083
- Whitepaper
- N/A
- Technical Requirements
- https://github.com/sig-net/mpc/blob/develop/chain-signatures/contract-eth/README.md→
Assets in Scope
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Chain Signatures, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Foundry, a tool used for fuzz-testing, was employed to check how the protocol behaves under various inputs. Due to the complex and dynamic interactions within the protocol, unexpected edge cases might arise. Therefore, it was important to use fuzz-testing to ensure that several system invariants hold true in all situations.
Fuzz-testing allows the input of many random data points into the system, helping to identify issues that regular testing might miss. A specific Echidna fuzzing suite was prepared for this task, and throughout the assessment, 3 invariants and 4 fuzz tests were tested over 50,000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
|---|---|---|
| invariantPublicKeyUnchanged - the public key remains the same throughout invariant runs. | Passed | 50K+ |
| invariantLatestKeyVersionIsZero - latestKeyVersion() always returns 0. | Passed | 50K+ |
invariantDepositCalculation - the getSignatureDeposit() formula matches the requestCounter logic. | Passed | 50K+ |
| Fuzz | ||
| testFuzzMultipleSimultaneousRequests - the deposit calculation scales correctly when multiple requests exist. | Passed | 50K+ |
| testFuzzBoundaryPayload - only payloads below the secp256k1 curve order are accepted. | Passed | 50K+ |
| testFuzzAlternatePredecessor - derived keys differ when using different predecessor addresses. | Passed | 50K+ |
| testFuzzDeriveEpsilon - deriveEpsilon produces consistent, deterministic values for identical inputs. | Passed | 50K+ |
Invariant
- invariantPublicKeyUnchanged - the public key remains the same throughout invariant runs.
Test Result
- Passed
Run Count
- 50K+
Invariant
- invariantLatestKeyVersionIsZero - latestKeyVersion() always returns 0.
Test Result
- Passed
Run Count
- 50K+
Invariant
- invariantDepositCalculation - the
getSignatureDeposit()formula matches therequestCounterlogic. Test Result
- Passed
Run Count
- 50K+
Invariant
- Fuzz
Test Result
Run Count
Invariant
- testFuzzMultipleSimultaneousRequests - the deposit calculation scales correctly when multiple requests exist.
Test Result
- Passed
Run Count
- 50K+
Invariant
- testFuzzBoundaryPayload - only payloads below the secp256k1 curve order are accepted.
Test Result
- Passed
Run Count
- 50K+
Invariant
- testFuzzAlternatePredecessor - derived keys differ when using different predecessor addresses.
Test Result
- Passed
Run Count
- 50K+
Invariant
- testFuzzDeriveEpsilon - deriveEpsilon produces consistent, deterministic values for identical inputs.
Test Result
- Passed
Run Count
- 50K+
Additional Recommendations
The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.
To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:
Detecting changes to ownership or critical permissions.
Monitoring large or unexpected transactions and minting events.
Pausing operations when irregularities are identified.
These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.