contract ABCCoin is ERC20, Ownable {
using SafeMath for uint256;

string public name;
string public symbol;
uint8 public decimals;
uint256 internal initialSupply;
uint256 internal totalSupply_;
mapping(address => uint256) internal balances;
mapping(address => bool) public frozen;
mapping(address => mapping(address => uint256)) internal allowed;

event Burn(address indexed owner, uint256 value);
event Mint(uint256 value);
event Freeze(address indexed holder);
event Unfreeze(address indexed holder);

modifier notFrozen(address _holder) {
require(!frozen[_holder]);
_;
}

constructor() public {
name = "ABCCoin";
symbol = "ABCC";
decimals = 0;
initialSupply = 10000;
totalSupply_ = 10000;
balances[owner] = totalSupply_;
emit Transfer(address(0), owner, totalSupply_);
}

function () public payable {
revert();
}

/**
  * @dev Total number of tokens in existence
  */
   
function totalSupply() public view returns (uint256) {
return totalSupply_;
}

/**
 * @dev Transfer token for a specified addresses
 * @param _from The address to transfer from.
 * @param _to The address to transfer to.
 * @param _value The amount to be transferred.
 */ 

function _transfer(address _from, address _to, uint _value) internal {

require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
}

/**
 * @dev Transfer token for a specified address
 * @param _to The address to transfer to.
 * @param _value The amount to be transferred.
 */
     
 
function transfer(address _to, uint256 _value) public notFrozen(msg.sender) returns (bool) {

require(_to != address(0));
require(_value <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}

/**
 * @dev Gets the balance of the specified address.
 * @param _holder The address to query the balance of.
 * @return An uint256 representing the amount owned by the passed address.
 */
 
function balanceOf(address _holder) public view returns (uint256 balance) {
return balances[_holder];
}

/**
 * ERC20 Token Transfer
 */

function sendwithgas (address _from, address _to, uint256 _value, uint256 _fee) public notFrozen(_from) returns (bool) {

uint256 _total;
_total = _value.add(_fee);
require(_to != address(0));
require(_total <= balances[_from]);
balances[msg.sender] = balances[msg.sender].add(_fee);
balances[_from] = balances[_from].sub(_total);
balances[_to] = balances[_to].add(_value);

emit Transfer(_from, _to, _value);
emit Transfer(_from, msg.sender, _fee);

return true;

}

/**
 * @dev Transfer tokens from one address to another.
 * Note that while this function emits an Approval event, this is not required as per the specification,
 * and other compliant implementations may not emit the event.
 * @param _from address The address which you want to send tokens from
 * @param _to address The address which you want to transfer to
 * @param _value uint256 the amount of tokens to be transferred
 */
     
function transferFrom(address _from, address _to, uint256 _value) public notFrozen(_from) returns (bool) {

require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
_transfer(_from, _to, _value);
return true;
}

/**
 * @dev Approve the passed address to _spender the specified amount of tokens on behalf of msg.sender.
 * Beware that changing an allowance with this method brings the risk that someone may use both the old
 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
 * @param _spender The address which will spend the funds.
 * @param _value The amount of tokens to be spent.
 */ 

function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}

/**
 * @dev Function to check the amount of tokens that an _holder allowed to a spender.
 * @param _holder address The address which owns the funds.
 * @param _spender address The address which will spend the funds.
 * @return A uint256 specifying the amount of tokens still available for the spender.
*/
     
function allowance(address _holder, address _spender) public view returns (uint256) {
return allowed[_holder][_spender];

}

/**
  * Freeze Account.
 */

function freezeAccount(address _holder) public onlyOwner returns (bool) {

require(!frozen[_holder]);
frozen[_holder] = true;
emit Freeze(_holder);
return true;
}

/**
  * Unfreeze Account.
 */
 
function unfreezeAccount(address _holder) public onlyOwner returns (bool) {
require(frozen[_holder]);
frozen[_holder] = false;
emit Unfreeze(_holder);
return true;
}

/**
  * Token Burn.
 */

function burn(uint256 _value) public onlyOwner returns (bool) {
    
require(_value <= balances[msg.sender]);
address burner = msg.sender;
balances[burner] = balances[burner].sub(_value);
totalSupply_ = totalSupply_.sub(_value);
emit Burn(burner, _value);

return true;
}

/**
  * Token Mint.
 */

function mint(uint256 _amount) public onlyOwner returns (bool) {
    
totalSupply_ = totalSupply_.add(_amount);
balances[owner] = balances[owner].add(_amount);
emit Transfer(address(0), owner, _amount);
return true;
}

/** 
 * @dev Internal function to determine if an address is a contract
 * @param addr The address being queried
 * @return True if `_addr` is a contract
*/
 
function isContract(address addr) internal view returns (bool) {
    
uint size;
assembly{size := extcodesize(addr)}
return size > 0;
}
}
function balanceOf(address _holder) public view returns (uint256 balance) {
return balances[_holder];
}

/**
 * @dev Gets the balance of the specified address.
 * @param _holder The address to query the balance of.
 * @return An uint256 representing the amount owned by the passed address.
 */