// Vulnerability label: ARTHM_LE
pragma solidity ^0.4.18;

// ---------------------------
// OMGCat coin contract
//
// Deployed to 	: 0x921beCA00339c458342cF09b4B0f4adb3942e332
// symbol		: OMGCAT
// name 		: OMGCatCoin
// Total supply : 100,000,000,000.000000000000000000
// Decimals 	: 18
// ------------
// Safe maths
// ------------
contract SafeMath {
    function safeAdd(uint a, uint b) public pure returns (uint c){
    	c = a + b;
    	require(c >= a);
    }

    function safeSub(uint a, uint b) public pure returns (uint c) {
    	require(b <= a);
    	c = a - b;
    }

    function safeMul(uint a, uint b) public pure returns (uint c) {
    	c = a * b;
    	require(a == 0 || c / a == b);
    }

    function safeDiv(uint a, uint b) public pure returns (uint c) {
    	require(b > 0);
    	c = a / b;
    }
}

// ------------------------------------------------
// OMGCatCoin Standard #20 Interface
// ------------------------------------------------
contract ERC20Interface {
	function totalSupply() public constant returns (uint);
	function balanceOf(address tokenOwner) public constant returns (uint balance);
	function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
	function transfer(address to, uint tokens) public returns (bool success);
	function approve(address spender, uint tokens) public returns (bool success);
	function transferFrom(address from, address to, uint tokens) public returns (bool success);

	event Transfer(address indexed from, address indexed to, uint tokens);
	event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

// -------------
// Contract function to receive approval and execute function in one call
// -------------
contract ApproveAndCallFallBack {
	function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}

// -------------
// Owned contract
// -------------
contract Owned {
	address public owner;
	address public newOwner;

	event OwnershipTransferred(address indexed _from, address indexed _to);

	function Owned() public {
		owner = msg.sender;
	}

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

	function transferOwnership(address _newOwner) public onlyOwner {
		newOwner = _newOwner;
	}

	function acceptOwnership() public {
		require(msg.sender == newOwner);
		OwnershipTransferred(owner, newOwner);
		owner = newOwner;
		newOwner = address(0);
	}
}

// ---------
// -- ERC20 Token, with the additional of symbol, name, decimals and assisted
// ---------
contract OMGCatCoin is ERC20Interface, Owned, SafeMath {
	string public symbol;
	string public  name;
	uint8 public decimals;
	uint public _totalSupply;

	mapping(address => uint) balances;
	mapping(address => mapping(address => uint)) allowed;

	// -----------
	// Constructor 
	// -----------
	function OMGCatCoin() public {
		symbol = 'OMGCAT';
		name = 'OMGCatCoin';
		decimals = 18;
		_totalSupply = 100000000000 * 10**uint(decimals);
		balances[0x921beCA00339c458342cF09b4B0f4adb3942e332] = _totalSupply;
		Transfer(address(0), 0x921beCA00339c458342cF09b4B0f4adb3942e332, _totalSupply);
	}

	// ------------
	// Total supply
	// ------------
	function totalSupply() public constant returns (uint) {
		return _totalSupply - balances[address(0)];
	}

	// ----
	// Get the coin balance for account coinOwner
	// ----
	function balanceOf(address tokenOwner) public constant returns (uint balance) {
		return balances[tokenOwner];
	}

	// ------
	// transfer the balance from token owner account to 'to' account
	// - Owner's account must have sufficient balance to transfer
	// - 0 value transfers are allowed
	// -------
	function transfer(address to, uint tokens) public returns (bool success) {
		balances[msg.sender] = safeSub(balances[msg.sender], tokens);
		balances[to] = safeAdd(balances[to], tokens);
		Transfer(msg.sender, to, tokens);

		return true;
	}

	// -----
	// Token owner can approve for spender to transferFrom(...) tokens
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account
    //
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces 	
    function approve(address spender, uint tokens) public returns (bool success) {
    	allowed[msg.sender][spender] = tokens;
    	Approval(msg.sender, spender, tokens);
    	return true;
    }

    // ---------------
    //
    // callin accoutn must already have sufficient tokens to approve(...)
    // for spending from the form account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allownace to transfer
    // - 0 value transfers are allowed
    // --------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
    	balances[from] = safeSub(balances[from], tokens);
    	allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
    	balances[to] = safeAdd(balances[to], tokens);
    	Transfer(from, to, tokens);
    	return true;
    }

    // -----------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // -----------
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
    	return allowed[tokenOwner][spender];
    }

    // ------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account. The spender contract function
    // receiveApproval(...) is then executed
    function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
    	allowed[msg.sender][spender] = tokens;
    	Approval(msg.sender, spender, tokens);
    	ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
    	return true;
    }

    // ---------
    // Dont accept ETH;
    // ---------
    function () public payable { 
    	revert();
    }

    // -----------
    // Owner can transfer out any accidentally sent ERC20 tokens
    // ------------
    function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
    	return ERC20Interface(tokenAddress).transfer(owner, tokens);
    }
}