Pexcoin Staking - Audit Report

Audit Summary

Pexcoin Audit Report Project-X is building a new staking contract for users to deposit tokens and earn yield.

For this audit, we reviewed the following contract at 0x9A20a15fD6F9ef07a2ce913A0cE4E521Ede55Fbc on the Binance Smart Chain mainnet.

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

Audit Findings

Please ensure trust in the team prior to investing as they have some control in the ecosystem.
Date: January 11th, 2022.

Optimization - Finding #1

Description: Several functions are declared public, but are never called internally. Several state variables can never be modified, but are not declared constant.
- TokenStaker: getPeriodRewardTokenCount, getpoolUnusedRewardAddress, setpoolUnusedRewardAddress, getPoolTotalStakedSupply, getPoolTotalRewardSupply, getPoolTotalLostRewardAmount, setPoolRewardTokenCount, getCalculationFactor, setCalculationFactor, releaseReward, deposit, withdraw, emergencyWithdraw

State Variables:
- TokenStaker: contractLockPeriod, minimumBalance

Recommendation: We recommend declaring these functions external and declaring these state variables constant for additional gas savings on each call.

Contract Overview

  • Anyone can use this contract to deposit any amount of the designated staking token in order to earn rewards in the form of the staking token.
  • Staked tokens are locked within the staking contract until the lock time of 6 months has elapsed.
  • Users receive rewards per reward period based on the stake time and reward rate of the pool.
  • Users may withdraw their staked funds when the lock time has elapsed; rewards are automatically calculated but not transferred on withdrawals.
  • Users may trigger an "emergency withdrawal" to withdraw their staked amount at any time.
  • On emergency withdrawals, the user's rewards are forfeited and allocated as unused staking rewards.
  • The owner can transfer the unused staking rewards to the unused reward address at any time.
  • The owner can set the unused reward address at any time.
  • The owner can set the reward rate for the staking pool at any time.
  • The owner can set the calculation factor to any value at any time.
  • As the contract is implemented with Solidity v0.8.X, it is protected from any underflow/overflow attacks.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of ControlThe owner can set the reward rate to any value at any time.WARNING
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Logical IssuesN/APASS
Multiple SendsN/APASS
State Change External CallsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

Function Graph

Staking Graph

Inheritence Chart

Staking contract inheritance

Functions Overview

 + [Int] Minter 
    - [Ext] mint #

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

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

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [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

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner

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

 +  TokenStaker (Ownable)
    - [Pub]  #
    - [Pub] getPeriodRewardTokenCount
       - modifiers: onlyOwner
    - [Pub] getpoolUnusedRewardAddress
       - modifiers: onlyOwner
    - [Pub] setpoolUnusedRewardAddress #
       - modifiers: onlyOwner
    - [Pub] getPoolTotalStakedSupply
    - [Pub] getPoolTotalRewardSupply
    - [Pub] getPoolTotalLostRewardAmount
       - modifiers: onlyOwner
    - [Pub] setPoolRewardTokenCount #
       - modifiers: onlyOwner
    - [Pub] getCalculationFactor
       - modifiers: onlyOwner
    - [Pub] setCalculationFactor #
       - modifiers: onlyOwner
    - [Pub] releaseReward #
       - modifiers: onlyOwner
    - [Pub] remainLockTime
    - [Int] _MassUpdate #
    - [Pub] claimableReward
    - [Pub] deposit #
    - [Pub] withdraw #
    - [Pub] emergencyWithdraw #
    - [Ext] claim #