Maximus Diamond Hands

Smart Contract Audit Report

Audit Summary

Maximus Diamond Hands Audit Report Maximus is creating a new staking platform which includes multiple new tokens.

For this audit, we reviewed the Maximus' PerpetualPool, Team, StakeRewardDistribution, MAXIEscrow, MysteryBox, DiamondHandsClub, RewardBucket, DHStakeRewardDistribution contracts at commit 4d2e8309af3858f2636027bcb1d97c5622a9ced3 on the team's GitHub repository.

We previously reviewed the project team's token contract here and staking contract here.

Audit Findings

No findings were identified.
Date: September 21st, 2022.

Contracts Overview

  • As the contracts are implemented with Solidity v0.8.x, they are safe from any possible overflows/underflows.
  • ReentrancyGuard is utilized in applicable functions, protecting them from any potential reentrancy attacks.
  • The project team should exercise caution and ensure that the appropriate contracts are excluded from any fee-on-transfer mechanisms.
PerpetualPool Contract:
  • This contract is used as a pool for HEX staking.
  • The contract consists of two periods: a minting/reload period and a staking period.
  • Upon deployment, a pool token name and symbol, initial mint period length, staking period duration, and reload period duration are provided.
  • The initial minting period begins once the contract is deployed. During this time, users can provide HEX to this contract in order to have pool tokens minted to them.
  • Pool tokens are minted based on the HEX amount deposited divided by the HEX redemption rate, which begins at 1 pool token per HEX.
  • Users can also redeem their pool tokens in exchange for HEX at the redemption rate during this period. The pool tokens are burned in the process.
  • Any user can end the minting period and activate the staking period once the current day has exceeded the end of the minting period.
  • Once activated, the HEX contract's stake is initiated for the duration of the staking period using this contract's collected HEX tokens.
  • Any user can end the staking period once the current day has exceeded the end day of the staking period.
  • A portion of the contract's total HEX after staking is transferred to the Team contract based on the principal stake amount, stake length, and earned HEX staking rewards.
  • This contract's entire hedron balance is also transferred to the Team contract.
  • A new HEX redemption rate is then calculated based on the number HEX tokens in the contract per pool token in existence.
  • A new minting/reload period will then restart where users can again provide and redeem HEX.
  • The duration of each minting/reload period after the initial minting period is equal to the specified reload period duration.
  • This contract's period number is incremented each time a new period starts.
  • Hedron tokens can be minted through this contract by any user at any time.
  • As the HEX and Hedron contracts were not included in the scope of this audit, we are unable to provide an assessment with regards to security or functionality.
  • Days are calculated according to the HEX contract's current day.
Team Contract:
  • This contract allows users to deposit MAXI in return for Team tokens. TEAM can then be staked to earn rewards in various tokens.
  • Upon deployment, PerpetualPool contracts with the following token names and stake periods are created:
    • A "Maximus Base" pool with a stake period of 369 days and a reload period of 7 days.
    • A "Maximus Trio" pool with a stake period of 1,111 days and a reload period of 7 days.
    • A "Maximus Lucky" pool with a stake period of 2,555 days and a reload period of 14 days.
    • A "Maximus Decimus" pool with a stake period of 3,696 days and a reload period of 14 days.
  • Each of these pools is created with an initial mint period length of 21 days.
  • A StakeRewardDistribution contract, MAXIEscrow contract, and MysteryBox are also deployed.
  • During this contract's minting phase, users are permitted to deposit Maxi tokens in exchange for minted TEAM at a 1:1 ratio.
  • Users can then "stake" their TEAM at any time which will burn them and create or update their "Stake Record" for the next staking period.
  • The Stake Record's stake ID and expiry period are set to the next available staking period.
  • After 21 days have passed, any user can finalize the minting phase. This will mark the minting phase as completed.
  • Of the contract's total collected Maxi tokens, 20% are burned, 30% are transferred to the MAXIEscrow contract, and 50% are transferred to the MysteryBox contract.
  • Users are still permitted to stake at any time.
  • Periods are determined by querying the Maximus Base PerpetualPool's contract's period information.
  • Any user can prepare a claim for any reward tokens once a staking period has ended.
  • When a claim is prepared, the contract's balance of the specified token is transferred to the Stake Reward Distribution contract.
  • This balance is divided by the total amount of TEAM staked during the previous staking period to calculate the specified token rewards.
  • Users are entitled to a share of these rewards based on their Staked amount during the previous staking period.
  • The team should ensure that no fee-on-transfer tokens are used as reward tokens unless the proper exemptions are made.
  • Once a user's stake expiry period has passed, they can end it and receive their originally deposited TEAM.
  • A user can end a portion or all of their Team Stake before its staking period is over but must pay a 3.69% penalty on the amount withdrawn.
  • The amount ended minus this penalty is then minted back to the user.
  • A user can also choose to restart an expired Stake instead of ending it. The balance of the expired stake is moved into a new Stake with an expiration set to the end of the next staking period.
StakeRewardDistribution Contract:
  • Users can use this contract in order to claim rewards earned from the Team contract.
  • Users can claim at any time after rewards for the specified token have been transferred for a given staking period.
  • When claiming, the user must specify the reward token ticker, Stake ID, and staking period which the user is claiming rewards for.
MAXIEscrow Contract:
  • This contract is used to lock MAXI tokens received by the Team contract and release them back into the Team contract over time.
  • Once the minting period is finalized in the Team contract, 30% of its received MAXI is transferred to a new instance of this contract.
  • 1/6th of these funds can be released on Period 5, 1/3rd can be released on Period 11, and the remaining half can be released on Period 17.
  • Periods are determined using the Maximus Base Perpetual Pool contract's determined period number.
MysteryBox Contract:
  • Once the minting period is finalized in the Team contract, 50% of its received MAXI is transferred to a new instance of this contract.
  • This contract allows any user to "flush" the contract's TEAM or MAXI by providing an equal amount of their own MAXI.
  • When flushing, the user can provide any amount less than 1 million MAXI.
  • This MAXI is transferred from the user to the "Mystery Box Hot Address".
  • An equal amount of either MAXI or TEAM is then transferred from this contract to the Mystery Box Hot Address.
  • As the Mystery Box Hot Address was not included in the scope of this audit, we are unable to provide an assessment with regards to security or functionality.
DiamondHandsClub Contract:
  • Any user can join the Diamond Hands club by specifying a number of Pool tokens that will be staked in this contract.
  • The user must grant the contract an allowance for the number of tokens they're staking in order for this transaction to successfully occur.
  • The users' "Stake Record" for the next staking period will either be created or updated.
  • The Stake Record's stake ID and expiry period are set to the next available staking period.
  • Once a user's stake expiry period has passed, the user can end it and receive their originally deposited Pool tokens.
  • A user can end a portion or all of their Pool Stake before its staking period is over, but must pay a penalty based on the stake length of the Pool contract on the amount withdrawn.
  • The amount ended minus this penalty is then transferred back to the user.
  • The tokens collected through the penalty are sent to the RewardBucket contract.
  • A user can extend a currently active Stake into the next staking period when the current period is the same as the user's expire period.
  • A user can also choose to restart an expired Stake instead of ending it. The balance of the expired stake is moved into a new Stake with an expiration set to the end of the next staking period.
RewardBucket Contract:
  • Any user can activate this contract which will set the Pool addresses and set each supported reward token in the contract.
  • Users can prepare a claim for any reward tokens once a staking period has ended.
  • When a claim is prepared, the contract's balance of the specified token is transferred to the DHStakeRewardDistribution contract.
  • This balance is divided by the total number of tokens staked during the previous staking period to calculate the specified token rewards.
  • The team should ensure that no fee-on-transfer tokens are used as reward tokens unless the proper fee exemptions are made.
  • Users are entitled to a share of these rewards based on their staked amount during the previous staking period.
DHStakeRewardDistribution Contract:
  • Users can use this contract in order to claim rewards earned from the DiamondHandsClub contract.
  • Users can claim at any time after rewards for the specified token have been transferred for a given staking period.
  • When claiming, the user must specify the reward token ticker, Stake ID, and staking period which the user is claiming rewards for.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control N/A PASS
Compiler Issues N/A PASS
Delegate Call to Untrusted Contract N/A PASS
Dependence on Predictable Variables N/A PASS
Ether/Token Theft N/A PASS
Flash Loans N/A PASS
Front Running N/A PASS
Improper Events N/A PASS
Improper Authorization Scheme N/A PASS
Integer Over/Underflow N/A PASS
Logical Issues N/A PASS
Oracle Issues N/A PASS
Outdated Compiler Version N/A PASS
Race Conditions N/A PASS
Reentrancy N/A PASS
Signature Issues N/A PASS
Unbounded Loops N/A PASS
Unused Code N/A PASS
Overall Contract Safety   PASS

PerpetualPool, Team, StakeRewardDistribution, MAXIEscrow, MysteryBox Contracts

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IERC20Metadata (IERC20)
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC20 (Context, IERC20, IERC20Metadata)
    - [Pub]  #
    - [Pub] name
    - [Pub] symbol
    - [Pub] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] transfer #
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] transferFrom #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Int] _transfer #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _spendAllowance #
    - [Int] _beforeTokenTransfer #
    - [Int] _afterTokenTransfer #

 + [Int] IERC20Permit 
    - [Ext] permit #
    - [Ext] nonces
    - [Ext] DOMAIN_SEPARATOR

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Int] functionDelegateCall #
    - [Int] functionDelegateCall #
    - [Int] verifyCallResult

 + [Lib] SafeERC20 
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeApprove #
    - [Int] safeIncreaseAllowance #
    - [Int] safeDecreaseAllowance #
    - [Int] safePermit #
    - [Prv] _callOptionalReturn #

 +  ERC20Burnable (Context, ERC20)
    - [Pub] burn #
    - [Pub] burnFrom #

 + [Lib] SafeMath 
    - [Int] tryAdd
    - [Int] trySub
    - [Int] tryMul
    - [Int] tryDiv
    - [Int] tryMod
    - [Int] add
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] mod
    - [Int] sub
    - [Int] div
    - [Int] mod

 +  ReentrancyGuard 
    - [Pub]  #

 +  HedronToken 
    - [Ext] approve #
    - [Ext] transfer #
    - [Ext] mintNative #
    - [Ext] claimNative #
    - [Ext] currentDay

 +  HEXToken 
    - [Ext] currentDay
    - [Ext] stakeStart #
    - [Ext] approve #
    - [Pub] transfer #
    - [Pub] stakeEnd #
    - [Ext] stakeCount

 +  PerpetualPool (ERC20, ERC20Burnable, ReentrancyGuard)
    - [Pub]  #
       - modifiers: ERC20,ReentrancyGuard
    - [Pub] decimals
    - [Ext] getCurrentPeriod
    - [Ext] getHexDay
    - [Ext] getEndStaker
    - [Prv] mint #
    - [Ext] pledgeHEX #
       - modifiers: nonReentrant
    - [Ext] redeemHEX #
       - modifiers: nonReentrant
    - [Ext] stakeHEX #
       - modifiers: nonReentrant
    - [Prv] _stakeHEX #
    - [Prv] _endStakeHEX #
    - [Ext] endStakeHEX #
       - modifiers: nonReentrant
    - [Prv] get_bonus_sharing_amount
    - [Prv] calculate_redemption_rate
    - [Ext] mintHedron #
    - [Prv] _mintHedron #

 +  Team (ERC20, ERC20Burnable, ReentrancyGuard)
    - [Pub]  #
       - modifiers: ERC20,ReentrancyGuard
    - [Prv] deployPools #
    - [Prv] deployPool #
    - [Prv] declareSupportedTokens #
    - [Pub] getSupportedTokens
    - [Prv] deployStakeRewardDistributionContract #
    - [Ext] mintTEAM #
       - modifiers: nonReentrant
    - [Ext] finalizeMinting #
       - modifiers: nonReentrant
    - [Prv] deployMAXIEscrow #
    - [Prv] deployMysteryBox #
    - [Ext] stakeTeam #
       - modifiers: nonReentrant
    - [Prv] newStakeRecord #
    - [Ext] earlyEndStakeTeam #
       - modifiers: nonReentrant
    - [Prv] earlyEndStakeRecord #
    - [Ext] endCompletedStake #
       - modifiers: nonReentrant
    - [Prv] endExpiredStake #
    - [Ext] extendStake #
       - modifiers: nonReentrant
    - [Pub] restakeExpiredStake #
       - modifiers: nonReentrant
    - [Ext] prepareClaim #
       - modifiers: nonReentrant
    - [Pub] getAddressPeriodEndTotal
    - [Pub] getPeriodRedemptionRates
    - [Pub] getPoolAddresses
    - [Pub] getClaimableAmount
    - [Pub] getCurrentPeriod
    - [Pub] isStakingPeriod
    - [Prv] getNextStakingPeriod
    - [Pub] decimals
    - [Prv] mint #

 +  StakeRewardDistribution (ReentrancyGuard)
    - [Pub]  #
       - modifiers: ReentrancyGuard
    - [Ext] claimRewards #
       - modifiers: nonReentrant
    - [Prv] collectSupportedTokenAddress #
    - [Pub] prepareSupportedTokens #
       - modifiers: nonReentrant

 +  MAXIEscrow (ReentrancyGuard)
    - [Pub]  #
       - modifiers: ReentrancyGuard
    - [Pub] scheduleRebates #
    - [Ext] releaseMAXI #

 +  MysteryBox (ReentrancyGuard)
    - [Pub]  #
       - modifiers: ReentrancyGuard
    - [Pub] flushTEAM #
       - modifiers: nonReentrant
    - [Pub] flushMAXI #
       - modifiers: nonReentrant

 +  MAXIToken 
    - [Ext] approve #
    - [Pub] transfer #
    - [Pub] burn #

 +  TEAMToken 
    - [Pub] getCurrentPeriod
    - [Pub] getAddressPeriodEndTotal
    - [Pub] getSupportedTokens
    - [Pub] getClaimableAmount

DiamondHandsClub, RewardBucket, DHStakeRewardDistribution Contracts

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IERC20Metadata (IERC20)
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC20 (Context, IERC20, IERC20Metadata)
    - [Pub]  #
    - [Pub] name
    - [Pub] symbol
    - [Pub] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] transfer #
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] transferFrom #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Int] _transfer #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _spendAllowance #
    - [Int] _beforeTokenTransfer #
    - [Int] _afterTokenTransfer #

 + [Lib] SafeMath 
    - [Int] tryAdd
    - [Int] trySub
    - [Int] tryMul
    - [Int] tryDiv
    - [Int] tryMod
    - [Int] add
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] mod
    - [Int] sub
    - [Int] div
    - [Int] mod

 +  ReentrancyGuard 
    - [Pub]  #
    - [Prv] _nonReentrantBefore #
    - [Prv] _nonReentrantAfter #

 +  TEAMContract 
    - [Pub] getPoolAddresses

 +  PerpetualContract 
    - [Ext] getCurrentPeriod
    - [Ext] getHexDay

 +  DiamondHandsClub (ReentrancyGuard)
    - [Pub]  #
       - modifiers: ReentrancyGuard
    - [Pub] deployStakeRewardDistributionContract #
       - modifiers: nonReentrant
    - [Pub] deployRewardBucketContract #
       - modifiers: nonReentrant
    - [Ext] joinClub #
       - modifiers: nonReentrant
    - [Prv] newStakeRecord #
    - [Pub] calculatePenalty
    - [Ext] earlyEndStakeToken #
       - modifiers: nonReentrant
    - [Prv] earlyEndStakeRecord #
    - [Ext] endCompletedStake #
       - modifiers: nonReentrant
    - [Prv] endExpiredStake #
    - [Ext] extendStake #
       - modifiers: nonReentrant
    - [Pub] restakeExpiredStake #
       - modifiers: nonReentrant
    - [Pub] getAddressPeriodEndTotal
    - [Pub] getglobalStakedTokensPerPeriod
    - [Pub] getCurrentPeriod
    - [Pub] isStakingPeriod
    - [Prv] getNextStakingPeriod

 +  RewardBucket (ReentrancyGuard)
    - [Pub]  #
       - modifiers: ReentrancyGuard
    - [Pub] activate #
       - modifiers: nonReentrant
    - [Prv] declareSupportedTokens #
    - [Ext] prepareClaim #
       - modifiers: nonReentrant
    - [Pub] getPeriodRedemptionRates
    - [Pub] getSupportedTokens
    - [Pub] getClaimableAmount

 +  DHStakeRewardDistribution (ReentrancyGuard)
    - [Pub]  #
       - modifiers: ReentrancyGuard
    - [Pub] activate #
       - modifiers: nonReentrant
    - [Ext] claimRewards #
       - modifiers: nonReentrant
    - [Pub] prepareSupportedTokens #
       - modifiers: nonReentrant
    - [Prv] collectSupportedTokenAddress #

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 1300+ 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 across 1500 projects!.
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.