¿Cuánto cálculo se puede hacer en una función de respaldo?

Simplemente enviando Ether a un contrato, se ejecutará el código del contrato . En Solidity, este código se asigna a lo que llama la función de respaldo.

¿Cuánto trabajo se puede realizar en una función de reserva?

Respuestas (1)

La función de reserva puede hacer tantos cálculos como la cantidad de gas que recibe.

Hay 2 casos (básicamente recipient.sendy recipient.call{value:...}("")) y el caso 2 tiene implicaciones de seguridad y es una parte clave de cómo se atacó y explotó theDAO el 17 de junio de 2016.

Caso 1: 2300 gasolina

La función de respaldo de un recipientcontrato solo obtiene un estipendio de gasolina de 2300 si se invocó con recipient.transferorecipient.send . Esto es lo mismo que una cuenta externa pagando recipientcon web3.eth.sendTransaction({to:recipient, gas:21000, ...}).

La última parte de una publicación de blog de Ethereum explica:

Si desea que su contrato reciba Ether, debe hacer que su función alternativa sea barata. Solo puede usar gas 2300, lo que no permite ninguna escritura de almacenamiento ni llamadas de función que se envíen a lo largo de Ether. Básicamente, lo único que debe hacer dentro de la función de respaldo es registrar un evento para que los procesos externos puedan reaccionar ante el hecho.

Los ejemplos de un proceso externo incluyen filtros y relojes web3.js.

Nota: desde diciembre de 2019, recipient.transfery recipient.sendya no se recomiendan: ¿la transferencia () sigue siendo segura después de la actualización de Estambul?

Caso 2: Por mucha gasolina que se ponga, cuidado con la seguridad

recipient.call{value:...}("")(y el uso de funciones relacionadas como .callcode, .delegatecall) proporcionará a la función de respaldo prácticamente[1] tanta gasolina como le queda a la persona que llama.

Para obtener los mismos efectos (estipendio de gas de 2300) y seguridad que el Caso 1, los llamantes deben limitar explícitamente el gas a cero al invocar el recipientpor:recipient.call{gas: 0, value: ...}("")

(el DAO no limitó el gas y sufrió un ataque de reentrada el 17 de junio de 2016 ).


notas al pie

[1] Explicación de por qué una función de reserva obtiene casi todo el gas, pero no todo. chriseth (autor de Solidity) dijo :

Este es uno de los lugares peculiares de la EVM. No puedes simplemente decir "envía toda mi gasolina junto con la llamada", siempre tienes que dar un número explícito. Tenemos el código de operación de GAS que nos da la cantidad de gasolina que aún está disponible, pero el problema es que realizar la llamada en sí también cuesta algo de gasolina, por lo que tenemos que restar la cantidad de gasolina que cuesta la llamada del valor proporcionado por GAS, y también hay que restar la cantidad de gasolina que cuesta realizar la resta...

es recipient.call.gas(2300).value(...)equivalente a recipient.call.gas(0).value(...)?
@K._ No, el primero manda 2300 gasolina más.
Actualización importante : a partir de mayo de 2021, el uso de sendy ya no transferse considera seguro . Utilice call{value: amount}("")en su lugar.
@PaulRazvanBerg Gracias, agregó la Nota al Caso 1 y también actualizó la sintaxis de Solidity.