Solidity: tipos de funciones – Adrian Rodriguez
Los tipos de funciones nos sirven para definir restricciones de acceso a las mismas. Tenemos 4 tipos:
- External
- Internal
- Private
- Public
Voy a explicar cada una de ellas para intentar despejar las posibles dudas que haya.
External: cuando definimos una función como external estamos evitando que sea llamada internamente, es decir, desde otras funciones del contrato donde se encuentra definida o de los herederos del mismo.
Public: todos pueden llamar a esta función.
Private: sólo puede se puede acceder desde el contrato donde se encuentra la función, no se puede desde fuera ni desde los herederos del contrato. Esto no quiere decir que no pueda verse el contenido de la misma, todo lo que haya en un smart contract lo podrá ver cualquiera.
Internal: solo permitimos el acceso a la función desde el propio contrato y desde los herederos de éste.
Es importante saber cuándo usar cada tipo, ya que un buen uso consigue que optimicemos el consumo de gas y un mal uso puede llevar a errores graves del código. Además, se considera buena práctica definir explícitamente el tipo de función, así ayudamos a su lectura a otros desarrolladores y los usuarios que quieran usar nuestro contrato.
Primero, las funciones son por defecto public, por tanto, pueden ser llamadas desde todas partes. Esto nos lleva a que es necesario definir de forma explícita el tipo de función si queremos limitar las llamadas a la nuestra. Incluso, se considera buena práctica hacerlo y, más aún, definirla correctamente. Un buen ejemplo de no definir correctamente el tipo de las funciones fue el ataque a la cartera de Parity, en cuyo código la función initWallet, que cambiaba el dueño de la cartera, se dejó como public, lo cual permitió el robo de una no despreciable cantidad de ethers.
Segundo, la diferencia entre external y public, además de las restricciones de acceso, también reside en cómo tratan los parámetros de entrada. Una función public copiará los argumentos en memoria, lo cual es bastante caro. Esto es así, ya que dichas funciones pueden ser llamadas internamente, proceso totalmente diferente que si son llamadas desde fuera. Dicha diferencia radica en que las llamadas internas esperan que los parámetros estén en memoria. Mientras que las funciones external no necesitan de este proceso, ya que pueden leer los argumentos directamente desde el calldata, ya que nunca podrán ser llamadas internamente.
Veámoslo con un ejemplo:
La siguiente función:
function getExternal(uint _value) public returns (uint)
Usa la siguiente cantidad de gas:
Pero si la redefinimos como public:
function getPublic(uint _value) public returns (uint)
El uso de gas aumenta:
Para que puedas comprobarlo tu mismo dejo aquí el ejemplo.
Por tanto, a la hora de definir una función como public o external, hay que tener claro si sólo se va a utilizar desde fuera del contrato o no, ya que podemos optimizar el coste en gas de la llamada.
Por otro lado, considerando las llamadas internas, éstas se ejecutan a través de un JUMP (y como se dijo antes, los parámetros se pasan como punteros), lo cual hace que sean la más baratas de hacer.
Fuentes
Solidity.readthedocs.io. (2019). Types — Solidity 0.4.21 documentation. [online] Available at: https://solidity.readthedocs.io/en/v0.4.21/types.html [Accessed 22 Jul. 2019].
Wojciechowski, J., Hess, T. and Sinha, S. (2019). `external` vs `public` best practices. [online] Ethereum Stack Exchange. Available at: https://ethereum.stackexchange.com/questions/19380/external-vs-public-best-practices/19391#19391 [Accessed 22 Jul. 2019].
Published at Mon, 26 Aug 2019 11:52:39 +0000
{flickr|100|campaign}
