Introduction
We express our gratitude to the Lumia team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Lumia is a robust liquidity infrastructure protocol interconnecting Layer 1’s and Layer 2’s with liquidity from CEXs and DEXs.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for Lumia |
Audited By | Viktor Raboshchuk, Viktor Lavrenenko |
Approved By | Ataberk Yavuzer |
Website | https://lumia.org/→ |
Changelog | 22/01/2025 - Preliminary Report |
29/01/2025 - Final Report | |
Platform | Lumia, BSC, Ethereum |
Language | Solidity |
Tags | Staking; Governance; Migration |
Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Lumia
- Audited By
- Viktor Raboshchuk, Viktor Lavrenenko
- Approved By
- Ataberk Yavuzer
- Website
- https://lumia.org/→
- Changelog
- 22/01/2025 - Preliminary Report
- 29/01/2025 - Final Report
- Platform
- Lumia, BSC, Ethereum
- Language
- Solidity
- Tags
- Staking; Governance; Migration
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
---|---|
Repository | https://github.com/orionprotocol/lumia/tree/audit/veOrn-veLumia-migration→ |
Commit | c8129b0 |
Review Scope
- Commit
- c8129b0
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are not complete:
Project overview is not detailed.
All roles in the system are missing.
Use cases are not complete.
For each contract all features are not described.
Technical description is not complete:
Run instructions are provided.
Technical specification is partially provided.
The NatSpec documentation is partially provided.
Code quality
The development environment is configured.
Best practices are not followed.
Test coverage
Code coverage of the project is 35.3% (branch coverage).
Deployment and basic user interactions are covered with tests.
Negative cases coverage is partially provided.
Interactions by several users are not tested thoroughly.
System Overview
Lumia is a governance protocol with staking functionality and migration functionality with the following contracts:
orionprotocol___lumia/contracts/legacy/governance/VeORNPausable.sol
- (VeOrnPausable
contract is a staking contract that allows users to lock their ORN tokens for specified durations to earn both standard and points-based rewards. The latter can be received in the dropLock mode of the contract. Inheriting fromTWBalance
,veORNStorage
, andStakingPoints
, it manages user deposits, calculates rewards, and facilitates withdrawals upon lock expiration. Moreover, the contract has a pausing functionality which allows the owner to pause the critical contract's functionality and migrate users' data to the Lumia chain).orionprotocol___lumia/contracts/governance/VeLumia/VeLumiaMigrated.sol
- (VeLumiaMigrated
contract is a staking contract that allows users to lock their Lumia for specified durations to earn both standard and points-based rewards. It contains additional functionality to allow the contract's admin to migrate the stakes and unclaimed rewards from theVeOrnPausable.sol
deployed on Ethereum and BSC.orionprotocol___lumia/contracts/governance/VeLumia/Migrator.sol
- (VeOrnMigrator
contract is a contract containing the migration functionality needed to migrate the data from theVeORNPausable
toVeLumiaMigrated
).orionprotocol___lumia/contracts/legacy/governance/veORNStorage.sol
- (veORNStorage
contract is a storage contract storing the necessary data for theVeORNPausable.sol
).orionprotocol___lumia/contracts/legacy/governance/base/Staking.sol
- (TheStaking
contract is an abstract Solidity smart contract enabling users to stake ORN and earn rewards. It tracks each user’s stake, accumulated rewards, and withdrawals. The contract manages a globalrewardRate
, calculates individual rewards based on stake size and time elapsed, and allows users to claim or unstake their funds).orionprotocol___lumia/contracts/governance/libraries/PausableLib.sol
- (The pausing functionality used byVeORNPausable
andVeLumiaMigrated
contracts).
Privileged roles
The owner of the
VeOrnPausable
contract which is stored by thesmartOwner
can:pause/unpause the contract.
change the address of the
smartVote
contract via thesetSmartVote()
function.change the admin of the contract via the
setAdmin()
function.update the airdrop state via the
updateAirdropState()
function.
The admin of the
VeOrnPausable
contract can:set rewards and pointRewards via
setRewards()
andsetPointsRewards()
functions.call the migration
moveORNToVeLumia()
function.
The owner of the
VeLumiaMigrated
contract can:change the address of the
smartVote
contract via thesetSmartVote()
function.change the admin of the contract via the
setAdmin()
function.update the airdrop state via the
updateAirdropState()
function.pause/unpause the contract.
The admin of the
VeLumiaMigrated
contract can:set rewards and pointRewards via
setRewards()
andsetPointsRewards()
functions.initiate the migration process via
migrateMany()
function.
Potential Risks
Relying on off-chain admin calculations: The off-chain migrating user data from VeOrnPausable
to VeLumiaMigrated
introduces significant risks. Inaccurate or manipulated off-chain data may lead to incorrect user balances, loss of unclaimed rewards, distorted governance power, and potential financial loss for users, undermining trust and raising legal concerns.
Reliance on Governance External Contracts: The functioning of the system significantly relies on the governance of external contracts. Any flaws or vulnerabilities in these contracts adversely affect the audited project, potentially leading to security breaches or loss of funds.
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 Risks: 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.
Reward Pool Depletion: If the reward pool balance runs out, users won't be able to withdraw their earned rewards or stakes, as there won't be enough funds to cover the claims. To prevent this, protocol administrators should regularly monitor the reward pool and top it up as needed to ensure it always has enough balance for payouts.
Admin's Unrestricted State Modification: The absence of restrictions on state variable modifications via functions setPointsRewards()
and setRewards()
by the admin can lead to sudden changes in rewards. This affects contract integrity and user trust, especially during critical operations like reward distribution. Moreover, the incorrect reward value and abnormal duration period for the rewards distribution can potentially result in no rewards being allocated to participants.
Reliance on Owner's Actions: Users who stake their tokens using the dropLock
option will encounter withdrawal restrictions and will only be able to retrieve their staked tokens once the isAirdropPassed
parameter is activated. Since this activation is performed exclusively by the contract owner through the updateAirdropState()
function, it creates a risk of delayed unlocked stakes.
The VeLumiaMigrated::_migrate()
function considers the option when the locktime of users' stakes on Ethereum or BSC is different from the same value of users' previous stakes on the Lumia chain resulting in the function choosing the minimum from both values. As a consequence, the user's bigger locktime value can be suddenly changed and replaced with a smaller one after the migration is over.
During the migration process, the ratio between 1 ORN and 1 Lumia token is maintained at 1:1, reflecting the rebranding of ORN to Lumia. While this ensures consistency in the migration, it's important to assess the rebranding process thoroughly to identify and address any potential issues that may have arisen.
This audit report focuses exclusively on the security assessment of the contracts within the specified review scope. Interactions with out-of-scope contracts are presumed to be correct and are not examined in this audit. We want to highlight that Interactions with contracts outside the specified scope, such as the implementation of the IOrionVoting
interface, legacy/governance/base/StakingPoints.sol,
and other out-of-scope contracts have not been verified or assessed as part of this report. While we have diligently identified and mitigated potential security risks within the defined scope, it is important to note that our assessment is confined to the isolated contracts within this scope. The overall security of the entire system, including external contracts and integrations beyond our audit scope, cannot be guaranteed. Users and stakeholders are urged to exercise caution when assessing the security of the broader ecosystem and interactions with external contracts. For a comprehensive evaluation of the entire system, additional audits and assessments outside the scope of this report are necessary. This report serves as a snapshot of the security status of the audited contracts within the specified scope at the time of the audit. We strongly recommend ongoing security evaluations and continuous monitoring to maintain and enhance the overall system's security.
The previously deployed versions of VeORN
and VeLumiaMigrated
lack storage gaps in their parent contracts, including StakingPoints
, TWBalance
, Staking
, Pausable
and VeOrnMigrator
. This omission introduces a significant risk of storage collisions if these parent contracts are modified in the future. Specifically, updates to the storage layouts—such as adding new state variables or restructuring existing ones—could overwrite or corrupt critical data in the child contracts, potentially leading to unpredictable behavior, security vulnerabilities, or complete contract failure.
Front-running During The Initialization Of The Implementation Contract: If the deployment and the initialization of the implementation contract, which is VeLumiaMigrated
, will not be handled within one transaction, it can cause the front-running of the VeLumiaMigrated::initialize()
function by the attacker which will lead to unexpected system behavior. In addition to that, the VeORNPausable
contract does not adhere to the best practices and does not implement the Initialization pattern, which creates a risk of the improper usage of the system.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2025-8366 | Improper DropLock State Management Leads to Incorrect Reward Calculations and Usability Issues | fixed | Medium | |
F-2025-8365 | Unpaused claimReward Allows Reward Duplication During Migration Process | fixed | Medium | |
F-2025-8359 | Unclaimed Rewards Not Properly Decremented After claimReward() Execution | fixed | Medium | |
F-2025-8358 | Mismatch Between Documentation and Contract Logic | fixed | Medium | |
F-2025-8356 | Version Incompatibility in Solidity Compilation | fixed | Low | |
F-2025-8354 | Incorrect Handling of Future Pause Timestamp Can Cause Unintended Pausing | fixed | Low | |
F-2025-8426 | CEI Pattern Violation in VeOrnPausable and VeLumiaMigrated Contracts | fixed | Observation | |
F-2025-8376 | Redundant Modifiers in pause() and unpause() Functions Decrease Code Quality | fixed | Observation | |
F-2025-8374 | Duplicated Token Name and Symbol Can Lead to Confusion | accepted | Observation | |
F-2025-8361 | Absence of Custom Errors Leading to Increased Gas Costs | 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/orionprotocol/lumia/tree/audit/veOrn-veLumia-migration→ |
Commit | c8129b00df29916efe2a8a4606acbe7d84603d2d |
Whitepaper | N/A |
Requirements | Requirements→ |
Technical Requirements | Requirements→ |
Scope Details
- Commit
- c8129b00df29916efe2a8a4606acbe7d84603d2d
- Whitepaper
- N/A
- Requirements
- Requirements→
- Technical Requirements
- Requirements→
Assets in Scope
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Lumia, Hacken followed its methodology by performing fuzz-testing on the project's main functions. 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, 25 invariants were tested over 20000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
---|---|---|
testFuzzCreateLock:: Ensures that users can create locks with varying amounts and durations. Validates that the locked amount and lock expiration time are accurately recorded in the contract's state. Confirms that the total stake within the contract correctly reflects the user's lock after advancing time by the lock duration. | Passed | 20K+ |
testFuzzIncreaseLock: Verifies that users can incrementally increase their existing lock amounts and extend durations . Checks that the total locked amount updates appropriately and that the lock's expiration time remains consistent post-increase. Ensures the contract's total stake accurately represents the user's enhanced stake after time progression. | Passed | 20K+ |
testFuzzWithdraw:: Tests the withdrawal mechanism by allowing users to withdraw their locked funds after the lock duration has fully elapsed. Confirms that upon withdrawal, the user's balance increases by the locked amount, and the contract's total stake decreases accordingly. Additionally, it verifies that users can successfully claim their accrued rewards before withdrawing, ensuring the integrity of the withdrawal process. | Passed | 20K+ |
testFuzzRewardsFlow:: Evaluates the entire rewards lifecycle by setting variable rewards and durations, creating locks, and advancing time to accrue rewards. Checks that users receive partial rewards proportional to their lock amounts and durations after half the reward period. Ensures that after the full reward duration, all rewards are claimable and that no residual rewards remain, maintaining accurate reward distribution. | Passed | 20K+ |
testFuzzTimeWeightedAverage:: Assesses the calculation of the time-weighted average of the total supply within the contract. Users create locks, and after a portion of the lock duration, some locks are increased. The test advances time and verifies that the TWA accurately reflects the changes in total supply over time, ensuring precise tracking of staking contributions relative to their durations. | Passed | 20K+ |
testFuzzTopUpInfluence:: Investigates how additional top-ups by the admin influence reward distribution. After initial top-ups and user lock creations, the admin performs further top-ups. The test advances time to accrue rewards and verifies that the reward ratios between users remain consistent despite the increased contract balance, ensuring that top-ups do not skew proportional reward allocations. | Passed | 20K+ |
testFuzzParallelLocks:: Ensures that multiple users can concurrently create locks with different amounts and durations. After advancing time, the test verifies that each user accrues rewards proportional to their respective locks. It also checks that all users can successfully claim their rewards independently, maintaining correct reward calculations and preventing cross-user interference. | Passed | 20K+ |
testFuzzTopUpThenFailWithdraw:: Validates that users without an active lock cannot withdraw funds. After the admin performs a top-up, an arbitrary user (excluded from known roles) attempts to withdraw without establishing a lock. The test expects the withdrawal to revert with a specific error (InvalidOperandOOG ), ensuring that the contract correctly enforces lock prerequisites for withdrawals and prevents unauthorized fund retrievals. | Passed | 20K+ |
testFuzz_balanceOfT:: Ensures that after user creates a lock with a specified balance0 the amountTW recorded in balanceOfTW for the user is at least equal to balance0 multiplied by the lock duration. This guarantees accurate tracking of time-weighted balances based on lock amounts and durations. | Passed | 20K+ |
testFuzz_balanceOfAv:: Validates that after user creates a lock and subsequently increases it by an additional amount, the average balance calculated by balanceOfAvg reflects the increased lock correctly. It ensures that the average considers both the initial and additional lock amounts over the specified time deltas, maintaining consistency in average calculations. | Passed | 20K+ |
testFuzz_toUint128:: This test verifies the toUint128 function's ability to accurately convert a non-negative int128 value to uint128 . It ensures that when provided with a valid positive input, the conversion retains the original value without alteration. Additionally, the test confirms that the function correctly reverts when attempting to convert negative int128 values, thereby preventing unintended underflows and maintaining type safety within the contract. | Passed | 20K+ |
testFuzz_toInt128:: This test assesses the toInt128 function's functionality by converting a uint128 value to an int128 . It ensures that the conversion succeeds when the input is within the permissible range (≤ MAX_U64x64 ), accurately reflecting the original uint128 value. The test also verifies that inputs exceeding MAX_U64x64 correctly trigger a revert, safeguarding against overflow and ensuring that only valid conversions are permitted, thus maintaining the integrity of signed integer operations. | Passed | 20K+ |
testFuzz_from_uint:: evaluates the from_uint method, which scales a uint256 input by shifting it left by 64 bits to achieve fixed-point representation. The test ensures that for inputs within the allowable range (≤ 0x7FFFFFFFFFFFFFFF ), the function returns the correctly scaled uint128 value. It also verifies that inputs exceeding this threshold cause the function to revert, thereby preventing overflow and ensuring precise fixed-point calculations essential for accurate mathematical operations within the contract. | Passed | 20K+ |
testFuzz_div18:: This test scrutinizes the div18 function, which performs division of x by y scaled by 10¹⁸ to maintain fixed-point precision. It ensures that the function returns accurate results when y is non-zero and the operation does not result in an overflow. The test also confirms that attempts to divide by zero or perform operations that exceed the maximum allowed value correctly revert, thereby enforcing safe arithmetic practices and maintaining the reliability of financial computations within the contract. | Passed | 20K+ |
testFuzz_div256:: The test function examines the div256 method, which divides x shifted left by 64 bits by y to achieve fixed-point division. The test ensures that when y is non-zero and the division does not lead to an overflow, the function returns the correct uint128 result. It also verifies that dividing by zero or causing an overflow appropriately triggers a revert, thereby safeguarding against invalid operations and ensuring that only mathematically sound divisions are executed within the contract. | Passed | 20K+ |
testFuzz_mul256:: This test evaluates the mul256 function, responsible for multiplying x by y and shifting the result right by 64 bits to maintain fixed-point precision. It ensures that for valid inputs where the product does not exceed uint64x64 limits, the function returns the accurate uint128 result. The test also checks that scenarios leading to overflow correctly cause the function to revert, thus preventing erroneous calculations and ensuring the integrity of multiplication operations within the contract's mathematical framework. | Passed | 20K+ |
testFuzz_div:: function tests the div method, which divides x shifted left by 64 bits by y to perform fixed-point division. The test verifies that the function returns precise results when y is non-zero and the division remains within uint64x64 bounds. It also ensures that dividing by zero or operations resulting in an overflow appropriately revert, thereby enforcing safe and accurate division practices essential for the contract's reliable mathematical computations. | Passed | 20K+ |
testFuzz_mul:: This test assesses the mul function, which multiplies x by y and shifts the product right by 64 bits to maintain fixed-point precision. It ensures that for inputs where the multiplication does not exceed uint64x64 limits, the function returns the correct uint128 result. Additionally, the test verifies that multiplying by zero yields zero and that any multiplication leading to an overflow correctly reverts, thereby maintaining the accuracy and safety of multiplication operations within the contract. | Passed | 20K+ |
testFuzz_exp_2:: function evaluates the exp_2 method, which calculates 2 raised to the power of x . The test ensures that for inputs below 0x400000000000000000 , the function returns accurate exponential values without causing an overflow. It also verifies that inputs exceeding this threshold correctly trigger a revert, thereby maintaining the mathematical correctness and preventing the computation of excessively large values that could compromise the contract's stability. | Passed | 20K+ |
testFuzz_sqrt:: This test examines the sqrt function, which computes the floor of the square root for a given uint128 input. It ensures that for non-zero inputs, the square of the result is less than or equal to x shifted left by 64 bits and that incrementing the result by one causes the square to exceed x shifted left by 64 bits. Additionally, the test confirms that the square root of zero correctly returns zero, thereby ensuring accurate and reliable square root calculations essential for precise mathematical operations within the contract. | Passed | 20K+ |
testFuzz_sqrt0:: function tests the sqrt0 method, which calculates the square root for non-negative int128 inputs. The test ensures that negative inputs correctly trigger a revert, preventing invalid operations. For non-zero inputs, it verifies that the square of the result does not exceed x shifted left by 64 bits and that incrementing the result by one causes the square to surpass this threshold. The test also confirms that the square root of zero returns zero, thereby maintaining mathematical accuracy and type safety in square root computations. | Passed | 20K+ |
testFuzz_createLock:: After creating a lock with valid fuzzed amounts and durations, the contract's total supply increases appropriately, the user's lock information (amount and expiration) is accurately recorded, and invalid inputs causing out-of-bound lock times correctly trigger reverts. | Passed | 20K+ |
testFuzz_getReward:: Following a lock creation and time warp, the accrued reward reported by getReward() aligns with the expected accumulation, and upon claiming, the user's balance increases by approximately the pending reward while preserving reward calculation accuracy. | Passed | 20K+ |
testFuzz_pauseAndUnpauseTimestamp:: Using a future timestamp to pause and then unpausing the contract ensures that the pause state activates only after the specified time, and subsequent unpausing correctly resets the pause state, with the contract's paused status reflecting these transitions accurately. | Failed | 20K+ |
testFuzz_ClaimRewardAfterTime:: After warping time and topping up funds to cover rewards, claiming rewards results in the user's balance increasing by an amount closely matching the pending reward, preserving correct reward distribution and ensuring no discrepancies occur during the claim process. | Passed | 20K+ |
testFuzz_WithdrawLock:: When attempting to withdraw funds, if the lock period has not expired, the transaction reverts as expected with the appropriate error message, and once the lock expires, withdrawal succeeds, resetting the user's token balance to zero and reducing the total supply accordingly. | Passed | 20K+ |
Invariant
testFuzzCreateLock::
Ensures that users can create locks with varying amounts and durations. Validates that the locked amount and lock expiration time are accurately recorded in the contract's state. Confirms that the total stake within the contract correctly reflects the user's lock after advancing time by the lock duration.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzIncreaseLock:
Verifies that users can incrementally increase their existing lock amounts and extend durations . Checks that the total locked amount updates appropriately and that the lock's expiration time remains consistent post-increase. Ensures the contract's total stake accurately represents the user's enhanced stake after time progression.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzWithdraw::
Tests the withdrawal mechanism by allowing users to withdraw their locked funds after the lock duration has fully elapsed. Confirms that upon withdrawal, the user's balance increases by the locked amount, and the contract's total stake decreases accordingly. Additionally, it verifies that users can successfully claim their accrued rewards before withdrawing, ensuring the integrity of the withdrawal process.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzRewardsFlow::
Evaluates the entire rewards lifecycle by setting variable rewards and durations, creating locks, and advancing time to accrue rewards. Checks that users receive partial rewards proportional to their lock amounts and durations after half the reward period. Ensures that after the full reward duration, all rewards are claimable and that no residual rewards remain, maintaining accurate reward distribution.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzTimeWeightedAverage::
Assesses the calculation of the time-weighted average of the total supply within the contract. Users create locks, and after a portion of the lock duration, some locks are increased. The test advances time and verifies that the TWA accurately reflects the changes in total supply over time, ensuring precise tracking of staking contributions relative to their durations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzTopUpInfluence::
Investigates how additional top-ups by the admin influence reward distribution. After initial top-ups and user lock creations, the admin performs further top-ups. The test advances time to accrue rewards and verifies that the reward ratios between users remain consistent despite the increased contract balance, ensuring that top-ups do not skew proportional reward allocations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzParallelLocks::
Ensures that multiple users can concurrently create locks with different amounts and durations. After advancing time, the test verifies that each user accrues rewards proportional to their respective locks. It also checks that all users can successfully claim their rewards independently, maintaining correct reward calculations and preventing cross-user interference.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzzTopUpThenFailWithdraw::
Validates that users without an active lock cannot withdraw funds. After the admin performs a top-up, an arbitrary user (excluded from known roles) attempts to withdraw without establishing a lock. The test expects the withdrawal to revert with a specific error (InvalidOperandOOG
), ensuring that the contract correctly enforces lock prerequisites for withdrawals and prevents unauthorized fund retrievals.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_balanceOfT::
Ensures that after user creates a lock with a specifiedbalance0
theamountTW
recorded inbalanceOfTW
for the user is at least equal tobalance0
multiplied by the lock duration. This guarantees accurate tracking of time-weighted balances based on lock amounts and durations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_balanceOfAv::
Validates that after user creates a lock and subsequently increases it by an additional amount, the average balance calculated bybalanceOfAvg
reflects the increased lock correctly. It ensures that the average considers both the initial and additional lock amounts over the specified time deltas, maintaining consistency in average calculations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_toUint128::
This test verifies thetoUint128
function's ability to accurately convert a non-negativeint128
value touint128
. It ensures that when provided with a valid positive input, the conversion retains the original value without alteration. Additionally, the test confirms that the function correctly reverts when attempting to convert negativeint128
values, thereby preventing unintended underflows and maintaining type safety within the contract.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_toInt128::
This test assesses thetoInt128
function's functionality by converting auint128
value to anint128
. It ensures that the conversion succeeds when the input is within the permissible range (≤ MAX_U64x64
), accurately reflecting the originaluint128
value. The test also verifies that inputs exceedingMAX_U64x64
correctly trigger a revert, safeguarding against overflow and ensuring that only valid conversions are permitted, thus maintaining the integrity of signed integer operations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_from_uint::
evaluates thefrom_uint
method, which scales auint256
input by shifting it left by 64 bits to achieve fixed-point representation. The test ensures that for inputs within the allowable range (≤ 0x7FFFFFFFFFFFFFFF
), the function returns the correctly scaleduint128
value. It also verifies that inputs exceeding this threshold cause the function to revert, thereby preventing overflow and ensuring precise fixed-point calculations essential for accurate mathematical operations within the contract.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_div18::
This test scrutinizes thediv18
function, which performs division ofx
byy
scaled by 10¹⁸ to maintain fixed-point precision. It ensures that the function returns accurate results wheny
is non-zero and the operation does not result in an overflow. The test also confirms that attempts to divide by zero or perform operations that exceed the maximum allowed value correctly revert, thereby enforcing safe arithmetic practices and maintaining the reliability of financial computations within the contract.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_div256::
The test function examines thediv256
method, which dividesx
shifted left by 64 bits byy
to achieve fixed-point division. The test ensures that wheny
is non-zero and the division does not lead to an overflow, the function returns the correctuint128
result. It also verifies that dividing by zero or causing an overflow appropriately triggers a revert, thereby safeguarding against invalid operations and ensuring that only mathematically sound divisions are executed within the contract.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_mul256::
This test evaluates themul256
function, responsible for multiplyingx
byy
and shifting the result right by 64 bits to maintain fixed-point precision. It ensures that for valid inputs where the product does not exceeduint64x64
limits, the function returns the accurateuint128
result. The test also checks that scenarios leading to overflow correctly cause the function to revert, thus preventing erroneous calculations and ensuring the integrity of multiplication operations within the contract's mathematical framework.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_div::
function tests thediv
method, which dividesx
shifted left by 64 bits byy
to perform fixed-point division. The test verifies that the function returns precise results wheny
is non-zero and the division remains withinuint64x64
bounds. It also ensures that dividing by zero or operations resulting in an overflow appropriately revert, thereby enforcing safe and accurate division practices essential for the contract's reliable mathematical computations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_mul::
This test assesses themul
function, which multipliesx
byy
and shifts the product right by 64 bits to maintain fixed-point precision. It ensures that for inputs where the multiplication does not exceeduint64x64
limits, the function returns the correctuint128
result. Additionally, the test verifies that multiplying by zero yields zero and that any multiplication leading to an overflow correctly reverts, thereby maintaining the accuracy and safety of multiplication operations within the contract.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_exp_2::
function evaluates theexp_2
method, which calculates 2 raised to the power ofx
. The test ensures that for inputs below0x400000000000000000
, the function returns accurate exponential values without causing an overflow. It also verifies that inputs exceeding this threshold correctly trigger a revert, thereby maintaining the mathematical correctness and preventing the computation of excessively large values that could compromise the contract's stability.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_sqrt::
This test examines thesqrt
function, which computes the floor of the square root for a givenuint128
input. It ensures that for non-zero inputs, the square of the result is less than or equal tox
shifted left by 64 bits and that incrementing the result by one causes the square to exceedx
shifted left by 64 bits. Additionally, the test confirms that the square root of zero correctly returns zero, thereby ensuring accurate and reliable square root calculations essential for precise mathematical operations within the contract.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_sqrt0::
function tests thesqrt0
method, which calculates the square root for non-negativeint128
inputs. The test ensures that negative inputs correctly trigger a revert, preventing invalid operations. For non-zero inputs, it verifies that the square of the result does not exceedx
shifted left by 64 bits and that incrementing the result by one causes the square to surpass this threshold. The test also confirms that the square root of zero returns zero, thereby maintaining mathematical accuracy and type safety in square root computations.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_createLock::
After creating a lock with valid fuzzed amounts and durations, the contract's total supply increases appropriately, the user's lock information (amount and expiration) is accurately recorded, and invalid inputs causing out-of-bound lock times correctly trigger reverts.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_getReward::
Following a lock creation and time warp, the accrued reward reported by getReward() aligns with the expected accumulation, and upon claiming, the user's balance increases by approximately the pending reward while preserving reward calculation accuracy.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_pauseAndUnpauseTimestamp::
Using a future timestamp to pause and then unpausing the contract ensures that the pause state activates only after the specified time, and subsequent unpausing correctly resets the pause state, with the contract's paused status reflecting these transitions accurately.Test Result
- Failed
Run Count
- 20K+
Invariant
testFuzz_ClaimRewardAfterTime::
After warping time and topping up funds to cover rewards, claiming rewards results in the user's balance increasing by an amount closely matching the pending reward, preserving correct reward distribution and ensuring no discrepancies occur during the claim process.Test Result
- Passed
Run Count
- 20K+
Invariant
testFuzz_WithdrawLock::
When attempting to withdraw funds, if the lock period has not expired, the transaction reverts as expected with the appropriate error message, and once the lock expires, withdrawal succeeds, resetting the user's token balance to zero and reducing the total supply accordingly.Test Result
- Passed
Run Count
- 20K+
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.