Introduction
We express our gratitude to the Neemo Finance team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Neemo Staked Astar is a staking protocol operating across both L1 and L2 chains.
Document | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for Neemo Finance |
| Audited By | Olesia Bilenka |
| Approved By | Przemyslaw Swiatowiec |
| Website | https://neemo.finance/→ |
| Changelog | 10/01/2025 - Preliminary Report |
| 04/02/2025 - Final Report | |
| Platform | Astar, Soneium |
| Language | Solidity |
| Tags | Staking; Upgradable; Layer 2; ERC-20; Claims |
| Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Neemo Finance
- Audited By
- Olesia Bilenka
- Approved By
- Przemyslaw Swiatowiec
- Website
- https://neemo.finance/→
- Changelog
- 10/01/2025 - Preliminary Report
- 04/02/2025 - Final Report
- Platform
- Astar, Soneium
- Language
- Solidity
- Tags
- Staking; Upgradable; Layer 2; ERC-20; Claims
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
|---|---|
| Repository | https://github.com/neemo-finance/neemo-staked-astar→ |
| Commit | 4a04087 |
| Remediation Commit | d9ef85d |
Review Scope
- Commit
- 4a04087
- Remediation Commit
- d9ef85d
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are provided and comprehensive.
Technical description is provided and comprehensive.
Code quality
The code mostly follows best practices.
Several redundant code parts were identified.
The development environment is configured.
Test coverage
Code coverage of the project is 90.25% (branch coverage).
Deployment and basic user interactions are covered with tests.
Some negative cases coverage is missed.
System Overview
Neemo Staked Astar is a staking protocol operating across both L1 and L2 chains with the following contracts:
DappStakingManager - is an upgradeable staking contract that allows users to deposit native tokens and receive liquid staking tokens (LST) in return, based on the current exchange rate. Users can stake tokens through dAppStaking, claim rewards, and request withdrawals, which are processed at the end of specific staking periods (batches). The contract manages multiple batches, tracking user balances and staking metadata. It enables linear bonus rewards, distributed over defined eras, and synchronizes state between Layer 1 (L1) and Layer 2 (L2) using a multichain manager. Fees are applied during reward distribution and LST minting, with a portion of the rewards or minted tokens allocated to the Neemo treasury. Exchange rates are dynamically calculated based on the total staked tokens and rewards, ensuring accurate LST issuance and withdrawal amounts. The contract also supports referral-based deposits, allowing users to refer others and track referrals.
DappStakingManagerL2 - is an upgradeable staking contract designed to handle staking operations, reward distribution, and withdrawal processes for the Neemo platform on Layer 2 (L2). The contract facilitates depositing ASTR tokens, minting liquid staking tokens (NsASTR), and managing withdrawals either through standard withdrawal requests synchronized with Layer 1 (L1) or via rapid withdrawal with associated fees.
The contract ensures synchronization with L1 by leveraging a multichain manager to update exchange rates, process claims, and manage state transitions, such as unlocking or finalizing staking batches. It enforces configurable thresholds for staking and rapid withdrawal, while also supporting referral-based deposits to track user referrals.
Key functionalities include minting NsASTR for deposited tokens, handling staking thresholds, distributing rewards, and ensuring accurate synchronization with L1 to maintain consistency. The contract also applies rapid withdrawal fees and a deviation limit.
NsASTR - is an ERC-20 compliant token contract designed to represent staked ASTR tokens on the Neemo platform. This token is tightly integrated with the DappStakingManagerL2 contract, which acts as its sole manager, ensuring controlled and secure minting and burning operations.
MultichainManager - is a contract that manages multichain operations for the Neemo ecosystem, enabling seamless communication between Layer 1 and Layer 2 using Chainlink CCIP. It facilitates key processes such as token minting, state synchronization, and handling staking and withdrawal requests across chains. The contract interacts with the DappStakingManager and DappStakingManagerL2 contracts to ensure consistent state management and user balances.
The contract supports minting operations by processing requests from L1 and enabling the minting of tokens on L2, while also syncing exchange rates and staking data between layers. It tracks failed cross-chain messages and allows retries or recovery through a retry mechanism. Additionally, it uses configurable gas limits for Chainlink callbacks to optimize transaction costs and supports secure token rescues in case of incorrect transfers.
PauseActions \- is a library that defines constants representing various pause action types for controlling functionalities within the Neemo ecosystem contracts.
Roles \- is a library that defines bytes32 constants representing various roles used for access control within the Neemo ecosystem.
Configs \- is a library that defines configuration keys and constants that are essential for managing and operating the Neemo protocol.
Privileged roles
DappStakingManager:
The NEEMO_DEV_ROLE in the DappStakingManager contract has the authority to perform several privileged actions, such as updating the treasury address, configuring critical protocol parameters like the reward fee, minting fee, and exchange rate deviation limits, and setting the number of eras for bonus reward distribution. This role can also update the ending era for the current staking period, change the multichain manager address, and toggle the staking functionality on or off. Additionally, the role has access to lifecycle functions like reprice and syncPeriod, which are essential for managing staking operations.
The TIMELOCK_ROLE has the authority to manage upgrades to the contract by authorizing new implementations. It can also force synchronization of the staking period via the forceSyncPeriod function, ensuring the protocol remains operational in cases where automatic synchronization fails.
The PAUSER_ROLE is responsible for pausing specific functionalities of the contract, such as deposits, withdrawals, minting, or claiming tokens, while the UNPAUSER_ROLE can resume these functionalities.
DappStakingManagerL2:
the NEEMO_DEV_ROLE holds several privileges, including the ability to start the staking manager by initializing key parameters like the nsASTR address, the multichain manager, and the exchange rate. It can also update critical configuration parameters such as the rapid withdrawal fee, minimum staking threshold, rapid liquidity threshold, and exchange rate deviation limits. This role can modify the ending era of the current staking period and enable or disable staking functionality.
The TIMELOCK_ROLE has the authority to upgrade the contract by authorizing new implementations and can rescue funds or tokens from the contract.
The PAUSER_ROLE has the ability to pause specific functionalities of the contract, including deposits, withdrawals, minting, syncing, and repricing. This role is essential for temporarily disabling certain operations.. The UNPAUSER_ROLE complements this by being able to unpause these functionalities.
MultichainManager:
The NEEMO_DEV_ROLE has the authority to start the multichain manager by setting up key addresses such as the sourceChainAstar, dappStakingManager, and the remoteMultichainManager. This role also configures the destination chain selector, claiming chain ID, and can adjust the gas amount required for cross-chain transactions. Additionally, it can set the minimum mint threshold.
The TIMELOCK_ROLE is empowered to set or update the remote multichain manager address, ensuring proper alignment with the multichain setup. It can also rescue funds or tokens from the contract.
The PAUSER_ROLE can temporarily disable critical functionalities like sending messages or processing cross-chain operations.
Potential Risks
Scope Definition and Security Guarantees: The audit does not cover all code in the repository. Contracts outside the audit scope may introduce vulnerabilities, potentially impacting the overall security due to the interconnected nature of smart contracts.
Dependency on External Logic for Implemented Logic: The implemented DappStakingManager logic highly depends on external contracts (dAppStaking) not covered by the audit. The DappStakingManager, MultichainManager, DappStakingManagerL2 depend on DappStakingManagerL2 not covered by the audit. This reliance introduces risks if these external contracts are compromised or contain vulnerabilities, affecting the audited project's integrity.
System Reliance on External Contracts: The functioning of the system significantly relies on specific external contracts. Any flaws or vulnerabilities in these contracts adversely affect the audited project, potentially leading to security breaches or loss of funds.
Owner's Unrestricted State Modification: The absence of restrictions on state variable modifications by the owner leads to arbitrary changes, affecting contract integrity and user trust, especially during critical operations like minting phases.
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.
Flexibility and Risk in Contract Upgrades: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides exibility 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.
Flexibility and Risk in Contract Upgrades: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides exibility 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.
Outdated Message Processing Risk: In the MultichainManager contract, failed messages can be retried using the retryFailedMessage function. However, these messages may become outdated by the time they are retried, such as an old exchange rate synchronization. Processing such outdated messages could lead to inconsistencies or incorrect state updates within the system. Additionally, during the time it takes for calls between L1 and L2 to be processed, various state changes may occur, such as updates in asset balances, staking activities, or governance decisions. Processing such outdated messages could lead to inconsistencies or incorrect state updates within the system.
Insufficient Fee Balance Risk: the contract system relies on the MultichainManager to cover the fees required for cross-chain message transmission. If the MultichainManager lacks sufficient balance to pay these fees, critical cross-chain communication will fail, potentially disrupting the system's operations.
Critical Functionality Pausing Risk: the contracts include mechanisms to pause critical functionalities, such as deposits and withdrawals. If these functionalities are paused, users may be unable to perform essential actions, leading to potential service disruption and user dissatisfaction.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2025-8113 | Inconsistent Ratios in DappStakingManagerL2 Causing Balances Discrepancies | fixed | Critical | |
| F-2025-8112 | Incorrect finalExchangeRate Calculation Leading to Locked Tokens in Contract | mitigated | Critical | |
| F-2025-8129 | Improper Addition to failedMessageIds in ccipReceive Causes Function Revert | fixed | High | |
| F-2025-8117 | Potential Unauthorized Fund Transfers via depositDelegateWithMint | fixed | High | |
| F-2025-8114 | Incorrect Batch Status Update in claimUnlockingTokens Causing Claim Failing | mitigated | High | |
| F-2025-8119 | State Desynchronization Between L1 and L2 During Contract Pause in _exchangeRateProtection | fixed | Medium | |
| F-2025-8118 | Address Mismatch Between L1 and L2 in NsAstr Minting | mitigated | Medium | |
| F-2025-8125 | Non-Strict Check in _claimUnlockingTokens Allows Excessive redeemAmount | mitigated | Low | |
| F-2025-8120 | Inconsistency Risk Due to Unsynchronized Configuration Functions Between L1 and L2 | mitigated | Low | |
| F-2025-8128 | Missing Event Emission in startMultichainManager Function | fixed | Observation |
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/neemo-finance/neemo-staked-astar→ |
| Commit | 4a0408739631e0d7d020cff6b7d221fb638a0f89 |
| Remediation Commit | d9ef85d3123a57ac0a1539d14144ab932591b9fb |
| Requirements | https://github.com/neemo-finance/neemo-staked-astar/blob/main/README.md→ |
Scope Details
- Commit
- 4a0408739631e0d7d020cff6b7d221fb638a0f89
- Remediation Commit
- d9ef85d3123a57ac0a1539d14144ab932591b9fb
Assets in Scope
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Neemo Staked Astar, 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 Foundry fuzzing suite was prepared for this task, and throughout the assessment, 11 invariants 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 |
|---|---|---|
The exchange rate must remain within the defined bounds of allowed deviation (RATE_INCREASE_LIMIT). If the deviation exceeds the limit or the rate falls below the previous value, the contract must automatically pause to prevent further operations. | Passed | 50K+ |
The total supply of LST tokens (totalLstSupply) must match the sum of all user balances in userLstBalances. | Passed | 50K+ |
| Deposit and withdrawal updates should be consistent. | Passed | 50K+ |
| Withdraw amount should not exceed deposited amount. | Passed | 50K+ |
reprice function shouldl correctly updates the exchange rate based on deposits, withdrawals, and rewards. | Passed | 50K+ |
| Bonus reward should be appropriately incorporated into the reprice calculations. | Passed | 50K+ |
User balances must correctly reflect deposits and minting actions when deposits are made via depositDelegateWithMint or depositDelegate | Passed | 50K+ |
| Correct fees must be deducted when minting occurs, ensuring the mint fee logic is applied accurately. | Passed | 50K+ |
| User's nsASTR balance must increase by the correct amount after a successful mint operation, reflecting the minted tokens accurately. | Passed | 50K+ |
The exchange rate must reflect the correct ratio of totalAstarDeposit to totalLstSupply after rewards are added, verifying accurate price updates. | Passed | 50K+ |
Consistency must be maintained between the L1 and L2 exchange rates (dappStakingManager.getRate() and dappStakingManagerL2.lastExchangeRate()), ensuring synchronization between layers. | Passed | 50K+ |
Invariant
- The exchange rate must remain within the defined bounds of allowed deviation (
RATE_INCREASE_LIMIT). If the deviation exceeds the limit or the rate falls below the previous value, the contract must automatically pause to prevent further operations. Test Result
- Passed
Run Count
- 50K+
Invariant
- The total supply of LST tokens (
totalLstSupply) must match the sum of all user balances inuserLstBalances. Test Result
- Passed
Run Count
- 50K+
Invariant
- Deposit and withdrawal updates should be consistent.
Test Result
- Passed
Run Count
- 50K+
Invariant
- Withdraw amount should not exceed deposited amount.
Test Result
- Passed
Run Count
- 50K+
Invariant
repricefunction shouldl correctly updates the exchange rate based on deposits, withdrawals, and rewards.Test Result
- Passed
Run Count
- 50K+
Invariant
- Bonus reward should be appropriately incorporated into the reprice calculations.
Test Result
- Passed
Run Count
- 50K+
Invariant
- User balances must correctly reflect deposits and minting actions when deposits are made via
depositDelegateWithMintordepositDelegate Test Result
- Passed
Run Count
- 50K+
Invariant
- Correct fees must be deducted when minting occurs, ensuring the mint fee logic is applied accurately.
Test Result
- Passed
Run Count
- 50K+
Invariant
- User's nsASTR balance must increase by the correct amount after a successful mint operation, reflecting the minted tokens accurately.
Test Result
- Passed
Run Count
- 50K+
Invariant
- The exchange rate must reflect the correct ratio of
totalAstarDeposittototalLstSupplyafter rewards are added, verifying accurate price updates. Test Result
- Passed
Run Count
- 50K+
Invariant
- Consistency must be maintained between the L1 and L2 exchange rates (
dappStakingManager.getRate()anddappStakingManagerL2.lastExchangeRate()), ensuring synchronization between layers. 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.