abstract contract ERC777Receiver is IERC777Recipient {

    // Needed constants to accept ERC777 tokens in deposit
    IERC1820Registry constant private _erc1820 = // See EIP1820
        IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
    bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = // See EIP777
        keccak256("ERC777TokensRecipient");

    constructor() public {
        // Register as a token receiver
        _erc1820.setInterfaceImplementer(
            address(this), 
            TOKENS_RECIPIENT_INTERFACE_HASH, 
            address(this)
        );
    }

    address private token;

    //  @dev: This hook is called when the contract receives GeoTokens.
    //  The contract can only receive GeoTokens from the owner
    function tokensReceived(
        address /*operator*/,
        address from,
        address /*to*/,
        uint256 ,
        bytes calldata /*userData*/,
        bytes calldata /*operatorData*/
    ) external override {
        require(msg.sender == getToken(), "GeoPreSale.tokensReceived() - Wrong token");
        require(from == getOwner(), "GeoPreSale.tokensReceived() - Only owner");
    }

    function getOwner() virtual public view returns(address);

    function getToken() virtual public view returns(address);
}
function tokensReceived(
    address /*operator*/,
    address from,
    address /*to*/,
    uint256 ,
    bytes calldata /*userData*/,
    bytes calldata /*operatorData*/
) external override {
    require(msg.sender == getToken(), "GeoPreSale.tokensReceived() - Wrong token");
    require(from == getOwner(), "GeoPreSale.tokensReceived() - Only owner");
}

//  @dev: This hook is called when the contract receives GeoTokens.
//  The contract can only receive GeoTokens from the owner