Hola Omar! Un par de aclaraciones primero:
sé que con el hash de la función se puede determinar
Técnicamente sí, pero es importante destacar que el selector de la función sólo son los primeros 4 bytes del hash de la firma de la función. 4 bytes no tienen las mismas garantías de seguridad que 32. Con lo que voy a lo siguiente:
por lo que si el bytecode final contiene 633ccfd60b podemos asumir que existe la funcion withdraw dentro de ese contrato
Esto es correcto, pero tiene truco.
Como el selector de una función son 4 bytes, la probabilidad de que esos 4 bytes existan de forma consecutiva en el bytecode es suficientemente alta como para ignorar, puede que te encuentres bytes consecutivos iguales pero que sean realmente instrucciones.
La única forma de asegurar que una función con selector 0x633ccfd6 es si esta existe en el entry point hub del bytecode.
Más información acá
De todas formas, esto no garantiza que la función sea withdraw, dado que alguna otra función puede casualmente derivar los mismos primeros 4 bytes, por lo que, aunque determinado selector exista en el hub del contrato, no es seguro asumir que es la función que esperas. Esto se conoce como "function selector clashing"
Ahora sí, respondiendo a tu pregunta:
cómo se podría determinar si el contracto contiene una función con argumentos y el tipo de accessiblidad?
Una función internal o private no aparece en entry point del contrato.
Funciones public o external sí aparecen ahí, pero no estoy seguro de si hay alguna diferencia sustancial en el bytecode que permita deducir su visibilidad.
Tampoco es posible saber los argumentos, a menos que analices el body de la función para determinar qué parámetros lee de calldata, cuyo encoding es complejo y puede que no sea preciso. Por ejemplo, un bytes[] memory y un bytes[] calldata tienen encoding similar pero uno apunta a memory y otro a calldata. Es difícil generalizar.
Lo que puedes hacer es usar un decompiler, pero no te da toda la información y generalmente el output es difícil de leer.
https://ethervm.io/decompile
Otra opción que puedes usar si quieres saber si un contrato tiene una función, es simulándola. Tenderly es una muy buena herramienta para simulations:
https://tenderly.co/transaction-simulator