contract ResolveToken{
	address pyramid;

	constructor(address _pyramid) public{
		pyramid = _pyramid;
	}

	modifier pyramidOnly{
	  require(msg.sender == pyramid);
	  _;
    }

	event Transfer(
		address indexed from,
		address indexed to,
		uint256 amount,
		bytes data
	);

	event Mint(
		address indexed addr,
		uint256 amount
	);

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

	string public name = "Resolve";
    string public symbol = "PoWHr";
    uint8 constant public decimals = 18;
	uint256 private _totalSupply;

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }
	function mint(address _address, uint _value) public pyramidOnly(){
		balances[_address] += _value;
		_totalSupply += _value;
		emit Mint(_address, _value);
	}

	// Function that is called when a user or another contract wants to transfer funds .
	function transfer(address _to, uint _value, bytes memory _data) public returns (bool success) {
		if (balanceOf(msg.sender) < _value) revert();
		if(isContract(_to)) {
			return transferToContract(_to, _value, _data);
		}else{
			return transferToAddress(_to, _value, _data);
		}
	}

	// Standard function transfer similar to ERC20 transfer with no _data .
	// Added due to backwards compatibility reasons .
	function transfer(address _to, uint _value) public returns (bool success) {
		if (balanceOf(msg.sender) < _value) revert();
		//standard function transfer similar to ERC20 transfer with no _data
		//added due to backwards compatibility reasons
		bytes memory empty;
		if(isContract(_to)){
			return transferToContract(_to, _value, empty);
		}else{
			return transferToAddress(_to, _value, empty);
		}
	}

	//assemble the given address bytecode. If bytecode exists then the _addr is a contract.
	function isContract(address _addr) public view returns (bool is_contract) {
		uint length;
		assembly {
			//retrieve the size of the code on target address, this needs assembly
			length := extcodesize(_addr)
		}
		if(length>0) {
			return true;
		}else {
			return false;
		}
	}

	//function that is called when transaction target is an address
	function transferToAddress(address _to, uint _value, bytes memory _data) private returns (bool success) {
		moveTokens(msg.sender,_to,_value);
		emit Transfer(msg.sender, _to, _value, _data);
		return true;
	}

	//function that is called when transaction target is a contract
	function transferToContract(address _to, uint _value, bytes memory _data) private returns (bool success) {
		moveTokens(msg.sender, _to, _value);
		ERC223ReceivingContract reciever = ERC223ReceivingContract(_to);
		reciever.tokenFallback(msg.sender, _value, _data);
		emit Transfer(msg.sender, _to, _value, _data);
		return true;
	}

	function moveTokens(address _from, address _to, uint _amount) private{
		balances[_from] -= _amount;
		balances[_to] += _amount;
	}

    function balanceOf(address _owner) public view returns (uint balance) {
        return balances[_owner];
    }

    function allowance(address src, address guy) public view returns (uint) {
        return approvals[src][guy];
    }

    function transferFrom(address src, address dst, uint wad) public returns (bool){
        require(approvals[src][msg.sender] >=  wad, "That amount is not approved");
        require(balances[src] >=  wad, "That amount is not available from this wallet");
        if (src != msg.sender) {
            approvals[src][msg.sender] -=  wad;
        }
		moveTokens(src,dst,wad);

        bytes memory empty;
        emit Transfer(src, dst, wad, empty);

        return true;
    }

    function approve(address guy, uint wad) public returns (bool) {
        approvals[msg.sender][guy] = wad;

        emit Approval(msg.sender, guy, wad);

        return true;
    }

    event Approval(address indexed src, address indexed guy, uint wad);
}
function transferToAddress(address _to, uint _value, bytes memory _data) private returns (bool success) {
	moveTokens(msg.sender,_to,_value);
	emit Transfer(msg.sender, _to, _value, _data);
	return true;
}

//function that is called when transaction target is an address