creation_sourcecode: // File: contracts/lib/SafeMath.sol
  
  /*
  
      Copyright 2020 DODO ZOO.
      SPDX-License-Identifier: Apache-2.0
  
  */
  
  pragma solidity 0.6.9;
  
  
  /**
   * @title SafeMath
   * @author DODO Breeder
   *
   * @notice Math operations with safety checks that revert on error
   */
  library SafeMath {
      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
          if (a == 0) {
              return 0;
          }
  
          uint256 c = a * b;
          require(c / a == b, "MUL_ERROR");
  
          return c;
      }
  
      function div(uint256 a, uint256 b) internal pure returns (uint256) {
          require(b > 0, "DIVIDING_ERROR");
          return a / b;
      }
  
      function divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
          uint256 quotient = div(a, b);
          uint256 remainder = a - quotient * b;
          if (remainder > 0) {
              return quotient + 1;
          } else {
              return quotient;
          }
      }
  
      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
          require(b <= a, "SUB_ERROR");
          return a - b;
      }
  
      function add(uint256 a, uint256 b) internal pure returns (uint256) {
          uint256 c = a + b;
          require(c >= a, "ADD_ERROR");
          return c;
      }
  
      function sqrt(uint256 x) internal pure returns (uint256 y) {
          uint256 z = x / 2 + 1;
          y = x;
          while (z < y) {
              y = z;
              z = (x / z + z) / 2;
          }
      }
  }
  
  // File: contracts/lib/InitializableOwnable.sol
  
  
  /**
   * @title Ownable
   * @author DODO Breeder
   *
   * @notice Ownership related functions
   */
  contract InitializableOwnable {
      address public _OWNER_;
      address public _NEW_OWNER_;
      bool internal _INITIALIZED_;
  
      // ============ Events ============
  
      event OwnershipTransferPrepared(address indexed previousOwner, address indexed newOwner);
  
      event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  
      // ============ Modifiers ============
  
      modifier notInitialized() {
          require(!_INITIALIZED_, "DODO_INITIALIZED");
          _;
      }
  
      modifier onlyOwner() {
          require(msg.sender == _OWNER_, "NOT_OWNER");
          _;
      }
  
      // ============ Functions ============
  
      function initOwner(address newOwner) public notInitialized {
          _INITIALIZED_ = true;
          _OWNER_ = newOwner;
      }
  
      function transferOwnership(address newOwner) public onlyOwner {
          emit OwnershipTransferPrepared(_OWNER_, newOwner);
          _NEW_OWNER_ = newOwner;
      }
  
      function claimOwnership() public {
          require(msg.sender == _NEW_OWNER_, "INVALID_CLAIM");
          emit OwnershipTransferred(_OWNER_, _NEW_OWNER_);
          _OWNER_ = _NEW_OWNER_;
          _NEW_OWNER_ = address(0);
      }
  }
  
  // File: contracts/external/ERC20/CustomERC20.sol
  
  
  contract CustomERC20 is InitializableOwnable {
      using SafeMath for uint256;
  
      string public name;
      uint8 public decimals;
      string public symbol;
      uint256 public totalSupply;
  
      uint256 public tradeBurnRatio;
      uint256 public tradeFeeRatio;
      address public team;
  
      mapping(address => uint256) balances;
      mapping(address => mapping(address => uint256)) internal allowed;
  
      event Transfer(address indexed from, address indexed to, uint256 amount);
      event Approval(address indexed owner, address indexed spender, uint256 amount);
  
      event ChangeTeam(address oldTeam, address newTeam);
  
  
      function init(
          address _creator,
          uint256 _totalSupply,
          string memory _name,
          string memory _symbol,
          uint8 _decimals,
          uint256 _tradeBurnRatio,
          uint256 _tradeFeeRatio,
          address _team
      ) public {
          initOwner(_creator);
          name = _name;
          symbol = _symbol;
          decimals = _decimals;
          totalSupply = _totalSupply;
          balances[_creator] = _totalSupply;
          require(_tradeBurnRatio >= 0 && _tradeBurnRatio <= 5000, "TRADE_BURN_RATIO_INVALID");
          require(_tradeFeeRatio >= 0 && _tradeFeeRatio <= 5000, "TRADE_FEE_RATIO_INVALID");
          tradeBurnRatio = _tradeBurnRatio;
          tradeFeeRatio = _tradeFeeRatio;
          team = _team;
          emit Transfer(address(0), _creator, _totalSupply);
      }
  
      function transfer(address to, uint256 amount) public returns (bool) {
          _transfer(msg.sender,to,amount);
          return true;
      }
  
      function balanceOf(address owner) public view returns (uint256 balance) {
          return balances[owner];
      }
  
      function transferFrom(
          address from,
          address to,
          uint256 amount
      ) public returns (bool) {
          require(amount <= allowed[from][msg.sender], "ALLOWANCE_NOT_ENOUGH");
          _transfer(from,to,amount);
          allowed[from][msg.sender] = allowed[from][msg.sender].sub(amount);
          return true;
      }
  
      function approve(address spender, uint256 amount) public returns (bool) {
          allowed[msg.sender][spender] = amount;
          emit Approval(msg.sender, spender, amount);
          return true;
      }
  
      function allowance(address owner, address spender) public view returns (uint256) {
          return allowed[owner][spender];
      }
  
  
      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");
          require(balances[sender] >= amount, "ERC20: transfer amount exceeds balance");
  
          balances[sender] = balances[sender].sub(amount);
  
          uint256 burnAmount;
          uint256 feeAmount;
          if(tradeBurnRatio > 0) {
              burnAmount = amount.mul(tradeBurnRatio).div(10000);
              balances[address(0)] = balances[address(0)].add(burnAmount);
              emit Transfer(sender, address(0), burnAmount);
          }
  
          if(tradeFeeRatio > 0) {
              feeAmount = amount.mul(tradeFeeRatio).div(10000);
              balances[team] = balances[team].add(feeAmount);
              emit Transfer(sender, team, feeAmount);
          }
          
          uint256 receiveAmount = amount.sub(burnAmount).sub(feeAmount);
          balances[recipient] = balances[recipient].add(receiveAmount);
  
          emit Transfer(sender, recipient, receiveAmount);
      }
  
  
      //=================== Ownable ======================
      function changeTeamAccount(address newTeam) external onlyOwner {
          require(tradeFeeRatio > 0, "NOT_TRADE_FEE_TOKEN");
          emit ChangeTeam(team,newTeam);
          team = newTeam;
      }
  
      function abandonOwnership(address zeroAddress) external onlyOwner {
          require(zeroAddress == address(0), "NOT_ZERO_ADDRESS");
          emit OwnershipTransferred(_OWNER_, address(0));
          _OWNER_ = address(0);
      }
  }