abstract contract RawStakingContract {
    using Address for address;

    /**
    * @dev Returns address of StakingInterfaceRouter
    */
    function router() public view virtual returns (StakingInterfaceRouter);

    /**
    * @dev Checks permission for calling fallback function
    */
    function isFallbackAllowed() public virtual returns (bool);

    /**
    * @dev Withdraw tokens from staking contract
    */
    function withdrawTokens(uint256 _value) public virtual;

    /**
    * @dev Withdraw ETH from staking contract
    */
    function withdrawETH() public virtual;

    receive() external payable {}

    /**
    * @dev Function sends all requests to the target contract
    */
    fallback() external payable {
        require(isFallbackAllowed());
        address target = address(router().target());
        require(target.isContract());
        // execute requested function from target contract
        (bool callSuccess, ) = target.delegatecall(msg.data);
        if (callSuccess) {
            // copy result of the request to the return data
            // we can use the second return value from `delegatecall` (bytes memory)
            // but it will consume a little more gas
            assembly {
                returndatacopy(0x0, 0x0, returndatasize())
                return(0x0, returndatasize())
            }
        } else {
            revert();
        }
    }
}
/**
 * @notice Internal base class for AbstractStakingContract and InitializableStakingContract
 */
function router() public view virtual returns (StakingInterfaceRouter);

/**
 * @dev Returns address of StakingInterfaceRouter
 */