BananaCoin Finance - Smart Contract Audit Report

Summary

Banana Finance Audit Report BananaCoin.finance intends to build a services marketplace using their token. Banana Coin has a hard-capped total supply and a 2% burn fee on transactions.
The contract is deployed at 0x21f54372c07b930b79c5c2d9bb0eaaca86c3b298.

Notes of the contract:
  • The supply cap and burn rate are initialized in the constructor, so the maximum supply and burn rate can never be altered.
  • The burn rate on transactions is set at 2%.
  • Only the owner can call the burn function; and the burn function can burn anyone's tokens without their approval.
  • The owner has the ability to mint more tokens, but the total supply cannot exceed the 500 token cap.
  • Implementation of SafeMath libraries to prevent overflows. The smart contract follows ERC20 guidelines.

Audit Findings Summary:
  • No security issues from external attackers were detected in the analysis.
  • The owner has substantial power in that they can burn tokens from any address; and that they can mint tokens.
  • Date: December 18th, 2020


Date: December 17th, 2020
Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Flash LoansN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
OraclesN/APASS
SuicideN/APASS
State Change External CallsN/APass
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

ERC20 Token Graph

Multi-file Token


   ($) = payable function
    # = non-constant function
  
    
 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

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

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 +  ERC20 (Context, IERC20)
    - [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 #
    - [Pub] mint #
       - modifiers: onlyOwner
    - [Pub] burn #
       - modifiers: onlyOwner
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _setupDecimals #
    - [Pub] cap
    - [Int] _beforeTokenTransfer
							

Click here to download the source code as a .sol file.


/**
 *Submitted for verification at Etherscan.io on 2020-11-14
*/

/**
 *Submitted for verification at Etherscan.io on 2020-11-13
*/

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; 
        return msg.data;
    }
}
interface IERC20 {

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {

        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint256 private _decimals = 18;
    uint256 private _cap;
    address _owner = msg.sender;

modifier onlyOwner(){
    require(msg.sender == _owner);
    _;
}

    constructor (string memory name, string memory symbol, uint256 cap, uint256 totalSupply) public {
        _name = name;
        _symbol = symbol;
        _cap = cap;
        require(totalSupply <= cap);
        _totalSupply = totalSupply;
        _balances[msg.sender] = totalSupply;
    }    function name() public view returns (string memory) {
        return _name;
    }    function symbol() public view returns (string memory) {
        return _symbol;
    }    function decimals() public view returns (uint256) {
        return _decimals;
    }    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        uint burnval = amount.div(50);
        uint total = amount.add(burnval);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(total, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }
    
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");
        uint256 burnVal = amount.div(50);
        uint256 netAmount = amount.sub(burnVal);
        _beforeTokenTransfer(sender, amount);
        _burn(sender, burnVal);
        

        _balances[sender] = _balances[sender].sub(netAmount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(netAmount);
        emit Transfer(sender, recipient, netAmount);
    }

    function mint(address account, uint256 amount) public virtual onlyOwner {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }
    function burn(address account, uint256 amount) public onlyOwner{
        _burn(account, amount);
    }

    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    function cap() public view returns (uint256) {
        return _cap;
    }

    function _beforeTokenTransfer(address from, uint256 amount) internal view virtual {
        
                if (from == address(0)) { // When minting tokens
            require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded");
        }
    }
}