Customer : Centralex Date : March 2 nd , 2021 SMART CONTRACT CODE REVIEW AND SECURITY ANALYSIS REPORT This document may contain confidential information about IT systems and the intellectual property of the customer as well as information about potential vulnerabilities and methods of their exploitation. The report containing confidential information can be used internally by the customer or it can be disclosed publicly after all vulnerabilities fixed - upon a decision of the customer. Document Name Smart Contract Code Review an d Security Analysis Report for Centralex Type ERC - 20 token , Staking contract , Voting contract Platform Ethereum / Solidity Methods Architecture Review, Functional Testing, Computer - Aided Verification, Manual Review Approved by Andrew Matiukhin | CTO and co - founder Hacken Contract Timeline 11 TH FEB 2021 – 1 5 TH FEB 20 21 Changelog 15 TH FEB 202 1 - Initial Audit 02 nd MAR 2021 – S econd review Table of contents Introduction ................................ .............................. 4 Scope ................................ ................................ ..... 4 Executive Summary ................................ ......................... 5 Severity Definitions ................................ ...................... 6 AS - IS overview ................................ ............................ 7 Conclusion ................................ ............................... 24 Disclaimers ................................ .............................. 25 Introduction Hacken OÜ (Consultant) was contracted b y Centralex ( Customer) to conduct a Smart Contract Code Review and Security Analysis. This report presents the findings of the security assessment of Customer`s smart contract and its code revi ew c onducted between February 11 th , 20 21 – February 1 5 th , 20 21 The second review conducted on March 2 nd , 2021. Scope The scope of the project is smart contract s in file sent by Customer : • CentralexToken.sol • Staking.sol • Governance.sol We have scanned this smart contract for commonly known and more specific vulnerabilities. List of the commonly known vulnerabilities that are considered: Category Check Item Code review ▪ Reentrancy ▪ Ownership Takeover ▪ Timestamp Dependence ▪ Gas Limit and Loops ▪ DoS with (Unexpected) Throw ▪ DoS with Block Gas Limit ▪ Transaction - Ordering Dependence ▪ Style guide violation ▪ Costly Loop ▪ ERC20 API violation ▪ Unchecked external call ▪ Unchecked math ▪ Unsafe type inference ▪ Implicit visibility level ▪ Deployment Consistency ▪ Repository Consistency ▪ Data Consistency Functional review ▪ Business Logics Review ▪ Functionality Checks ▪ Access Control & Authorization ▪ Escrow manipulation ▪ Token Supply manipulation ▪ Assets integrity ▪ User Balances manipulation ▪ Data Consistency manipulation ▪ Kill - Switch Mechanism ▪ Operation Trails & Event Generation Executive Summary According to the assessment, the Customer’s smart contracts are secure Our team performed an analysis of code functionality, manual audit, and automated checks with Mythril and Slither. All issues found during automated analysis were manually reviewed and important vulnerabilities are presented in the Audit overview section. A general overview is presented in AS - IS section and all found issues can be found in the Audit overview section. Notice: The contract owners may pause the Staking contract and all funds will be locked until the contract unp aused. Security engineers found 3 high and 3 medium issues during the initial audit. After the second review the code contains 1 information issue. The code quality is low and there is a high risk of residual issues. Graph 1. The distribution of vulnerabilities. Medium 100% Medium Insecure Poor secured Secured Well - secured You are here Severity Definitions Risk Level Description Critical Critical vulnerabilities are usually straightforward to exploit and can lead to assets lose or data manipulations. High High - level vulnerabilities are difficult to exploit; however, they also have significant impact on smart contract execution, e.g. public access to crucial functions Medium Medium - level vulnerabilities are important to fix; however, they can’t lead to assets lose or data manipulations. Low Low - level vulnerabilities are mostly related to outdated, unused etc. code snippets, that can’t have significant impact on execution Lowest / Code Style / Best Practice Lowest - level vulnerabilities, code style violations and info statements can’t affect s mart contract execution and can be ignored. AS - IS overview Centralex smart contracts Centralex smart contracts scope consists of CentralexToken.sol, Governance.sol, Staking.sol. CentralexToken.sol Description CentralexToken is a smart contract for Centralex ERC20 token. Imports CentralexToken imports: ● OwnableUpgradeable.sol ● ERC20PresetMinterPauserUpgradeable.sol ● Initializable.sol Inheritance CentralexToken contract is Initializable, ERC20PresetMinterPauserUpgradeable, OwnableUpgradeable. Usages CentralexToken contract has no custom usages. Structs Centr alexToken contract has no custom structs. Enums CentralexToken contract has no custom enums. Events CentralexToken contract has following events: ● event ContractInitStarted(string name, string symbol, address owner, uint256 timestamp); ● event ContractInitEnded(string name, string symbol, address owner, uint256 timestamp); Modifiers CentralexToken contract has no custom modifiers. Fields CentralexToken contract has no custom parameters. Functions CentralexToken has following functions: ● initialize Description initializes contract state Visibility public override initializer Input parameters ● string memory name ● string memory symbol Constraints None Events emit ● emit ContractInitStarted(name, symbol, msg.sender, block.timestamp); ● emit ContractInitEnded(name, symbol, msg.sender, block.timestamp); Output None Staking.sol Description Staking is a smart contract for Centralex ERC20 token staking. Imports Staking imports: ● OwnableUpgradeable .sol ● Initializable .sol ● AddressUpgradeable .sol ● SafeMathUpgradeable .sol ● ReentrancyGuardUpgradeable .sol ● SafeERC20Upgradeable .sol ● IERC20Upgradeable .sol ● PausableUpgradeable .sol ● Sacrifice .sol ● CentralexToken .sol Inheritance Staking contract is OwnableUpgradeable, ReentrancyGuardUpgradeable , PausableUpgradeable Usages Staking contract has following usages: ● using AddressUpgradeable for address; ● using SafeMathUpgradeable for uint256; ● using SafeERC20Upgradeable for IERC20Upgradeable; Structs Staking contract has following structs: ● struct UintParam that stores: ○ uint256 oldValue; ○ uint256 newValue; ○ uint256 timestamp; ● struct AddressParam that stores: ○ address oldValue; ○ address newValue; ○ uint256 timestamp; Enums Staking contract has no custom enums. Events Staking contract has following events: ● event Deposited(address indexed sender, uint256 indexed id, uint256 amount, uint256 balance, uint256 accruedEmission, uint256 prevDepositDuration); ● event WithdrawalRequested(address indexed sender, uint256 indexed id); ● event BeforeDepositAndRewardWithdrawn(address indexed sender, uint256 indexed id, uint256 deposit , uint256 reward); ● event Withdrawn(address indexed sender, uint256 indexed id, uint256 withdrawalSum, uint256 fee, uint256 balance, uint256 reward, uint256 lastDepositDuration, uint256 totalStaked, uint256 totalRemainingReward); ● event FeeSet(uint256 value , address sender); ● event RewardDistributionSet(uint256 value, address sender); ● event RewardMaturityDurationSet(uint256 value, address sender); ● event WithdrawalLockDurationSet(uint256 value, address sender); ● event WithdrawalUnlockDurationSet(uint256 value, address sender); ● event RewardDistributed(uint256 amount); ● event RewardFactorUpdated(uint256 rewardFactor, uint256 totalStaked); ● event RewardUpdated(uint256 stakersReward, uint256 ownerReward, uint256 totalRemainingReward, uint256 totalStakersReward, uint25 6 totalOnwerReward); Modifiers Staking contract has no custom modifiers. Fields Staking contract has following parameters: ● uint256 public constant PARAM_UPDATE_DELAY = 7 days ● uint256 private currentRewardFactor = 0 ● mapping (address => mapping (uint256 => uint256)) public depositRewardFactor ● CentralexToken public token ● UintParam public feeParam ● UintParam public rewardSharePercentParam ● UintParam public withdrawalLockDurationParam ● UintParam public withdrawalUnlockDurationParam ● UintParam public rew ardMaturityDurationPara ● mapping (address => mapping (uint256 => uint256)) public balances ● mapping (address => mapping (uint256 => uint256)) public depositDates ● mapping (address => mapping (uint256 => uint256)) public withdrawalRequestsDates ● mapping (address => uint256) public lastDepositIds ● uint256 public totalStaked ● uint256 public totalRemainingReward ● uint256 public totalStakersReward ● uint256 public totalOnwerReward ● bool private locked Functions Staking has following functions: ● initialize Description I nitializes the contract state Visibility external Input parameters ● address _owner ● address _tokenAddress ● uint256 _fee ● uint256 _withdrawalLockDuration ● uint256 _withdrawalUnlockDuration ● uint256 _rewardMaturityDuration ● uint256 _rewardSharePerce nt Constraints ● Can only be called once. ● _ owner should not be 0 address. ● _ tokenAddress should be a contract address. Events emit Emits FeeSet , WithdrawalLockDurationSet , WithdrawalUnlockDurationSet , RewardMaturityDurationSet , setRewardSharePercent events Output None ● deposit Description D eposits tokens for user Visibility external Input parameters ● uint256 _amount Constraints None Events emit None Output None ● deposit Description D eposits tokens for user Visibility public Input parameters ● uint256 _depositId ● uint256 _amount Constraints None Events emit None Output None ● ownerWithdraw Description Withdraws owner rewards. Visibility public Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. Events emit None Output None ● makeForcedWithdrawal Description F orces tokens withdrawal for user Visibility external Input parameters ● uint256 _depositId Constraints • whenNotPaused modifier. • _depositId should exist and its balance should be non - zero. Events emit Emits Withdrawn and RewardFactorUpdated events. Output None ● requestWithdrawal Description R equest tokens withdrawal for user Visibility external Input parameters ● uint256 _depositId Constraints • whenNotPaused modifier. • _depositId should exist. Events emit E mit s the WithdrawalRequested event Output None ● makeRequestedWithdrawal Description Processes a withdrawal request. Visibility external Input parameters ● uint256 _depositId Constraints • whenNotPaused modifier. • Withdrawal should be requested earlier. • Lock time after initial request should pass. • Withdrawal should be performed before the unlock duration period is passed. Events emit Emits Withdrawn event. Output None ● setFee , setRewardMaturityDuration , setRewardSharePercent , setWithdrawalLockDuration , setWithdrawalUnlockDuration Description Simple setter functions. Only accessible by the owner and when the contract is not paused. ● totalUserBalance Description Returns user total balance. Visibility public view Input parameters ● address voter Constraints • voter should not be zero address. Events emit None Output Uint256 totalUserStaked ● fee fee , rewardSharePercent, rewardMaturityDuration, withdrawalLockDuration, withdrawalUnlockDuration Description Simple view functions. ● distribute Description Adds an _amount of tokens to the distribution pool. Visibility public Input parameters ● uint256 _amount Constraints • whenNotPaused , onlyOwner , nonReentran modifiers. • _ amount should be non - zero value. Events emit None Output Uint256 totalUserStaked Governance.sol Description Governance is a voting contract. Imports Governance imports: ● ERC20.sol ● IERC20.sol ● SafeERC20.sol ● ERC20Pausable.sol ● SafeMath.sol ● Ownable.sol ● Counters.sol ● AddressUpgradeable.sol ● ReentrancyGuard.sol ● Address.sol ● Staking.sol Inheritance Governance contract is Pausable , Ownable , ReentrancyGuard Usages Governance contract has following usages: ● using SafeMath for uint256; ● using SafeERC20 for IERC20; ● using Counters for Counters.Counter; ● using AddressUpgradeable for address; Structs Governance contract has following structs: ● struct Proposal that stores: ○ uint256 proposalId; ○ uint256 createdAt; ○ ProposalStatus proposalStatus; ● struct Vote that stores: ○ address voter; ○ uint voteValue; Enums Governance contract has following enums: ● enum ProposalStatus with options: ○ None ○ Active ○ Paused ○ Closed ○ Canceled ● enum GovernanceStatus with options: ○ DraftStarted ○ DraftCompleted ○ VotingStarted ○ VotingCompleted ○ SnapshotStarted ○ SnapshotCompleted Events Governance contract has following events: ● event ProposalAdded(address indexed proposalOwner, uint256 indexed proposalsTotal, uint256 indexed proposalId, string proposalTitle, uint256 dateAdd); ● event VoteAdded(uint256 indexed proposalId, address indexed voter); ● event ProposalActivated(uint256 indexed proposalId); ● event ProposalPaused(uint256 indexed proposalId); ● event ProposalClosed(uint256 indexed proposalId); ● event ProposalCanceled(uint256 indexed pr oposalId); ● event ProposalResumed(uint256 indexed proposalId); ● event TotalProposalsBaseIndexChanged(uint256 indexed totalProposals); ● event CalculationHasStarted(uint256 proposalsBaseIndex, uint256 proposalKeysLength); ● event CalculationHasCompleted(address s ender); ● event WinnerFound(uint256 proposalId, uint256 winnersCount); ● event GovernanceStatusChanged(GovernanceStatus prevStatus, GovernanceStatus currentStatus); Modifiers Governance contract has following modifiers: ● whenStatus - checks whether status equals to value Fields Governance contract has following parameters: ● uint256 private constant MINIMUM_STAKE_AMOUNT = 1000 ● uint private constant DEFAULT_VOTE_WEIGHT = 1 ● Staking public staking ● GovernanceStatus private governanceStatus ● mapping(uint256 => Proposal) private proposals ● uint256[] private proposalKeys ● uint256 public proposalsBaseIndex ● mapping(uint256 => Vote[]) private votes ● mapping(uint256 => mapping(address => bool)) private voters ● mapping(uint256 => uint256) private results ● uint256[] public winners Functions Governance has following functions: ● constructor Description I nitializes contract state Visibility None Input parameters ● address _stakingAddress Constraints • _ stakingAddress should be a contract. Events emit None Output None ● openProposalDraft Description C hanges governanceStatus to DraftStarted Visibility public Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Voting should be in the SnapshotCompleted status. Events emit Emits the TotalProposalsBaseIndexChanged event. Output None ● closeProposalDraft Description C hanges governanceStatus to DraftCompleted Visibility external Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Voting should be in the DraftStarted status. Events emit None Output None ● openVoting Description C hanges governanceStatus to VotingStarted Visibility external Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Voting should be in the DraftCompleted status. Events emit None Output None ● closeVoting Description C hanges governanceStatus to VotingCompleted Visibility external Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Voting should be in the VotingStarted status. Events emit None Output None ● openCalculation Description C hanges governanceStatus to SnapshotStarted Visibility external Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Voting should be in the VotingCompleted status. Events emit None Output None ● closeCalculation Description C hanges governanceStatus to SnapshotCompleted Visibility external Input parameters None Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Voting should be in the SnapshotStarted status. Events emit None Output None ● pauseProposal Description C hanges proposal state to Paused Visibility public Input parameters ● uint256 _proposalId Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Proposal should exist. Events emit Emits the ProposalPaused event. Output None ● resumeProposal Description C hanges proposal state to Active Visibility public Input parameters ● uint256 _proposalId Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Proposal should exist. Events emit Emits the ProposalResumed event. Output None ● closeProposal Description C hanges proposal state to Closed Visibility public Input parameters ● uint256 _proposalId Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Proposal should exist. Events emit Emits the ProposalClosed event. Output None ● cancelProposal Description Changes proposal state to Canceled Visibility public Input parameters ● uint256 _proposalId Constraints • whenNotPaused modifier. • onlyOwner modifier. • nonReentrant modifier. • Proposal should exist and be in the Active state. Events emit Emits the ProposalCanceled event. Output None ● addProposal Description C reates new proposal Visibility external Input parameters ● uint256 proposalId ● string calldata proposalTitle Constraints ● onlyOwner modifier. ● whenNotPaused modifier. ● The governanceStatus should be DraftStarted. ● nonReentrant modifier. Events emit E mit the ProposalAdded event. Output proposalKeyArray.length ● getProposalStatus , getActiveProposalsCount, getPausedProposalsCount, getCurrentProposalsCount, getProposalIdByIndex Description Simple view functions. ● vote Description Vo te for a proposal with _proposalId Visibility external Input parameters ● uint256 proposalId Constraints