Pre bifurcación de Bizancio, podría usar gas == gasUsed
para detectar cuando una transacción ha fallado (más detalles en ¿Cómo se puede detectar el estado de la transacción de un error lanzado cuando el gas puede ser exactamente el mismo que el gas utilizado para una transacción exitosa? )
Después de la bifurcación de Byzantium, el código de operación de reversión ahora devuelve una cantidad de gas utilizada mucho menor. ¿Cómo detecto una transacción fallida después de la bifurcación de Bizancio?
Ver también:
Después de la bifurcación de Bizancio, eth.getTransactionReceipt(...)
devolverá un status
campo. El campo de estado tiene un valor de 0
cuando una transacción ha fallado con el REVERT
código de operación y 1
cuando la transacción ha tenido éxito.
Respondiendo al comentario de @thomas-jay-rush, cuando una transacción falla por un motivo que no sea REVERT
(es decir THROW
), el campo de estado tendrá un valor de 0
y gasUsed
será igual a gas
. Consulte tx 0xa0a5e34b como ejemplo.
Configuré el número de bloque de Byzantium en mi cadena de bloques de desarrollo usando lo siguiente genesis.json
:
{
"config": {
"homesteadBlock": 1,
"byzantiumBlock": 12
},
"nonce": "0",
"difficulty": "0x400",
"mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x3B4A1B44",
"alloc": {
"0xa00af22d07c87d96eeeb0ed583f8f6ac7812827e": {
"balance": "10000000000000000000000000"
},
"0xa11aae29840fbb5c86e6fd4cf809eba183aef433": {
"balance": "10000000000000000000000000"
}
}
}
Puedo ver que la bifurcación de Byzantium está activa en el siguiente geth
mensaje:
INFO [10-09|23:30:37] Configuración de cadena inicializada config="{ChainID: Homestead: 1 DAO: DAOSupport: false EIP150: EIP155: EIP158: Byzantium: 12 Engine: unknown}"
status
de0x0
Aquí está la información del recibo de la transacción de una transacción fallida con el REVERT
código de operación:
> eth.getTransactionReceipt("0x6c039439191ed046f8d4a92734bb6c23b92c175df39ce2f089ac84c590b94918")
{
blockHash: "0xf25b938c85772aa0abbbc9931e6da7a6e46c577619fb5004f2d85fdbe359eb60",
blockNumber: 89,
contractAddress: null,
cumulativeGasUsed: 35983,
from: "0xa11aae29840fbb5c86e6fd4cf809eba183aef433",
gasUsed: 35983,
...
status: "0x0",
to: "0x0e946b999033257976aa5cbe0e3530618ca1582d",
transactionHash: "0x6c039439191ed046f8d4a92734bb6c23b92c175df39ce2f089ac84c590b94918",
transactionIndex: 0
}
Lo mismo status: "0x0"
se devuelve al ejecutar una throw
instrucción compilada con Solidity 0.4.11.
status
de0x1
Y aquí está la información del recibo de transacción de una transacción exitosa:
> eth.getTransactionReceipt("0xbdacfebf6299a260adfa993421aeb26353aa2b4dd0e6f290d2acfd6a9b828a62")
{
blockHash: "0xbda8b2d2850306e8a02be074f11ffe4f2243003df6e9c4adb1bbdcda1faf2e42",
blockNumber: 87,
contractAddress: null,
cumulativeGasUsed: 126952,
from: "0xa11aae29840fbb5c86e6fd4cf809eba183aef433",
gasUsed: 126952,
logs: [{
address: "0x0e946b999033257976aa5cbe0e3530618ca1582d",
blockHash: "0xbda8b2d2850306e8a02be074f11ffe4f2243003df6e9c4adb1bbdcda1faf2e42",
blockNumber: 87,
data: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000",
logIndex: 0,
removed: false,
topics: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x000000000000000000000000a33a6c312d9ad0e0f2e95541beed0cc081621fd0", "0x000000000000000000000000a55a151eb00fded1634d27d1127b4be4627079ea"],
transactionHash: "0xbdacfebf6299a260adfa993421aeb26353aa2b4dd0e6f290d2acfd6a9b828a62",
transactionIndex: 0
}, {
...
}],
...
status: "0x1",
to: "0x0e946b999033257976aa5cbe0e3530618ca1582d",
transactionHash: "0xbdacfebf6299a260adfa993421aeb26353aa2b4dd0e6f290d2acfd6a9b828a62",
transactionIndex: 0
}
eth.getTransactionReceipt(...)
La horquilla anterior a Bizancio no incluye el status
campo.
Desde https://github.com/ethereum/go-ethereum/blob/master/core/types/receipt.go#L39-L42 :
ReceiptStatusFailed = uint(0)
ReceiptStatusSuccessful = uint(1)
Solo hay un estado de fallido (=0) o exitoso (=1).
Consulte EIP 658: Incorporación de datos de devolución de transacciones en recibos para obtener más información.
Aquí hay una transacción que se ejecutó con éxito: 0x142b8830
Y aquí hay una transacción que falló al usar el REVERT
código de operación: 0x67a5f644
La transacción fallida no se puede distinguir de la transacción exitosa en EtherScan actualmente, excepto que la transacción fallida consumió menos gas que la transacción exitosa y la transacción fallida no registró un evento pero la transacción exitosa sí.
Hice ping a EtherScan sobre este problema potencial.
Actualización del 15 de octubre de 2017 Ahora hay un campo TxReceipt Status: en la página de transacciones de EtherScan que muestra Success or Fail .
Odio decírtelo, pero a veces el gas usado y el gas suministrado son los mismos y tuvo éxito.
No puedo recordar cuál, creo que fue Parity, donde las estimaciones son 100% precisas.
Lefteris
privacidadisahumanright.eth
mtbitcoin
privacidadisahumanright.eth
thomas jay prisa
privacidadisahumanright.eth