Function Signatures y Function Selectors

En este tutorial vamos a aprender qué son y para qué sirven las firmas de funciones (Function Signatures) y los selectores de funciones (Function Selectors) en Solidity.

En Solidity podemos crear una función (contrato FunctionSelector en nuestro ejemplo) la cual nos devolverá el Function Signature:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract FunctionSelector {
    function getSelector(string calldata _func) external pure returns (bytes4) {
        return bytes4(keccak256(bytes(_func)));
    }
}

contract TestFunctionSelector {
    function funcion1(uint a, uint b) external pure returns (uint256) {
        return a + b;
    }

    function funcion2(bool a) external pure returns (bool) {
        return a == true ? false : true;
    }
}

contract CallFunctionSelector {
    function llamada(address _addr, uint256 a, uint256 b) external returns (bool, bytes memory) {
        (bool success, bytes memory data) = _addr.call(abi.encodeWithSignature("funcion1(uint256,uint256)", a, b));
        return (success, data); // data es hexadecimal, lo tenemos que convertir a decimal
    }
}

El Function Signature consiste en una combinación de una función y sus tipos de parámetros. Hay que tener en cuenta que no se incluye el nombre del parámetro, solo su tipo y que los tipos uint se deben pasar como uint256 en el Function Signature.

Vamos a ver un caso práctico con la siguiente función.

function funcion1(uint a, uint b) public {
	
}

El Function Signature de esta función queda de la siguiente manera, todo junto, sin espacios ni punto y coma al final.

funcion1(uint256,uint256)

Para conseguir el Function Selector tendremos que aplicarle un hash Keccak-256, copiar los primeros 4 bytes (primeros 8 caracteres) y añadirle un 0x delante.
Por ejemplo, para la anterior función, si le aplicamos el hash Keccak-256 nos devuelve: 45519205635dffd2ca582e4317dcbbdbf1c455760f52f64dcdc7e323ec8093b2

El Function Selector quedaría de la siguiente manera: 0x45519205

Podéis usar la siguiente utilidad online para aplicar un hash Keccak-256 a un string si no queréis usar un contrato para extraer los Function Selector https://emn178.github.io/online-tools/keccak_256.html

Al tratarse de hashes, los Function Selectors se pueden repetir. Es muy raro que en un mismo contraro ocurra, pero es bueno tenerlo en cuenta. En este enlace https://www.4byte.directory/signatures/?bytes4_signature=0xa9059cbb podemos ver cómo diferentes Function Signatures generan el mismo Function Selector.

Para probar los contratos que tenemos más arriba podemos desplegar en Remix primero el contrato TestFunctionSelector y después CallFunctionSelector. Copiamos la dirección del contrato de TestFunctionSelector y lo pasamos como llamada en el contrato CallFunctionSelector.

La respuesta nos será devuelta en hexadecimal, podemos convertirlo a decimal con esta utilidad: https://www.rapidtables.com/convert/number/hex-to-decimal.html
En nuestro ejemplo (10 + 20), 0x000000000000000000000000000000000000000000000000000000000000001e equivale a 30.

Los function Selector son útiles cuando no tenemos acceso al ABI del contrato. Podemos llamar a una función directamente en Solidity simplemente conociendo su selector de función o firma y aplicando hash a los datos de los parámetros de entrada.

En el próximo tutorial veremos cómo usar lo que hemos aprendido creando una pequeña utilidad la cual nos permitirá ver en tiempo real todas las llamadas a las funciones de los diferentes contratos que están desplegados en la mainnnet y testnet de Meter.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *