MBD Financials Token

CertiK2 addresses on Ethereum

CertiK reviewed MBD Financials (MBD Financials Token) on 2 May 2024: 32 findings, 3 critical; 28 marked fixed, 4 open.

3 critical findings, fixed
Open the reportOpen MBD Financials’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings32

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical003
High206
Medium104
Low1015
Critical`proposalIDcount` Variable Not Persisted in StoraFixed

The function `addProposal` incorrectly uses a local variable `proposalIDcount` to track proposal IDs. Changes to `proposalIDcount` within the function do not persist between transactions because the local variable is not stored back into a state variable. This can lead to logical errors in the management of proposal IDs, as each call to `addProposal` will start with the same initial `proposalIDcount`, ignoring previous increments.

CriticalPotential for Multiple Votes on the Same ProposalFixed

The `submitVote()` is missing an `else` branch after checking if `blocked[msg.sender] == 0` or if the current proposal has a deadline further in the future than the one that is blocking the sender. This oversight allows for the possibility of a voter being able to vote multiple times on the same proposal.

CriticalReusable Voting Power via Token TransferFixed

In the `MBD` contract's voting mechanism, there is a critical design flaw where a user can vote on a proposal and then transfer their tokens to another account to vote again. This process can be repeated indefinitely, allowing the token holder to amplify their voting power disproportionately.

High`_owner` Gains `addLiquidity()` LP TokensFixed

```solidity=1361 uniswapV2Router.addLiquidityETH{value: ethAmount}( address(this), tokenAmount, 0, // slippage is unavoidable 0, // slippage is unavoidable owner(), block.timestamp ); ``` The function `addLiquidity()` calls function `uniswapV2Router.addLiquidityETH()` with the `to` address specified as `owner()` for acquiring the generated LP tokens from the `MBD-ETH` pool. As a result, over time the `_owner` address will accumulate a significant portion of LP tokens. If the `_owner` is an EOA (Externally Owned Account), mishandling of its private key can have devastating consequences to the project as a whole.

HighContract Gains Non-withdrawable ETH via the `swapFixed

The `swapAndLiquify` function converts half of the `contractTokenBalance` MBD tokens to ETH. The other half of MBD tokens and part of the converted ETH are deposited into the MBD-ETH pool on pancakeswap as liquidity. For every `swapAndLiquify` function call, a small amount of ETH is leftover in the contract. This is because the price of MBD drops after swapping the first half of MBD tokens into ETHs, and the other half of MBD tokens require less than the converted ETH to be paired with it when adding liquidity. The contract doesn't appear to provide a way to withdraw those ETH, and they will be locked in the contract forever.

HighIncompatible Uniswap V2 Router InterfaceFixed

The `swapExactTokensForETHSupportingFeeOnTransferTokens` and `addLiquidityETH` functions in the `IUniswapV2Router02` interface are missing the `deadline` parameter. The official Uniswap V2 Router requires a deadline for these functions to prevent front-running and ensure the transaction is executed within a specific timeframe.

HighLack of Voting Deadline Validation in `submitVoteFixed

The `submitVote` function does not check whether the `votingDeadline` of a proposal is still in the future, which allows votes to be cast on proposals that should no longer be active. This could result in votes being submitted after the deadline has passed, affecting the proposal's outcome and potentially violating governance rules.

HighPotential Flashloan AttackFixed

An attacker can use a flashloan as the initial funds for an exploit to enlarge the profit or manipulate the token price in decentralized exchanges. If swapping/adding liquidity happens without price and slippage control and can be triggered on-chain by anyone, then an attacker can exploit the contract. ```solidity=1347 uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens( tokenAmount, 0, // accept any amount of ETH path, address(this), block.timestamp ); ``` Function `MBD.swapTokensForEth` invokes `IUniswapV2Router02.swapExactTokensForETHSupportingFeeOnTransferTokens` without setting restrictions on slippage or minimum output amount, which may be triggered by anyone.

HighUndefined `whenNotBlocked` and `onlyEligibleVoterFixed

The `whenNotBlocked` modifier and `onlyEligibleVoter` modifier are used in the `submitProposal` and `submitVote` functions to restrict voting access to non-blocked addresses, and voter eligibility validation. However, the definitions of these modifiers are missing in the contract, leading to a compilation error and potential security risks.

MediumAbsence of Proposal State Validation Before VotinFixed

The `submitVote()` does not check whether a proposal has already passed before allowing a vote to be cast. This lack of validation allows votes to be submitted for a proposal that has already met the required threshold of votes to pass, which can lead to unnecessary gas expenditure and potential confusion about the final tally of votes.

Show 10 more
MediumUniswapV2Pair Should Be Excluded From RewardsFixed

Generally, deflationary tokens are incompatible with DEX and special rules need to be coded for DEX addresses eg. excluding them from reward. Otherwise, a hacker can exploit the protocol using the reflection mechanism. The balance of accounts that include rewards is calculated by `rAmount/rate`, where the rate is determined base on the total supply. If the `deliver()` function is executed with significant input, it can significantly decrease `rTotal`, thereby allowing for manipulation of the rate.

MediumVariable `_rOwned[account]` Not Updated in FunctiFixed

Variable `_rOwned[account]` is not updated in the function `includeInReward()`, which will make the accounts included siphon off the tokens out of the balances of all token holders. The Rate was higher at the moment of the `excludeFromReward(account)` call, so the `_rOwned[account] / _tOwned[account]` ratio is bigger than expected for accounts included in the reward.

MediumVariable Usage Before Setting ValueFixed

This issue pertains to a situation in which a contract utilizes a variable, `ProposalID`, before setting its value, leading to potential errors and unexpected behavior in the contract's execution.

LowDiscussion on Incorrect Use of Governance Array iFixed

The `whenNotBlocked` modifier is intended to prevent blocked accounts from voting. However, it incorrectly checks the `governance` array instead of the `blocked` array, which is supposed to track blocked accounts. This discrepancy can lead to unintended behavior, allowing blocked accounts to vote or preventing governance accounts from voting.

LowDuplicate `VotesSubmitted` Event Emission in `subFixed

The `submitVote` function emits the `VotesSubmitted` event twice, once within an if-statement and once at the end of the function, without any conditional differences that justify two separate emissions. This redundancy could lead to confusion and unnecessary gas costs when the event is emitted.

LowInefficient `tmarketing` Value Recalculation in `Fixed

The current implementation of the `_getTValues` and `_getRValues` functions leads to unnecessary recalculation of `tmarketing`. The `tmarketing` value is calculated twice: once in `_getTValues` and again in `_getRValues`. This redundancy increases gas costs and can be optimized.

LowMissing input validationFixed

The functions `_takeLiquidity` and `_takeMarketing` do not validate whether the `tLiquidity` and `_takeMarketingAmount` values are greater than zero before performing operations with these values. This could lead to unnecessary function calls and state changes, potentially wasting gas.

LowMissing Zero Address ValidationFixed

Addresses are not validated before assignment or external calls, potentially allowing the use of zero addresses and leading to unexpected behavior or vulnerabilities. For example, transferring tokens to a zero address can result in a permanent loss of those tokens. ```solidity=1239 MarketingAddress = _marketingAddress; ``` - `_marketingAddress` is not zero-checked before being used.

LowMissing Zero Amount CheckFixed

The function `swapTokensForEth()` and `addLiquidity()` function don't check if the `tokenAmount` variable is above zero before executing. This could cause gas costs for each function call.

LowPotential Divide by ZeroFixed

Performing division by zero would raise an error and revert the transaction. ```solidity=1047 return rAmount / currentRate; ``` The expression `rAmount / currentRate` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=1179 return rSupply / tSupply; ``` The expression `rSupply / tSupply` may divide by zero. Its divisor has has estimated interval [ninf, pinf]. --- ```solidity=1193 if (rSupply < _rTotal / _tTotal) return (_rTotal, _tTotal); ``` The expression `_rTotal / _tTotal` may divide by zero. Its divisor has has estimated interval [0, 40000000000000000000000000000].

Show 8 more
LowPotential Sandwich AttacksFixed

A sandwich attack might happen when an attacker observes a transaction swapping tokens or adding liquidity without setting restrictions on slippage or minimum output amount. The attacker can manipulate the exchange rate by frontrunning (before the transaction being attacked) a transaction to purchase one of the assets and make profits by back running (after the transaction being attacked) a transaction to sell the asset. The following functions are called without setting restrictions on slippage or minimum output amount, so transactions triggering these functions are vulnerable to sandwich attacks, especially when the input amount is large: - `uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens()` - `uniswapV2Router.addLiquidity()` Moreover,

LowRedundant codeFixed

The condition `!_isExcluded[sender] && !_isExcluded[recipient]` can be included in `else` .

LowState Variable Should Be Declared ConstantFixed

State variables that never change should be declared as `constant` to save gas. ```solidity=779 uint256 public _feeDenominator = 10000; ``` - `_feeDenominator` should be declared `constant`. --- ```solidity=780 uint256 public _MaxtotalFee = 2000; ``` - `_MaxtotalFee` should be declared `constant`. --- ```solidity=803 uint256 private numTokensSellToAddToLiquidity = 500000 * 10 ** 18; ``` - `numTokensSellToAddToLiquidity` should be declared `constant`. --- ```solidity=819 uint256 public _locktime = 60; ``` - `_locktime` should be declared `constant`.

LowUnnecessary Storage Read Access in For LoopFixed

The for loop contains repeated storage read access in the condition check. Given that the ending condition does not change in the for loop, the repeated storage read is unnecessary, and its associated high gas cost can be eliminated. ```solidity=1185 for (uint256 i = 0; i < _excluded.length; i++) { ``` Loop condition `i < _excluded.length` accesses the `length` field of a storage array.

LowUnprotected InitializerFixed

One or more logic contracts do not protect their initializers. An attacker can call the initializer and assume ownership of the logic contract, whereby she can perform privileged operations that trick unsuspecting users into believing that she is the owner of the upgradeable contract. ```solidity=217 contract MBD is Initializable, IERC20Upgradeable, AccessControlUpgradeable { ``` - `MBD` is an upgradeable contract that does not protect its initializer. ```solidity=313 function initialize() public initializer { ``` - `initialize` is an unprotected initializer function.

LowUnused Return ValueFixed

The smart contract does not check or store the return value of an external call in a local or state variable, which may introduce vulnerabilities due to the unhandled outcome. ```solidity=1361 uniswapV2Router.addLiquidityETH{value: ethAmount}( address(this), tokenAmount, 0, // slippage is unavoidable 0, // slippage is unavoidable owner(), block.timestamp ); ```

LowUnused ValueFixed

The smart contract contains one or more values that are not used, which can lead to unnecessary complexity and reduced maintainability. ```solidity=1523 proposalIDcount = proposalIDcount + 1; ``` - The variable `proposalIDcount` is never used after this assignment.

LowVariables That Could Be Declared as ImmutableFixed

The linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage. ```solidity=776 uint256 private _tTotal; ``` ```solidity=784 uint256 private _decimals; ```

Contracts in scope2

AddressChainSource code
0xa08898cabe14680cdfea55398143bc120889182eChain: EthereumSource code: Verified source
0x4ff319847664b03a956d8f4f076a35ec2d4a6f46Chain: EthereumSource code: Verified source

Part of MBD Financials’s security record

MBD Financials
Audits2 audits by 2 firmsLast audit May 2024, by CertiK.
Critical findingsNo open critical findingsAcross the 2 reports, 3 critical findings were reported. Each is marked fixed by the firm that reported it.
Open MBD Financials’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us