HoneyComb

Smart Contract Audit Report

Audit Summary

HoneyComb Audit Report HoneyComb is a new layered yield farming platform in which users can stake various tokens in order to earn rewards from multiple sources.

For this audit, we reviewed the HoneycombMaster and HoneycombStrategyForPancake contracts at commit 9a24e9114409a78541c42e7487b17e176bf3915f on the team's GitHub repository.

Audit Findings

All findings have been resolved, though some centralized aspects are present.
Date: July 1st, 2022.
Updated: July 5th, 2022 to reflect changes from commit 30e7a5fea0d402430408c262dc7b1c5667dd3c82 to commit 9a24e9114409a78541c42e7487b17e176bf3915f.

Finding #1 - HoneycombMaster - High (Resolved)

Description: Share prices are increased each time a withdrawal occurs as long as shares remain in the pool. As the token to share ratio is not guaranteed to increase over time, the share price will not accurately reflect the correct ratio of tokens to shares.
Risk/Impact: Over time, the share price will increase and allow users to withdraw more tokens than they should be permitted to. This will result in insufficient tokens remaining in the contract for other users to withdraw.
Recommendation: The share price should not be increased on each withdrawal unless additional staking tokens are transferred to the contract at an equal rate.
Resolution: The team has removed the share price increase mechanism from the contract.

Finding #2 - HoneycombMaster - High (Resolved)

Description: Deposit fees are incorrectly taken from the HoneycombMaster contract when they should be taken from the depositing user.
if (pool.depositFeeBP > 0) {
    uint256 depositFee = amount * pool.depositFeeBP / 10000;
    pool.want.safeTransfer(performanceFeeAddress, depositFee);
    amount = amount - depositFee;
}

uint256 newShares = (amount * ACC_EARNING_PRECISION) / pool.lpPerShare;
pool.want.safeTransferFrom(
    address(msg.sender),
    address(pool.strategy),
    amount
);
pool.strategy.deposit(msg.sender, to, amount, newShares);
Risk/Impact: The contract will send other users' deposited funds for fees instead of the depositing user's funds, potentailly preventing users from withdrawing their originally deposited funds.
Recommendation: The deposit fee should instead be transferred from the caller to the Performance Fee address.
Resolution: Deposit fees are now transferred from the caller instead of the contract.

Contracts Overview

  • As the contracts are implemented with Solidity v0.8.x, they are safe from any possible overflows/underflows.
  • The team should not use ERC-777 tokens as staking tokens.
  • The team must exercise caution when adding a fee-on-transfer token as a staking token. If a fee-on-transfer token is used, this contract should be excluded from the contract's fee mechanism.
HoneycombMaster Contract:
  • This contract allows users to stake various tokens into pools in order to earn rewards.
  • When a pool is deposited into, the tokens are transferred from the user to the pool's associated Strategy contract.
  • The user is granted "shares" based on their deposited amount and current share price.
  • Rewards are generated over time based on the contract's reward rate. Each time rewards are minted to the contract, an additional "Dev percentage" is minted to the Dev address.
  • Users earn portions of these rewards based on their number of shares and their staked pool's share of accumulated rewards.
  • Users can deposit on behalf of another specified user. In this case, the caller's tokens are deposited and the shares are granted to the specified user.
  • A deposit fee is taken from the user's deposit amount and sent to a "Performance Fee" address.
  • A referrer address can also be specified. This will be used to "record" a referral in an associated Referral contract.
  • As the Referral contract was not included in the scope of this audit, we are unable to provide an assessment with regards to security or functionality.
  • When withdrawing, a user inputs their share amount in exchange for a token amount dependent on the share price.
  • Pools with withdrawal fees enabled require users to pay a fee of up to 3% to a "Performance Fee" address. The fee may decrease based on the amount of time since the user's last deposit.
  • The calculated token amount after fees is withdrawn from the associated strategy contract to the user.
  • A user can also withdraw their tokens to another address.
  • When withdrawing from a pool with a greater number of total shares than shares being withdrawn, the share price will be increased in relation to the percentage of total shares being redeemed.
  • Users may potentially lose pending rewards when withdrawing if their withdrawal amount's rewards have exceeded their reward debt.
  • Users can choose whether to harvest their pending rewards or not upon withdrawal.
  • The user can also trigger an emergency withdrawal, which will withdraw without calculating rewards and reset their rewards to 0.
  • When harvesting, users pending rewards from this contract are transferred to them in the form of the contract's reward token.
  • If insufficient reward tokens exist in the contract, the difference will be minted.
  • The user's referrer, if one exists, is then minted an additional Referral Commission percentage in reward tokens.
  • Users are only transferred rewards from this contract when the harvest() or withdrawAndHarvest() functions are called.
  • The owner can add a new pool at any time, specifying a staking token, strategy contract, share of rewards, deposit fee, and whether a withdrawal fee exists.
  • If a contract restriction flag is enabled, contracts are not permitted to interact with this contract unless they have been approved by the owner.
  • The owner can add or remove a contract from the approved list at any time.
  • The owner can toggle the contract restriction flag at any time.
  • The owner can update the Referral Commission rate up to 20% at any time.
  • The owner can update the Dev mint percentage to up to 100% at any time.
  • The owner can update the deposit fee to any amount at any time.
  • The owner can update the Dev address, Performance Fee address, and Referral contract address at any time.
  • A pool's share price can be increased by the pool's strategy contract at any time; however the strategy contract reviewed within the scope of this audit did not contain this functionality.
  • The owner can update a pool's deposit fee to any amount and specify whether a pool has a withdrawal fee at any time.
  • The owner can update a pool's share of rewards at any time.
  • The owner can update a pool's strategy at any time. An owner of the new strategy is also specified and set.
  • The owner can also 'migrate' a pool's strategy at any time, which is intended to transfer funds from the previous strategy to the new one.
  • The owner can update the total reward rate at any time.
  • The owner can withdraw any non-staking token from a pool's HoneycombStrategyForPancake contract at any time.
  • The owner can mint any amount of reward tokens to any address at any time.
  • The owner can transfer ownership of the reward token contract to any address at any time.
HoneycombStrategyForPancake Contract:
  • This contract is used as a strategy for a given HoneycombMaster pool.
  • When tokens are deposited into this contract, they are transferred to an associated staking contract to earn further rewards.
  • Rewards per share will increase over time as the associated staking contract accumulates rewards.
  • Pending rewards from this contract are automatically harvested on each deposit and withdrawal from the contract's associated pool.
  • Users can also withdraw pending rewards directly from this contract by using the harvest() function.
  • If a user is depositing or withdrawing on behalf of another user, the specified user will also receive the caller's pending rewards.
  • When rewards are harvested, a Performance Fee is taken and sent to the Performance Fee address before the remainder is sent to the user.
  • If the contract does not have a sufficient reward token balance, the contract's remaining balance is transferred instead.
  • The owner of this contract is intended to be the HoneycombMaster contract.
  • The owner can transfer ownership of this contract to any address at any time.
  • The owner can withdraw any non-staking tokens from the contract at any time.
  • The owner can update the Performance Fee to up to 100% at any time.
  • The owner can grant an allowance to the associated staking contract at any time, or revoke the allowance of any address at any time.
  • The owner can migrate all funds and staked funds from this contract to another address at any time.

Audit Results

Vulnerability CategoryNotesResult
Arbitrary Jump/Storage WriteN/APASS
Centralization of Control
  • The owner has the permissions described above.
  • The owner can mint any amount of reward tokens to any address at any time.
  • The owner can update a pool's strategy at any time. An owner of the new strategy is also specified and set.
  • A pool's strategy contract can update the pool's share price at any time.
  • The owner can update the Performance fee of both the HoneycombMaster and HoneycombStrategyForPancake contracts to up to 100%.
  • The owner can update a pool's deposit fee to any amount at any time.
  • The owner can update the Dev mint percentage to up to 100% at any time.
  • The owner can migrate all funds and staked funds from this contract to another address at any time.
  • The owner can transfer ownership of the reward token contract to any address at any time.
  • The owner of the HoneycombMaster can transfer ownership of the HoneycombStrategyForPancake contract to any address at any time.
  • WARNING
    Compiler IssuesN/APASS
    Delegate Call to Untrusted ContractN/APASS
    Dependence on Predictable VariablesN/APASS
    Ether/Token TheftN/APASS
    Flash LoansN/APASS
    Front RunningN/APASS
    Improper EventsN/APASS
    Improper Authorization SchemeN/APASS
    Integer Over/UnderflowN/APASS
    Logical IssuesN/APASS
    Oracle IssuesN/APASS
    Outdated Compiler VersionN/APASS
    Race ConditionsN/APASS
    ReentrancyN/APASS
    Signature IssuesN/APASS
    Unbounded LoopsN/APASS
    Unused CodeN/APASS
    Overall Contract Safety PASS

    Inheritance Chart

    Smart Contract Audit - Inheritance

    Function Graph

    Smart Contract Audit - Graph

    Functions Overview

    
     ($) = payable function
     # = non-constant function
     
     Int = Internal
     Ext = External
     Pub = Public
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Int] _checkOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Int] verifyCallResult
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IERC20Permit 
        - [Ext] permit #
        - [Ext] nonces
        - [Ext] DOMAIN_SEPARATOR
    
     + [Lib] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Int] safePermit #
        - [Prv] _callOptionalReturn #
    
     + [Int] MintableToken (IERC20)
        - [Ext] mint #
        - [Ext] transferOwnership #
    
     + [Int] IHoneycombStrategy 
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] inCaseTokensGetStuck #
        - [Ext] setAllowances #
        - [Ext] revokeAllowance #
        - [Ext] migrate #
        - [Ext] onMigration #
        - [Ext] pendingTokens
        - [Ext] transferOwnership #
        - [Ext] setPerformanceFeeBips #
    
     + [Int] IStakingRewards 
        - [Ext] userInfo
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] lastTimeRewardApplicable
        - [Ext] rewardPerToken
        - [Ext] earned
        - [Ext] getRewardForDuration
        - [Ext] deposit #
        - [Ext] withdraw #
        - [Ext] stakeWithPermit #
        - [Ext] withdraw #
        - [Ext] getReward #
        - [Ext] pendingCake
        - [Ext] exit #
    
     + [Int] IEarningsReferral 
        - [Ext] recordReferral #
        - [Ext] recordReferralCommission #
        - [Ext] getReferrer
        - [Ext] updateOperator #
        - [Ext] drainBEP20Token #
    
     +  HoneycombStrategyBase (IHoneycombStrategy, Ownable)
        - [Pub]  #
        - [Ext] pendingTokens
        - [Ext] deposit #
           - modifiers: onlyOwner
        - [Ext] withdraw #
           - modifiers: onlyOwner
        - [Ext] inCaseTokensGetStuck #
           - modifiers: onlyOwner
        - [Ext] setAllowances #
           - modifiers: onlyOwner
        - [Ext] revokeAllowance #
           - modifiers: onlyOwner
        - [Ext] migrate #
           - modifiers: onlyOwner
        - [Ext] onMigration #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Ext] setPerformanceFeeBips #
           - modifiers: onlyOwner
    
     +  HoneycombStrategyStorage (Ownable)
        - [Ext] increaseRewardDebt #
           - modifiers: onlyOwner
        - [Ext] decreaseRewardDebt #
           - modifiers: onlyOwner
        - [Ext] setRewardDebt #
           - modifiers: onlyOwner
        - [Ext] increaseRewardTokensPerShare #
           - modifiers: onlyOwner
    
     +  HoneycombStrategyForPancake (HoneycombStrategyBase)
        - [Pub]  #
           - modifiers: HoneycombStrategyBase
        - [Pub] checkReward
        - [Pub] pendingRewards
        - [Ext] rewardTokens
        - [Ext] pendingTokens
        - [Ext] harvest #
        - [Ext] deposit #
           - modifiers: onlyOwner
        - [Ext] withdraw #
           - modifiers: onlyOwner
        - [Ext] migrate #
           - modifiers: onlyOwner
        - [Ext] onMigration #
           - modifiers: onlyOwner
        - [Ext] setAllowances #
           - modifiers: onlyOwner
        - [Int] _claimRewards #
        - [Int] _harvest #
        - [Int] _safeRewardTokenTransfer #
    
     +  HoneycombMaster (Ownable)
        - [Pub]  #
        - [Pub] poolLength
        - [Pub] pendingEarnings
        - [Ext] pendingTokens
        - [Pub] reward
        - [Pub] earningPerYear
        - [Pub] earningPerYearToHoneycomb
        - [Pub] totalShares
        - [Pub] totalLP
        - [Pub] userShares
        - [Pub] updatePool #
        - [Pub] massUpdatePools #
        - [Ext] deposit #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] withdraw #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] harvest #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] withdrawAndHarvest #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] emergencyWithdraw #
           - modifiers: onlyApprovedContractOrEOA
        - [Ext] add #
           - modifiers: onlyOwner
        - [Ext] set #
           - modifiers: onlyOwner
        - [Ext] migrateStrategy #
           - modifiers: onlyOwner
        - [Ext] setStrategy #
           - modifiers: onlyOwner
        - [Ext] manualMint #
           - modifiers: onlyOwner
        - [Ext] transferMinter #
           - modifiers: onlyOwner
        - [Ext] setDev #
           - modifiers: onlyOwner
        - [Ext] setPerfomanceFeeAddress #
           - modifiers: onlyOwner
        - [Ext] setDevMintBips #
           - modifiers: onlyOwner
        - [Ext] setEarningsEmission #
           - modifiers: onlyOwner
        - [Ext] modifyApprovedContracts #
           - modifiers: onlyOwner
        - [Ext] setOnlyApprovedContractOrEOAStatus #
           - modifiers: onlyOwner
        - [Ext] inCaseTokensGetStuck #
           - modifiers: onlyOwner
        - [Ext] setAllowances #
           - modifiers: onlyOwner
        - [Ext] revokeAllowance #
           - modifiers: onlyOwner
        - [Ext] setPerformanceFeeBips #
           - modifiers: onlyOwner
        - [Ext] accountAddedLP #
        - [Int] safeEarningsTransfer #
        - [Pub] getWithdrawFee
        - [Pub] setWithdrawFee #
           - modifiers: onlyOwner
        - [Pub] setEarningsReferral #
           - modifiers: onlyOwner
        - [Pub] setReferralCommissionRate #
           - modifiers: onlyOwner
        - [Int] payReferralCommission #
    
    

    About SourceHat

    SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1800+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value!
    Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!

    Contact us today to get a free quote for a smart contract audit of your project!

    What is a SourceHat Audit?

    Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.

    How Do I Interpret the Findings?

    Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:

    • High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
    • Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
    • Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
    • Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.