Halborn Logo

Staking-Module - Bonzo


Prepared by:

Halborn Logo

HALBORN

Last Updated 07/26/2024

Date of Engagement by: June 24th, 2024 - July 3rd, 2024

Summary

100% of all REPORTED Findings have been addressed

All findings

10

Critical

2

High

0

Medium

1

Low

2

Informational

5


1. Introduction

Bonzo engaged Halborn to conduct a security assessment on their smart contracts beginning on June 24th and ending on July 3rd. The security assessment was scoped to the smart contracts provided in the GitHub repository Bonzo Staking Module, commit hashes and further details can be found in the Scope section of this report.

The protocol utilizes Aave's Safety Module for staking and rewards distribution in WHBAR on the Hedera network. Stakers of any permitted asset by the emission manager can stake their assets in the Safety Module. The protocol ensures that stakers earn rewards in WHBAR, Hedera's wrapped HBAR token. The Safety Module acts as a backstop in case of a shortfall event, enhancing the protocol's security. This system is designed to incentivize users to contribute to the protocol's safety while earning rewards for their participation.

2. Assessment Summary

The team at Halborn was provided one week for the engagement and assigned one full-time security engineer to check the security of the smart contract. The security engineer is a blockchain and smart-contract security expert with advanced penetration testing, smart-contract hacking, and deep knowledge of multiple blockchain protocols.

The purpose of this assessment is to:

    • Ensure that smart contract functions operate as intended.

    • Identify potential security issues with the smart contracts.

In summary, Halborn identified some security risks that were mostly addressed by the Bonzo team.

3. Test Approach and Methodology

Halborn performed a combination of manual review of the code and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of the smart contract assessment. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of smart contracts and can quickly identify items that do not follow security best practices.

The following phases and associated tools were used throughout the term of the assessment:

    • Research into the architecture, purpose, and use of the platform.

    • Smart contract manual code review and walkthrough to identify any logic issues.

    • A thorough assessment of safety and usage of critical Solidity variables and functions in scope that could lead to arithmetic related vulnerabilities.

    • Manual testing by custom scripts.

    • Graphing out functionality and contract logic/connectivity/functions (solgraph).

    • Static Analysis of security for scoped contract, and imported functions. (Slither).

    • Local or public testnet deployment (Brownie, Remix IDE).

4. RISK METHODOLOGY

Every vulnerability and issue observed by Halborn is ranked based on two sets of Metrics and a Severity Coefficient. This system is inspired by the industry standard Common Vulnerability Scoring System.
The two Metric sets are: Exploitability and Impact. Exploitability captures the ease and technical means by which vulnerabilities can be exploited and Impact describes the consequences of a successful exploit.
The Severity Coefficients is designed to further refine the accuracy of the ranking with two factors: Reversibility and Scope. These capture the impact of the vulnerability on the environment as well as the number of users and smart contracts affected.
The final score is a value between 0-10 rounded up to 1 decimal place and 10 corresponding to the highest security risk. This provides an objective and accurate rating of the severity of security vulnerabilities in smart contracts.
The system is designed to assist in identifying and prioritizing vulnerabilities based on their level of risk to address the most critical issues in a timely manner.

4.1 EXPLOITABILITY

Attack Origin (AO):
Captures whether the attack requires compromising a specific account.
Attack Cost (AC):
Captures the cost of exploiting the vulnerability incurred by the attacker relative to sending a single transaction on the relevant blockchain. Includes but is not limited to financial and computational cost.
Attack Complexity (AX):
Describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability. Includes but is not limited to macro situation, available third-party liquidity and regulatory challenges.
Metrics:
EXPLOITABILIY METRIC (mem_e)METRIC VALUENUMERICAL VALUE
Attack Origin (AO)Arbitrary (AO:A)
Specific (AO:S)
1
0.2
Attack Cost (AC)Low (AC:L)
Medium (AC:M)
High (AC:H)
1
0.67
0.33
Attack Complexity (AX)Low (AX:L)
Medium (AX:M)
High (AX:H)
1
0.67
0.33
Exploitability EE is calculated using the following formula:

E=meE = \prod m_e

4.2 IMPACT

Confidentiality (C):
Measures the impact to the confidentiality of the information resources managed by the contract due to a successfully exploited vulnerability. Confidentiality refers to limiting access to authorized users only.
Integrity (I):
Measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of data stored and/or processed on-chain. Integrity impact directly affecting Deposit or Yield records is excluded.
Availability (A):
Measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability. This metric refers to smart contract features and functionality, not state. Availability impact directly affecting Deposit or Yield is excluded.
Deposit (D):
Measures the impact to the deposits made to the contract by either users or owners.
Yield (Y):
Measures the impact to the yield generated by the contract for either users or owners.
Metrics:
IMPACT METRIC (mIm_I)METRIC VALUENUMERICAL VALUE
Confidentiality (C)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Integrity (I)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Availability (A)None (A:N)
Low (A:L)
Medium (A:M)
High (A:H)
Critical (A:C)
0
0.25
0.5
0.75
1
Deposit (D)None (D:N)
Low (D:L)
Medium (D:M)
High (D:H)
Critical (D:C)
0
0.25
0.5
0.75
1
Yield (Y)None (Y:N)
Low (Y:L)
Medium (Y:M)
High (Y:H)
Critical (Y:C)
0
0.25
0.5
0.75
1
Impact II is calculated using the following formula:

I=max(mI)+mImax(mI)4I = max(m_I) + \frac{\sum{m_I} - max(m_I)}{4}

4.3 SEVERITY COEFFICIENT

Reversibility (R):
Describes the share of the exploited vulnerability effects that can be reversed. For upgradeable contracts, assume the contract private key is available.
Scope (S):
Captures whether a vulnerability in one vulnerable contract impacts resources in other contracts.
Metrics:
SEVERITY COEFFICIENT (CC)COEFFICIENT VALUENUMERICAL VALUE
Reversibility (rr)None (R:N)
Partial (R:P)
Full (R:F)
1
0.5
0.25
Scope (ss)Changed (S:C)
Unchanged (S:U)
1.25
1
Severity Coefficient CC is obtained by the following product:

C=rsC = rs

The Vulnerability Severity Score SS is obtained by:

S=min(10,EIC10)S = min(10, EIC * 10)

The score is rounded up to 1 decimal places.
SeverityScore Value Range
Critical9 - 10
High7 - 8.9
Medium4.5 - 6.9
Low2 - 4.4
Informational0 - 1.9

5. SCOPE

Files and Repository
(a) Repository: bonzo-staking-module
(b) Assessed Commit ID: 0c3d22e
(c) Items in scope:
  • contracts/interfaces/IAaveIncentivesController.sol
  • contracts/interfaces/IExchangeRate.sol
  • contracts/interfaces/IHederaTokenService.sol
↓ Expand ↓
Out-of-Scope: External libraries and financial-related attacks., New features/implementations after/with the remediation commit IDs.
Remediation Commit ID:
  • 1ecf599
  • b1b2698
  • 155419e
  • f3e259b
  • 5d97016
Out-of-Scope: New features/implementations after the remediation commit IDs.

6. Assessment Summary & Findings Overview

Critical

2

High

0

Medium

1

Low

2

Informational

5

Security analysisRisk levelRemediation Date
Miscalculated Period Disrupt Emission Schedule ExecutionCriticalSolved - 07/12/2024
Wrong Reward Distribution Leads to Double SpendCriticalSolved - 07/12/2024
Invalid emissionSchedule length checkMediumSolved - 07/15/2024
Missing duplicate caller addresses checkLowSolved - 07/12/2024
Hardcoded Testnet EVM Address Instead of MainnetLowSolved - 07/12/2024
Increase PERIOD_DURATION to 30 DaysInformationalSolved - 07/12/2024
Inconsistent Struct Parameter UpdateInformationalSolved - 07/12/2024
Usage of Outdated SafeCastInformationalAcknowledged
Use of memory Instead of calldata in Function VariableInformationalAcknowledged
Redundant Parameters in Function _getAssetIndexInformationalSolved - 07/12/2024

7. Findings & Tech Details

7.1 Miscalculated Period Disrupt Emission Schedule Execution

// Critical

Description

The current implementation of the _getAssetIndex function in the AaveDistributionManager contract incorrectly calculates the currentPeriod using periodStartTimestamp.sub(lastUpdateTimestamp). Initially, during the first iteration, both periodStartTimestamp and lastUpdateTimestamp are the same, making the difference zero, which works correctly. However, this approach fails when lastUpdateTimestamp is higher or equal to the timestamp of period 1 (index 0). This leads to incorrect period calculations and potential out-of-bounds errors when accessing the emission schedule.

The issue arises because the code does not correctly handle cases where the lastUpdateTimestamp is already in a later period, as shown in the provided diagrams. This flaw was not evident during initial setup testing when lastUpdateTimestamp was set to the current timestamp, corresponding to index 0.

Invalid period diagram
BVSS
Recommendation

To resolve this critical issue, the currentPeriod should be calculated using the formula DISTRIBUTION_DURATION - (DISTRIBUTION_END - periodStartTimestamp) / PERIOD_DURATION or by maintaining a mechanism to keep track of the last distributed period and calculating the elapsed time difference with the current timestamp.

The new formula needs to be thoroughly tested to ensure it handles all edge cases correctly. This testing should include scenarios where updates are made in periods beyond the initial setup and various edge cases such as period transitions and partial periods.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended.

Remediation Hash
1ecf5995b8ed3b7fa84441a7be114b4dbdf551bc

7.2 Wrong Reward Distribution Leads to Double Spend

// Critical

Description

The AaveIncentivesController contract has a vulnerability that results in double spending of rewards. The issue occurs in the claimRewards function, where the contract transfers rewards both as REWARD_TOKEN and as IWHBAR. Specifically, the contract transfers the reward amount to the recipient twice, once via REWARD_TOKEN.transferFrom(REWARDS_VAULT, to, amountToClaim) and again via IWHBAR(_whbarContract).withdraw(REWARDS_VAULT, to, amountToClaim).

This leads to the recipient receiving the reward amount twice, causing financial loss to the rewards vault and effectively doubling the rewards for the claimant.

BVSS
Recommendation

To fix this issue, the rewards should first be transferred to the contract's address and then transferred to the recipient. Additionally, proper approvals should be set up for the IWHBAR contract to transfer the reward amounts.

By implementing this change, the rewards will be correctly transferred to the recipient only once, and the risk of double spending will be mitigated. Additionally, ensure that the REWARD_TOKEN has been approved for spending by the IWHBAR contract to facilitate the withdrawal. This approach prevents financial loss and maintains the integrity of the rewards' distribution.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended. The REWARDS_VAULT will require to approve AaveIncentivesController to spend the _whbarContract tokens.

Remediation Hash
b1b269852a55fd7a2456b5d802054ba61ddffd8f
References
AaveIncentivesController.sol#169-170

7.3 Invalid emissionSchedule length check

// Medium

Description

The AaveDistributionManager contract allows the direct call to the configureAssets function without validating the length of the emissionSchedule. This can lead to an out-of-bounds error when fetching the asset index if an invalid emissionSchedule length is provided. The initialization functions in StakedToken and AaveIncentivesController correctly perform this check, but it should also be enforced in the configureAssets function of AaveDistributionManager to prevent potential vulnerabilities from improper usage.

BVSS
Recommendation

Add the following check in the configureAssets function of the AaveDistributionManager contract to ensure the validity of the emissionSchedule length:

require(
  emissionSchedule.length * PERIOD_DURATION == DISTRIBUTION_DURATION,
  'Invalid emission schedule length'
);

This will ensure that the emission schedule length is always valid, thereby preventing out-of-bounds errors when accessing the asset index.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended.

Remediation Hash
155419ee299f2162c61e064bb422327516d568c6

7.4 Missing duplicate caller addresses check

// Low

Description

The AaveIncentivesController contract lacks a check in the addCallerAssets function to prevent the addition of duplicate caller addresses. The current implementation uses a list to store whitelisted callers for the onlyCallerAsset modifier, which is not optimized for checking or preventing duplicates. This can lead to inefficiencies and potential issues with duplicate entries. The use of EnumerableSet from OpenZeppelin or a two-struct approach (a mapping for O(1) access and a list for enumeration) would optimize the code and prevent duplicates effectively.


BVSS
Recommendation

Optimize the addCallerAssets function by using EnumerableSet from OpenZeppelin or a two-struct approach to handle the whitelist of caller addresses. This will prevent duplicate entries and improve the efficiency of the whitelist check.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended. Moreover, a new struct was added to track the assets, this struct makes the addition, removal and most important, the check easier and more efficient for large amount of registered assets.

Remediation Hash
f3e259b8109e1f13de69ba8079f43b119b6ad643

7.5 Hardcoded Testnet EVM Address Instead of Mainnet

// Low

Description

The contract contains a hardcoded Ethereum address pointing to a testnet environment instead of the mainnet. This can lead to malfunction or security risks when deployed on the mainnet, as the address will not point to the intended contract or service. As shown in the SaucerSwap contract deployment page, the EVM addresses for WHBAR are:

BVSS
Recommendation

It is crucial to update the address to the mainnet equivalent before deployment, or use configurable parameters to set the correct environment-specific address dynamically, ensuring proper functionality and security across different environments.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended.

Remediation Hash
5d9701676aa921a2a895a36097f5b710162ccdc5
References
AaveIncentivesController.sol#L82

7.6 Increase PERIOD_DURATION to 30 Days

// Informational

Description

The contract contains a TODO comment indicating the intention to increase the immutable PERIOD_DURATION variable to 30 days at a later time. Leaving such TODOs unresolved can lead to inconsistencies and potential issues in the contract's functionality.

BVSS
Recommendation

It is crucial to address this change promptly by updating PERIOD_DURATION to 30 days or removing the TODO if the change is no longer necessary. Ensuring that all TODOs are resolved enhances the contract's reliability and clarity.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended.

Remediation Hash
5d9701676aa921a2a895a36097f5b710162ccdc5
References
AaveDistributionManager.sol#27-28

7.7 Inconsistent Struct Parameter Update

// Informational

Description

The parameter emissionPerSecond of the AssetData struct in AaveDistributionManager has been modified to include an array of different emissions depending on the period, but this update was not reflected in the out-of-scope IStakedToken.sol interface, which is utilized in StakeUIHelper.sol. This inconsistency can lead to integration issues and potential bugs, as the outdated interface does not match the current contract implementation.

BVSS
Recommendation

It is recommended to update the IStakedToken.sol interface to reflect the changes in the emissionPerSecond parameter, and, if willing to be used, refactor StakeUIHelper.sol accordingly in order to ensure seamless interaction between the contracts and preventing any discrepancies.

Remediation Plan

SOLVED: The Bonzo team solved this issue as recommended. The IStakedToken was removed.

Remediation Hash
1ecf5995b8ed3b7fa84441a7be114b4dbdf551bc

7.8 Usage of Outdated SafeCast

// Informational

Description

The contract uses an outdated version of SafeCast that allows implicit casting from uint to int. This implicit casting can introduce vulnerabilities and unintended behavior due to the differences in value ranges between unsigned and signed integers. Updating to a newer version of SafeCast that requires explicit casting will ensure safer and more predictable type conversions, mitigating potential risks, and will allow the use of newer and safer compiler versions.

BVSS
Recommendation

By using explicit type conversions, the contract ensures clarity and prevents unintended behavior, aligning with the safety improvements introduced in recent Solidity versions.

Remediation Plan

ACKNOWLEDGED: Ignoring as it causes compatibility issues with the older versions of the SafeHederaTokenService contract

References
SafeHederaTokenService.sol#6

7.9 Use of memory Instead of calldata in Function Variable

// Informational

Description

The configureAssets function in the AaveDistributionManager contract declares the parameter assetsConfigInput as memory. However, since this parameter is read-only during the function execution, using calldata instead of memory is more efficient. Calldata directly references the input data without copying it to memory, resulting in reduced gas consumption and improved performance.

Score
Recommendation

Keeping the variable as calldata can optimize the function's performance and decrease transaction costs.

Remediation Plan

ACKNOWLEDGED: Changing assetsConfigInput to memory starts giving downstream compilation issues in StakedToken.sol and AaveIncentivesController.sol. So we are ignoring it.

References
AaveDistributionManager.sol#51

7.10 Redundant Parameters in Function _getAssetIndex

// Informational

Description

The _getAssetIndex function in the AaveDistributionManager contract currently takes four parameters: currentIndex, assetConfig, lastUpdateTimestamp, and totalBalance. However, assetConfig already contains the lastUpdateTimestamp and totalBalance data, making the other two parameters redundant. This redundancy leads to unnecessary gas consumption and inefficiency. Simplifying the function to accept only the composite parameter assetConfig can optimize gas usage and improve overall performance.

Score
Recommendation

By eliminating the redundant parameters, the function becomes more efficient, reducing gas costs and enhancing performance. This approach ensures a more streamlined and cost-effective implementation.

Remediation Plan

SOLVED: The issue was solved by removing lastUpdateTimestamp.

Remediation Hash
1ecf5995b8ed3b7fa84441a7be114b4dbdf551bc
References
AaveDistributionManager.sol#225-230

8. Automated Testing

Static Analysis Report

Description

Halborn used automated testing techniques to enhance the coverage of certain areas of the scoped contracts. Among the tools used was Slither, a Solidity static analysis framework. After Halborn verified all the contracts in the repository and was able to compile them correctly into their abi and binary formats, Slither was run on the all-scoped contracts. This tool can statically verify mathematical relationships between Solidity variables to detect invalid or inconsistent usage of the contracts' APIs across the entire code-base.

Slither results

WHBARContract

StakedAave

The reentrancy instances flagged by Slither were checked individually, and have been categorised as false positives.

Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.