We express our gratitude to the Galileo Protocol team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
The Galileo Protocol is a cutting-edge tokenisation platform that aims to revolutionise the authentication and ownership of luxury goods and real-world assets.
Document
Review Scope
The system users should acknowledge all the risks summed up in the risks section of the report
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 clear and concise.
Run instructions are provided.
Technical specification is provided.
The NatSpec documentation is sufficient.
The development environment is configured.
Solidity Style Guide violations.
Code coverage of the project is 87.96% (branch coverage).
Deployment and basic user interactions are covered with tests.
Negative cases coverage is partially missed.
Interactions involving multiple users are tested.
Not all branches are covered by tests.
The Galileo Protocol Staking Platform is an advanced, multi-functional staking solution that integrates ERC721 Soulbound Tokens (SBTs) and staking mechanics for both Nebula Odyssey NFTs and LEOX ERC20 tokens. The platform is designed to support multiple NFT collections and enables participants to earn rewards while accumulating loyalty points that unlock various benefits within the Galileo ecosystem.
The core of the system is divided into two main contracts:
GalileoSoulBoundToken: This contract manages Soulbound Tokens (SBTs), which are issued to users upon staking and burned upon unstaking. These tokens serve as proof of a user’s staked position and are non-transferable, embodying the concept of binding ownership tied to specific staking events.
GalileoStaking: This contract handles the staking logic for NFTs and associated LEOX tokens. Users can stake NFTs from supported collections and optionally lock up LEOX tokens to earn higher rewards. The contract maintains information about staking positions, calculates rewards based on various parameters (e.g., staking duration, token traits), and supports reward distribution based on predefined reward windows. Pools and multipliers for boosting staking rewards are configurable by admins.
The platform ensures flexibility by supporting multiple NFT collections and implementing an upgradeable configuration system. The staking pools can be managed to include various reward tiers, time-locked staking options, and dynamic reward rates, making it adaptable for diverse staking strategies.
The files in the scope:
GalileoSoulBoundToken.sol: Handles Soulbound Tokens (SBTs), issuing them when NFTs are staked and burning them upon unstaking. This contract overrides standard ERC721 transfer and approval functions to enforce the non-transferable nature of SBTs, serving as immutable proof of staked positions.
GalileoStaking.sol: Implements the main staking logic for NFTs and LEOX ERC20 tokens. It supports staking for multiple collections, calculates rewards based on traits and lock-up periods, and configures dynamic reward windows. This contract manages the issuance and burning of SBTs and enables admins to configure staking pools, multipliers, and tax rates.
GalileoStakingErrors.sol: Defines custom error messages for different failure scenarios, enhancing the readability and specificity of revert messages across the staking contract.
GalileoStakingStorage.sol: Provides storage structures for staking positions, pool configurations, and reward windows. It maintains the state required for managing multi-collection staking and dynamic configurations.
IGalileoSoulBoundToken.sol: Standard interface for Soulbound Token operations, ensuring consistency in the issuance and burning of SBTs across the staking platform.
GalileoSoulBoundToken.sol:
owner: Can update the base URI and transfer ownership.
ADMIN_ROLE: Can issue and burn Soulbound Tokens.
GalileoStaking.sol:
ADMIN_ROLE:
Contract Management: Can pause/unpause the contract.
Configuration Updates: Manages collection, pool, and multiplier configurations.
Rewards & Emission Control: Updates emission rates, configures reward windows, and adjusts tax rates.
Withdrawals: Can withdraw accumulated tax from the contract.
DEFAULT_ADMIN_ROLE:
Full Control: Can assign/revoke roles within the contract.
VALIDATOR_ROLE:
Voucher Verification: Validates staking vouchers used in off-chain signing for StakeTokens
authenticity.
Dynamic Array Iteration Gas Limit Risks: The project iterates over large dynamic arrays, which leads to excessive gas costs, risking denial of service due to out-of-gas errors, directly impacting contract usability and reliability.
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.
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.
Administrative Control Over Critical Parameters and Contract Pausing: The admin role has the ability to pause/unpause the contract and modify critical parameters such as reward rates, tax rates, staking multipliers, and pool configurations at any time. This centralized control can result in sudden changes that impact user rewards, staking incentives, and expected returns. As a result, users may face unexpected alterations in staking conditions, potentially leading to dissatisfaction and loss of trust. Such centralization introduces the risk of mismanagement or malicious actions, which could significantly undermine the protocol's integrity and stability.
Staking Without Active Reward Windows: The contract allows users to stake their assets even when there are no active reward windows. If a user stakes during a period with no active reward window and no new reward cycles are added during their lock period, their funds will be locked in the contract for the entire duration without accruing any rewards. However, if a new reward cycle begins while their assets are still staked, they will start accumulating rewards from the start of that new cycle. In cases where no rewards are available throughout the lock period, users will be able to withdraw their staked NFTs and tokens via the emergency unstake function after the lock period ends. It is crucial for users to check the availability and timing of reward windows before staking and select their lock periods accordingly.
Lock-in During Emission Rate Changes: Users who stake their assets are locked into their staking period until its completion. If the emission rate (i.e., the reward rate) is altered during this lock-in period, stakers cannot withdraw or modify their positions to adapt to the new rates until the lock period expires. This inflexibility may result in users being bound to less favorable reward conditions than initially anticipated, potentially leading to reduced returns.
Irretrievable Excess or Mistakenly Sent Rewards: The staking contract is designed to distribute all rewards to users without any functionality for administrators or reward funders to withdraw rewards once added to the reward pool. While this ensures that rewards cannot be arbitrarily removed, it poses a risk where any excess rewards or tokens mistakenly sent to the contract cannot be reclaimed. This underscores the importance of precise reward funding.
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.
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2024-6401 | Missing Reward Updates in unstake Function Results in Incorrect Reward Calculations | Fixed | Critical | |
F-2024-6794 | Mismatch Between Staked NFT Token IDs and Minted SBT Token IDs Blocks Unstaking | Mitigated | Critical | |
F-2024-6455 | Lack of End Time Validation in rewardPerToken Function Leads to Over-Accumulation of Rewards | Fixed | High | |
F-2024-6428 | configurePool Resets State and Causes Incorrect Reward Calculations | Fixed | High | |
F-2024-6407 | Lack of Dedicated Reward Pool Tracking Allows Reward Drainage from Other Stakers | Fixed | High | |
F-2024-6376 | Unstaking Function Does Not Enforce Staking Lock Period | Fixed | High | |
F-2024-6457 | Lack of Emergency Withdrawal Mechanism | Fixed | Medium | |
F-2024-6451 | Unbounded Tax Rate in configurePool Allows Arbitrary Reward Manipulation | Fixed | Low | |
F-2024-6450 | Lack of Consistency Check for Staking Parameters in configureNewCollection Allows Incorrect Hierarchical Reward Structure | Fixed | Low | |
F-2024-6446 | Overlapping Reward Windows Create Inconsistencies in the Staking System | Fixed | Low |
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
Severity
Description
Severity
Description
Severity
Description
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.
The scope of the project includes the following smart contracts from the provided repository:
Scope Details
GalileoSoulBoundToken.sol
GalileoStaking.sol
GalileoStakingErrors.sol
GalileoStakingStorage.sol
IGalileoSoulBoundToken.sol
During the audit of Galileo Protocol, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Echidna →, 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 1,000,000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant
updateEmissionRate
function should correctly update the reward rate for the specified reward window index.Test Result
Run Count
Invariant
stake
function should handle multiple stakes of NFTs and LEOX tokens without interference. Each staker's staking position should correctly store their tokenId
, stakedLEOX
, citizen
, and timelockEndTime
. Each staker's LEOX balance should decrease by their respective staked amounts. The contract should handle multiple staking positions simultaneously.Test Result
Run Count
Invariant
stakeLeoxTokens
function can stake additional LEOX tokens on an existing staking position. The total staked LEOX amount in the staking position must reflect the sum of the initial and additional stakes. The staker's LEOX balance should decrease by the amount of the additional stake.Test Result
Run Count
Invariant
calculatePoints
function should return the correct number of points based on the staked LEOX amount. The calculated points should match the expected points calculated using the contract's formula.Test Result
Run Count
Invariant
calculateRewards
should be accurate based on staking duration and amount. Upon rewards withdrawal, the staker's LEOX balance should increase by the rewards amount minus any applicable taxes. The contract's LEOX balance should decrease by the rewards amount. The rewards withdrawal process should not affect other aspects of the staking position.Test Result
Run Count
Invariant
unstake
their assets. Upon unstaking, the staker should receive their staked LEOX and any accrued rewards, minus taxes. The staker's NFT should be returned to them. The staking position should be deleted from the contract after unstaking. The contract's balances should update correctly to reflect the unstaking.Test Result
Run Count
Invariant
rewardPerToken
function should calculate the reward per token accurately based on reward windows. The contract's rewardPerToken
value should match a manually calculated expected value within an acceptable tolerance.Test Result
Run Count
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.