¿Tener un contrato separado para el almacenamiento aumenta el costo del gas para realizar una transacción?

He estado leyendo mucho sobre la capacidad de actualización de los contratos inteligentes, y parece que la principal práctica predominante es que, en general, es una buena idea mantener la lógica del contrato separada del almacenamiento del contrato, por lo que es posible actualizar uno y no tener que cambiar el otro.

Mi pregunta es la siguiente: el hecho de que un contrato tenga que llamar a otro contrato aumenta la cantidad de gas que se gasta por esa lógica. Por ejemplo, digamos que tenía un contrato que buscaba un número X y luego lo agregaba al número 5.

En un caso, el contrato se almacena en el mismo X, por lo que puede buscarlo directamente. En el otro caso, un contrato separado es responsable de almacenar X, lo que hace que un contrato haga una llamada de función para obtener X. ¿Cuesta más gasolina? Si es así, ¿es posible decir cuánto más?

¡Gracias!

Respuestas (2)

Sí, pero es recomendable analizar las ventajas y desventajas de los mayores costos de gas, con la capacidad de actualización que brinda a su aplicación.

La mayoría de los contratos actualizables involucrarán bibliotecas y el código de operación DELEGATECALL y algunos de los costos se describen en parte de los documentos de Solidity sobre bibliotecas :

Las bibliotecas pueden verse como contratos base implícitos de los contratos que las utilizan. No serán explícitamente visibles en la jerarquía de herencia, pero las llamadas a funciones de biblioteca se ven como llamadas a funciones de contratos base explícitos (Lf() si L es el nombre de la biblioteca). Además, las funciones internas de las bibliotecas son visibles en todos los contratos, como si la biblioteca fuera un contrato base. Por supuesto, las llamadas a funciones internas utilizan la convención de llamadas internas, lo que significa que todos los tipos internos se pueden pasar y los tipos de memoria se pasarán por referencia y no se copiarán. Para realizar esto en EVM, el código de las funciones de la biblioteca interna (y todas las funciones llamadas desde allí) se incluirán en el contrato de llamada y se usará una llamada JUMP normal en lugar de una DELEGATECALL.

Básicamente, cuando todo está en un contrato, puede usar referencias, evitar copias y usar el código de operación JUMP.

Cuando se trata de contratos externos, DELEGATECALL es mucho más caro que JUMP (actualmente 700 gas vs 10 gas), y hay otros costos como la copia de datos.

Pero también es importante perfilar el caso de uso específico y comparar. Para el ejemplo simple dado arriba, el costo de una LLAMADA/LLAMADA DELEGADA sería abrumador. Pero en otros casos de uso, estos costos adicionales de gas pueden tener un impacto general mucho menor.

Me hizo evitar responder "No"... Estoy pensando que sí, los costos de cómputo son más altos, pero dado que estamos hablando de almacenamiento, el costo de cómputo se ve eclipsado por el costo de cambio de estado en la mayoría de los casos. En el caso de las lecturas, las llamadas locales no tienen costo de gasolina.
@RobHitchens Creo que su respuesta es buena y la votaría a favor: estamos presentando diferentes consideraciones y perspectivas y no veo mucha incongruencia. (Estoy de acuerdo en que las primeras respuestas pueden influir en las adicionales: no estoy seguro de cómo reducirlo; lamento que haya tenido el efecto de rehuir, especialmente como una respuesta bien escrita como la suya).

Diría que sí, un poco, pero no, no es tan importante en la mayoría de los casos. Dejando de lado el costo de implementación único, habrá un código adicional para ejecutar con cada transacción. No es gratis, pero el código adicional no será especialmente más caro de operar en la mayoría de los casos.

Eche un vistazo a los costos de gas por operación (sin garantía implícita): https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0 .

Una heurística básica es que los códigos de operación de cambio de estado (por ejemplo, SSTORE) son bastante altos en comparación con los códigos de operación de cálculo que no cambian la cadena de bloques. Por lo general, se pueden agregar pasos generales adicionales de bajo costo (por ejemplo, buscar una dirección de contrato y formar un mensaje) sin aumentar mucho el costo total de un cambio de estado. El cambio de estado será costoso en cualquier caso.

Las operaciones de lectura a menudo se manejan con funciones constantes o llamadas locales que no usan gas en absoluto . Por lo tanto, las preocupaciones sobre los costos de transacción generalmente se limitan a las transacciones que darán como resultado un cambio de estado. Por lo tanto, crear/insertar, actualizar y eliminar tiene un costo (la mayor parte de operaciones como SSTORE). Las lecturas suelen ser gratuitas, independientemente de su complejidad. Considere también que muchos sistemas usan almacenamiento fuera de la cadena alimentado por emisores de eventos que mantienen una copia de los hechos "oficiales" por motivos de rendimiento. Otro ejemplo de una situación en la que solo preocupa el costo de las actualizaciones.

Para jugar con un ejemplo específico y comparar costos, podría considerar codificar funciones representativas en ambos sentidos y comparar el consumo real de gas. El compilador Solidity Realtime mostrará el código de bytes después de la compilación. Puede pasar por alto el código fuente para ver qué pasos reales son "caros" y optimizarlos en consecuencia.

Como nota al pie, tenga cuidado con el costo oculto de la complejidad adicional. Si bien los contratos actualizables son ventajosos en muchos sentidos, hay un conjunto de compensaciones similares a yin-yan a considerar para cada caso de uso. Por ejemplo, la capacidad de actualización podría reducir la confiabilidad en algunos casos y es potencialmente una nueva fuente de errores.

Espero que sea útil.

Como se indica en la respuesta a continuación, hay un costo de gasolina significativo de 700 por llamada a la biblioteca, en comparación con 10 para una operación JUMP.