Introducción
EIP-150, o Ethereum Improvement Proposal 150, es una actualización del protocolo para la blockchain de Ethereum. Fue propuesta el 18 de marzo de 2016 e implementada el 20 de julio de 2016, como parte del hard fork Byzantium de Ethereum. Hubo varios cambios en el protocolo, pero nos centraremos en la regla 63/64 que introdujo.
Antes de profundizar en los detalles de EIP-150, es importante entender el concepto de gas y las llamadas a contratos en Ethereum.
Autoría
Este artículo fue coescrito por tanim0la (Twitter) como parte del RareSkills Technical Writing Program.
El concepto de gas en Ethereum
El gas es una unidad de medida para la potencia computacional requerida para ejecutar una operación o contrato particular en la Ethereum Virtual Machine (EVM).
Cada operación o contrato en la EVM requiere una cierta cantidad de gas para ejecutarse, la cual debe ser pagada por el usuario en forma de Ether. Siempre que un usuario inicia una transacción, está obligado a cubrir los costos acumulativos de todas las operaciones realizadas por su transacción.
Para una transferencia básica en Ethereum, el costo de dicha operación asciende exactamente a 21,000 de gas; sin embargo, las operaciones más complejas pueden requerir un número significativamente mayor de unidades de gas, pudiendo ascender potencialmente a millones.
Llamadas a Contratos
En Ethereum, un contrato (conocido como “caller”) tiene la capacidad de invocar a otros contratos (denominados “callees”) a través de opcodes especiales como CALL, STATICCALL y DELEGATECALL. Cuando esto ocurre, los “callees” reciben una cantidad específica de gas, similar a la que recibirían si fueran llamados directamente a través de una transacción.
La cantidad de gas asignada está determinada en parte por el caller, tal como se especifica en los parámetros del opcode. Para obtener más información, consulte la especificación de CALL proporcionada aquí como ejemplo. Si un callee recibe una cantidad insuficiente de gas, sus operaciones se revierten, desencadenando una excepción de “out of gas”.
Especificación de EIP-150
Anteriormente, un caller podía enviar todo el gas que se le había proporcionado al callee. Sin embargo, esto permitía una serie potencialmente interminable de contratos llamando a otros contratos, ya que el costo de gas de cada llamada era bajo.
Para evitar la aparición de un problema de “stack too deep” en la implementación del nodo de Ethereum, la profundidad máxima se limitó a 1024, lo cual se mantiene vigente en la actualidad. Cuando se alcanza esta profundidad, la última llamada se revertirá.
Como resultado, los firmantes de transacciones tenían la capacidad de garantizar que una llamada en particular se revertiría haciendo que la transacción pasara por una secuencia de llamadas hasta alcanzar una profundidad de 1023 antes de llamar al smart contract deseado. Este tipo de ataque se conoce como el “Call Depth Attack”.
Aquí hay un ejemplo de un contrato que sería vulnerable a este ataque:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.5;
// DO NOT USE!!!
contract Auction {
address highestBidder;
uint256 highestBid;
function bid() external payable {
if (msg.value < highestBid) revert();
if (highestBidder != address(0)) {
payable(highestBidder).send(highestBid); // refund previous bidder
}
highestBidder = msg.sender;
highestBid = msg.value;
}
}
Antes de la implementación de EIP-150, el contrato anterior podía ser susceptible al “Call Depth Attack”. Esto se debe a que un postor malintencionado podría iniciar una llamada recursiva a sí mismo, haciendo que la profundidad del stack aumentara a 1023 antes de llamar a la función bid(). Como resultado, la llamada send(highestBid) fallaría silenciosamente, lo que significa que el postor anterior no recibiría un reembolso, mientras que el nuevo postor aún se convertiría en el highestBidder.
La solución propuesta en EIP-150 fue reservar una porción del gas disponible dentro del contrato caller, después de llamar al contrato del callee (es decir, la llamada no puede consumir más de 63/64 del gas del padre).
Fórmula para el gas reservado para el padre:
Reserved portion of the available gas = available gas at Stack depth N - ((63/64) * available gas at Stack depth N)
¡Probemos la fórmula anterior!
Assume: available gas at Stack depth 0 = 1000
Reserved portion of the available gas = 1000 - ((63/64) * 1000) = 15
La regla 63/64: Gas que el callee puede recibir
La siguiente fórmula calcula el gas disponible en cualquier profundidad de stack. Además, el gas disponible es inversamente proporcional a la profundidad del stack (cuanto mayor sea la profundidad del stack, menor será el gas disponible).
Gas available at Stack depth 0 = Initial gas available * (63/64)^0
Gas available at Stack depth 1 = Initial gas available * (63/64)^1
Gas available at Stack depth 2 = Initial gas available * (63/64)^2
Gas available at Stack depth 3 = Initial gas available * (63/64)^3
.
.
.
Gas available at Stack depth N = Initial gas available * (63/64)^N
Aquí hay algunos valores de ejemplo.
Assume; Initial gas available = 3000
Gas available at Stack depth 10 = 3000 * (63/64)^10 = 2562
Gas available at Stack depth 20 = 3000 * (63/64)^20 = 2189

Debido a la rápida disminución de gas en cada nivel de profundidad adicional, la profundidad recursiva se limitaría de forma natural. Aunque el límite de profundidad de stack de 1024 todavía existe en la implementación actual de Ethereum, es prácticamente inalcanzable.
Además de la modificación mencionada anteriormente, EIP-150 también introdujo un cambio en los opcodes CALL\* donde el gas proporcionado es ahora un valor máximo en lugar de un valor estricto. Esto significa que si el gas disponible en el contrato que está siendo llamado (callee) es menor que el valor especificado dado al opcode, la llamada continuará pero con una cantidad reducida de gas en lugar de fallar, lo cual no era el caso en versiones anteriores.
Conclusiones
En resumen, el EIP-150 se introdujo para prevenir el Call Depth Attack. Lo hace aplicando la especificación de la regla 63/64, las implicaciones de esto son que incluso cuando se envía explícitamente todo el gas left en una llamada, una fracción seguirá reservada para el contrato que realiza la llamada.
Aprende más
Únete a nuestro Solidity Bootcamp para desarrollar una comprensión integral de la EVM y el protocolo de Ethereum.
Publicado originalmente el 23 de marzo de 2023