Introduction
We express our gratitude to the Somnia team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Somnia is A UUPS‑upgradeable, role‑gated staking and validator-committee system.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for Somnia |
Audited By | Kornel Światłowski, Kaan Caglan |
Approved By | Ivan Bondar |
Website | https://somnia.network/→ |
Changelog | 20/08/2025 - Preliminary Report |
29/08/2025 - Final Report | |
Platform | Somnia |
Language | Solidity |
Tags | Staking, Proxy, Upgradable, Centralization, Governance, Incentives |
Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Somnia
- Audited By
- Kornel Światłowski, Kaan Caglan
- Approved By
- Ivan Bondar
- Website
- https://somnia.network/→
- Changelog
- 20/08/2025 - Preliminary Report
- 29/08/2025 - Final Report
- Platform
- Somnia
- Language
- Solidity
- Tags
- Staking, Proxy, Upgradable, Centralization, Governance, Incentives
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
---|---|
Repository | https://github.com/somnia-chain___somnia-protocol/→ |
Initial commit | 35a4ea285813c94b38297afdf9f9ad28518b5b22 |
Remediation commit | d0f353dff8bb36143cfae9fbf18c2d6ff701708a |
Review Scope
- Initial commit
- 35a4ea285813c94b38297afdf9f9ad28518b5b22
- Remediation commit
- d0f353dff8bb36143cfae9fbf18c2d6ff701708a
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
{FindingsVulnSeverityStatusTable}
Documentation quality
Functional requirements are partially missed.
Technical description is provided.
Code quality
Code does not follow best practices.
Functions are copy-pasted across the codebase.
Several template code patterns were found.
The development environment is configured.
Test coverage
Code coverage of the project is 52.55% (branch coverage)
Deployment and basic user interactions are covered with tests.
Negative cases coverage is missed.
System Overview
Somnia Validator Committee & Staking is UUPS‑upgradeable, role‑gated staking and validator-committee system. Validators stake native tokens, can accept delegated stake, and—if meeting thresholds—join a Node Committee that runs epochs, fee burning, reward distribution, gas‑price voting, and inactivity voting that can remove validators.
Contracts
NodeCommittee upgradeable
Purpose: Manage validator membership across epochs, handle stake‑weighted inactivity votes, compute a stake‑weighted median gas price, and settle/burn epoch rewards.
Initialization:
initialize(address upgrader, uint256 initialMaxNodes, uint256 initialBurnFeePercentage, uint256 initialMinNodes)
Grants:
DEFAULT_ADMIN_ROLE
toupgrader
andmsg.sender
;UPGRADER_ROLE
toupgrader
Sets:
maxNodes
,minNodes
,burnFeePercentage
(bps, max 10000), marksCURRENT
&NEXT
epochs finalised,FUTURE
not finalised;finalisedEpochCounter = 2
Key state:
address nodeCommitteeStaking
(SomniaStaking contract)uint256 burnFeePercentage
(bps; used during settlement)uint256 maxNodes
,uint256 minNodes
uint256 finalisedEpochCounter
mapping(EpochStatus => Epoch) epochs
withCURRENT
,NEXT
,FUTURE
Registry:
address[] registeredNodes
,mapping(address => Node) nodeByAddress
Inactivity voting:
mapping(address=>uint256) warnedNodeWeight
,votedInactiveInEpoch[]
, per‑pair flags/snapshotsGas price votes:
mapping(address=>GasPriceVote) gasPriceVotes
EIP‑712 domain:
"NodeCommittee","1"
;PUBLIC_KEYS_TYPEHASH
Privileged roles & powers:
DEFAULT_ADMIN_ROLE
: setNodeCommitteeStaking
, setBurnFeePercentage
, setMinNodes
UPGRADER_ROLE
: authorize UUPS upgrades (_authorizeUpgrade
)
Call-gating (not roles):
OnlyStakingContract
(callernodeCommitteeStaking
):joinCommittee
,leaveCommittee
,updateNodeStake
OnlyNode
(calleraddress(this)
):finaliseEpoch
,moveToNextEpoch
➜ design implies self‑calls only
SomniaStaking upgradeable
Purpose: Accept validator self‑stake and delegated stake (native ETH), keep reward accounting, gate committee joins/leaves/updates into NodeCommittee
, manage validator delegate‑rate changes, and enforce minimums.
Initialization:
initialize(address upgrader, address nodeCommitteeAddress, uint256 initialUnstakePeriod, uint256 initialMinStake, uint256 initialDefaultDelegateStakeRate)
Grants:
DEFAULT_ADMIN_ROLE
toupgrader
,msg.sender
, and (also)address(0)
;UPGRADER_ROLE
toupgrader
;NODE_CALLER_ROLE
toaddress(0)
Sets:
unstakePeriod
,minStake
,nextEpochMinStake
,defaultDelegateStakeRate
minSelfStake = 50% of minStake
(constantMIN_SELF_STAKE_PERCENTAGE = 5000
)
Key state:
Params:
unstakePeriod
,minStake
,nextEpochMinStake
,defaultDelegateStakeRate
,minSelfStake
Totals:
totalStaked
Link:
address nodeCommittee
Per‑validator:
mapping(address => Stake) stakes
(own stake, delegated, rewards, delegate rate, epoch tracking)Delegations:
delegations[staker][]
,delegationInfoByValidator[staker][validator]
(amount, pendingRewards, RPS snapshot),accumulatedRewardsPerShare[validator]
Pending:
pendingRateChanges[validator]
Next‑epoch buffers:
nextEpochOwnStakes[]
,nextEpochDelegatedStakes[]
Understaked handling:
validatorsMarkedForRemoval
,validatorsToRemove[]
Unstake flow:
unstakeRequestTime[validator]
Roles & powers:
DEFAULT_ADMIN_ROLE
: admin setters; can callemergencyRemoveValidator
,emergencyApplyRateChange
, set paramsUPGRADER_ROLE
: authorize UUPS upgradesSTAKER_ROLE
: required for most validator actions (stake, join committee, claim validator rewards, etc.)NODE_CALLER_ROLE
&DEVELOPMENT_ADMIN
: “OnlyDevs” gate for certain ops (nodeCallerStakeAndJoinCommittee
,addStakers
,emergencyUnstakeRequest
)Custom grant override: holders of
DEVELOPMENT_ADMIN
can grantDEVELOPMENT_ADMIN
andSTAKER_ROLE
Privileged Roles systemwide summary
NodeCommittee
DEFAULT_ADMIN_ROLE
: set staking contract address, burn fee %, min nodesUPGRADER_ROLE
: approve upgradesCall gates: Only staking contract may add/remove/update nodes; epoch transition functions are self‑call only (
OnlyNode
)
SomniaStaking
DEFAULT_ADMIN_ROLE
: general admin, removes understaked validators, sets the unstake period, sets the minimum stake amount, sets the max total validator stake amount, apply rate changes, sets the default delegated stake rate for new validatorsUPGRADER_ROLE
: approve upgradesSTAKER_ROLE
: required for most validator actions (create stake, stake/join, claim validator rewards, set delegate rate, etc.)DEVELOPMENT_ADMIN
: Stakes tokens and joins the committee on behalf of a node, emergency unstake, adds stakersNODE_CALLER_ROLE
: same asDEVELOPMENT_ADMIN
role
Potential Risks
Validators Can Stuck Forever: If the protocol’s minNodes
constraint prevents the committee size from reaching zero, a final validator could become permanently locked in the set, unable to exit or withdraw stake — leaving funds stranded indefinitely if the network ceases operation.
Emergency Risk: The protocol contains multiple emergency and admin-only functions granting owners significant control, including forcibly removing validators, altering staking parameters, and upgrading core contracts. This centralization creates a high governance risk where misuse or compromise of admin keys could disrupt or seize protocol operations.
Single Points of Failure and Control: The project is fully or partially centralized, introducing single points of failure and control. This centralization can lead to vulnerabilities in decision-making and operational processes, making the system more susceptible to targeted attacks or manipulation.
Administrative Key Control Risk: The digital contract architecture relies on administrative keys for critical operations. Centralized control over these keys presents a significant security risk, as compromise or misuse can lead to unauthorized actions or loss of funds.
Flexibility and Risk in Contract Upgrade: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides flexibility in addressing issues and evolving the project, it also introduces risks if upgrade processes are not properly managed or secured, potentially allowing for unauthorized changes that could compromise the project's integrity and security.
Single Points of Failure and Control: The project is fully or partially centralized, introducing single points of failure and control. This centralization can lead to vulnerabilities in decision-making and operational processes, making the system more susceptible to targeted attacks or manipulation.
Absence of Time-lock Mechanisms for Critical Operations: Without time-locks on critical operations, there is no buffer to review or revert potentially harmful actions, increasing the risk of rapid exploitation and irreversible changes.
Address Zero as Privileged Super-Admin: The protocol grants critical administrative privileges to address(0)
during initialization, including DEFAULT_ADMIN_ROLE
and NODE_CALLER_ROLE
This unconventional design creates trust assumptions around a non-executable address and restricts legitimate administrative operations to require complex workarounds, while creating potential attack vectors if the privilege model is misunderstood or circumvented.
Epoch Transition Manipulation Risk: The three-phase epoch system (CURRENT → NEXT → FUTURE) relies entirely on internal contract calls without external validation, timing constraints, or decentralized triggers. This design allows entities capable of triggering epoch transitions to manipulate when validator committees rotate and rewards are distributed, potentially disrupting normal committee rotation patterns or favoring specific validators.
Role Privilege Escalation Pathways: The role system creates multiple pathways for privilege escalation through DEFAULT_ADMIN_ROLE
ability to grant any role and DEVELOPMENT_ADMIN
override capabilities in the custom grantRole()
function. The system lacks role hierarchy limits, separation of duties for sensitive role assignments, allowing compromised admin accounts to rapidly expand their privileges.
Economic Parameter Manipulation Through Staking Controls: The protocol allows validators to self-set delegation rates up to 100% while providing admin accounts multiple pathways to create stakes on behalf of others via nodeCallerStakeAndJoinCommittee()
and addStakers()
. This combination enables privileged accounts to establish favorable economic arrangements or manipulate committee composition through strategic stake allocation without market-based constraints.
Off-chain Consensus to On-chain Execution Verification Gap: The protocol describes requiring 2/3 of committee nodes to sign enshrined transactions, yet the on-chain OnlyNode modifier only verifies msg.sender address(this)
without validating that the required consensus threshold was actually achieved. This creates a critical gap where transactions appearing to originate from the contract itself are automatically trusted without cryptographic proof that 2/3 of validators actually agreed to execute them, potentially allowing unauthorized execution of critical functions.
Node Implementation Dependency Risk: Critical protocol operations depend entirely on off-chain node software to "craft transactions" that appear to originate from address(this)
or address(0)
. This architecture creates a single point of failure where vulnerabilities, bugs, or malicious modifications in the node implementation could compromise the entire protocol's security model. The system lacks on-chain validation mechanisms to verify the integrity or authenticity of these crafted transactions, making it dependent on the security of external software components.
Consensus Threshold Enforcement Failure: While the protocol claims to require 2/3 consensus for critical operations, there is no on-chain mechanism to verify this threshold was met before executing functions like finaliseEpoch()
or moveToNextEpoch()
. The system relies entirely on off-chain coordination and trust that nodes will only sign transactions when appropriate consensus is reached, but provides no cryptographic proof or verification that prevents execution with insufficient consensus or fraudulent signature aggregation.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2025-1210 | Missing Self‑Stake Check On Committee Entry | accepted | High | |
F-2025-1208 | Last Minute Delegation Captures Full Epoch's Rewards With Instant Exit | fixed | High | |
F-2025-1208 | Signature Replay Attack | mitigated | High | |
F-2025-1208 | DOS on reward settlement | fixed | High | |
F-2025-1223 | Insufficient Authorization Model Leads to Privilege Escalation | fixed | Medium | |
F-2025-1209 | Disproportionate Reward Allocation for Minimal Delegations | accepted | Medium | |
F-2025-1208 | Delegator Rug / Retroactive Rate Change | mitigated | Medium | |
F-2025-1208 | Cooldown can be “pre‑armed” on day 1 | fixed | Medium | |
F-2025-1229 | Absence of Constraints on Minimum Stake Value | accepted | Low | |
F-2025-1229 | Vote Weight Snapshot Not Repriced After Stake Reduction | fixed | Low |
Identify vulnerabilities in your smart contracts.
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/somnia-chain___somnia-protocol→ |
Initial commit | 35a4ea285813c94b38297afdf9f9ad28518b5b22 |
Remediation commit | d0f353dff8bb36143cfae9fbf18c2d6ff701708a |
Whitepaper | N/A |
Requirements | N/A |
Technical Requirements | N/A |
Scope Details
- Initial commit
- 35a4ea285813c94b38297afdf9f9ad28518b5b22
- Remediation commit
- d0f353dff8bb36143cfae9fbf18c2d6ff701708a
- Whitepaper
- N/A
- Requirements
- N/A
- Technical Requirements
- N/A
Assets in Scope
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Somnia / Somnia-Contracts, 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, 7 invariants were tested over 500,000 runs each. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
---|---|---|
Stake and Join Committee with Random Stake Amount | Passed | 500,000 |
Stake and Join Committee with Random Stake Amount (Second Call) | Passed | 500,000 |
Delegate Stake with Random Delegation Amount | Passed | 500,000 |
Redelegate Stake with Two Random Delegation Amounts | Passed | 500,000 |
Delegate Stake with Two Users and Random Amounts | Passed | 500,000 |
Undelegate Stake with Random Undelegation Amount | Passed | 500,000 |
Reward Distribution with Random Epoch Reward | Failed | 500,000 |
Invariant
- Stake and Join Committee with Random Stake Amount
Test Result
- Passed
Run Count
- 500,000
Invariant
- Stake and Join Committee with Random Stake Amount (Second Call)
Test Result
- Passed
Run Count
- 500,000
Invariant
- Delegate Stake with Random Delegation Amount
Test Result
- Passed
Run Count
- 500,000
Invariant
- Redelegate Stake with Two Random Delegation Amounts
Test Result
- Passed
Run Count
- 500,000
Invariant
- Delegate Stake with Two Users and Random Amounts
Test Result
- Passed
Run Count
- 500,000
Invariant
- Undelegate Stake with Random Undelegation Amount
Test Result
- Passed
Run Count
- 500,000
Invariant
- Reward Distribution with Random Epoch Reward
Test Result
- Failed
Run Count
- 500,000
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.