Me gustaría obtener las transacciones internas del contrato como: https://etherscan.io/address/0xd654bdd32fc99471455e86c2e7f7d7b6437e9179#internaltx
Estoy usando la API web3. ¿Hay alguna forma de hacerlo? ¿Dónde aparecen en la cadena de bloques?
Actualmente no hay ninguna forma de hacer esto usando la API web3. Las transacciones internas, a pesar del nombre (que no forma parte del papel amarillo; es una convención que la gente ha establecido) no son transacciones reales y no están incluidas directamente en la cadena de bloques; son transferencias de valor que se iniciaron mediante la ejecución de un contrato.
Como tal, no se almacenan explícitamente en ningún lugar: son los efectos de ejecutar la transacción en cuestión en el estado de la cadena de bloques. Los exploradores de blockchain como etherscan los obtienen ejecutando un nodo modificado con un EVM instrumentado, que registra todas las transferencias de valor que tuvieron lugar como parte de la ejecución de transacciones, almacenándolas por separado.
En el protocolo Ethereum solo hay transacciones y llamadas de mensajes. Una transacción es un tipo de llamada de mensaje.
Una transacción puede realizar otras llamadas de mensajes, pero estas no son transacciones (aunque los exploradores de cadenas de bloques pueden etiquetarlas incorrectamente como "transacciones internas"). Estas llamadas de mensajes (internos) no se publican en la cadena de bloques. Para encontrar las llamadas internas , la transacción debe procesarse a través de EVM (por ejemplo, https://github.com/ethereumjs/ethereumjs-vm ).
Para intentar ilustrar, una transacción en Javascript se ve así:
{
from: ...,
to: "C1",
value: ...,
gas: ...,
data: ...,
gasPrice: ...,
nonce: ...
}
Esto es lo que verá en la cadena de bloques. Las llamadas internas son los efectos de tomar la data
parte, alimentarla con to
el contrato C1 y ejecutar la máquina virtual Ethereum. Esto data
es lo que le dice a C1 que debe llamar a otro contrato C2: no hay ningún {from:C1, to:C2,...}
objeto separado en la cadena de bloques que se necesite.
El data
está codificado de acuerdo con una ABI que dice cosas como qué función debe llamarse y cuáles son los argumentos.
Nota: con la respuesta de @Nick, todas las transferencias de valor son una llamada de mensaje. Pero no todas las llamadas de mensajes son transferencias de valor. Una transferencia de valor es cuando a un contrato simplemente se le paga algo de Ether/wei (los datos son cero), pero los contratos pueden llamarse entre sí sin pagarse entre sí (los datos no son cero, el valor es cero).
Afortunadamente, Geth EVM tiene nuevas herramientas para hacer esto. Es posible usar debug_traceTransaction con la API de RPC.
En NodeJS:
var web3 = require('web3').web3;
web3.currentProvider.sendAsync({
method: "debug_traceTransaction",
params: ['0x3fac854179691e377fc1aa180b71a4033b6bb3bde2a7ef00bc8e78f849ad356e', {}],
jsonrpc: "2.0",
id: "2"
}, function (err, result) {
...
});
Luego, necesitará 'CREATE', 'CALL', 'CALLCODE' y 'DELEGATECALL' códigos de operación y realizar un seguimiento de la pila. Puede leer la explicación detallada de Nick Johnson : Instrumenting EVM
Si finalmente lo implemento, escribiré un artículo completo con el código.
Con versiones recientes de Parity (probadas en 1.8.3
) también es posible. El método RPC es trace_replayTransaction
. El código correspondiente es algo así como
web3.currentProvider.sendAsync({
method: "trace_replayTransaction",
params: [desiredTransactionHash, ['trace']],
jsonrpc: "2.0",
id: "1"
}, function (err, out) {
console.log(out);
}
La documentación se encuentra en el repositorio de parity github.
Puede usar callTracer
introducido en geth 1.8 https://github.com/ethereum/go-ethereum/pull/15516
$ nc -U /work/temp/rinkeby/geth.ipc
{"id": 1, "method": "debug_subscribe", "params": ["traceChain", "0x0", "0xffff", {"tracer": "callTracer"}]}
La API transmitirá una notificación de IPC por bloque no vacío. Una excepción es el último bloque, que se informará incluso si está vacío para que el usuario sepa que la transmisión ha terminado.
{"jsonrpc":"2.0","id":1,"result":"0xe1deecc4b399e5fd2b2a8abbbc4624e2"}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0x37","hash":"0xdb16f0d4465f2fd79f10ba539b169404a3e026db1be082e7fd6071b4c5f37db7","traces":[{"from":"0x31b98d14007bdee637298086988a0bbd31184523","gas":"0x0","gasUsed":"0x0","input":"0x","output":"0x","time":"1.077µs","to":"0x2ed530faddb7349c1efdbf4410db2de835a004e4","type":"CALL","value":"0xde0b6b3a7640000"}]}}}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0xf43","hash":"0xacb74aa08838896ad60319bce6e07c92edb2f5253080eb3883549ed8f57ea679","traces":[{"from":"0x31b98d14007bdee637298086988a0bbd31184523","gas":"0x0","gasUsed":"0x0","input":"0x","output":"0x","time":"1.568µs","to":"0xbedcf417ff2752d996d2ade98b97a6f0bef4beb9","type":"CALL","value":"0xde0b6b3a7640000"}]}}}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0xf47","hash":"0xea841221179e37ca9cc23424b64201d8805df327c3296a513e9f1fe6faa5ffb3","traces":[{"from":"0xbedcf417ff2752d996d2ade98b97a6f0bef4beb9","gas":"0x4687a0","gasUsed":"0x12e0d","input":"0x6060604052341561000c57fe5b5b6101828061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063230925601461003b575bfe5b341561004357fe5b61008360048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506100c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600185858585604051806000526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000866161da5a03f1151561014257fe5b50506020604051035190505b9493505050505600a165627a7a7230582054abc8e7b2d8ea0972823aa9f0df23ecb80ca0b58be9f31b7348d411aaf585be0029","output":"0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063230925601461003b575bfe5b341561004357fe5b61008360048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506100c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600185858585604051806000526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000866161da5a03f1151561014257fe5b50506020604051035190505b9493505050505600a165627a7a7230582054abc8e7b2d8ea0972823aa9f0df23ecb80ca0b58be9f31b7348d411aaf585be0029","time":"658.529µs","to":"0x5481c0fe170641bd2e0ff7f04161871829c1902d","type":"CREATE","value":"0x0"}]}}}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0xfff","hash":"0x254ccbc40eeeb183d8da11cf4908529f45d813ef8eefd0fbf8a024317561ac6b"}}}
El seguimiento de bloques individuales es concurrente en las transacciones (limitado a un número de núcleos) y también hace que el seguimiento de la cadena sea concurrente en los bloques (limitado a un número de núcleos).
Para obtener información sobre transacciones internas, puede utilizar debug_traceTransaction. El método devolverá un seguimiento completo de la transacción. Mediante los códigos de operación y los parámetros de cada paso, puede obtener la información que necesita.
Hay 2 problemas principales: 1. Identificar el principio de funcionamiento de los códigos de operación porque, por ejemplo, no siempre CALL da como resultado una transacción interna 2. Con una gran cantidad de pasos en el seguimiento, es posible que la respuesta no quepa en el búfer
El segundo problema se puede resolver pasando el segundo parámetro a los métodos para procesar los pasos en el lado geth. Puede encontrar más detalles aquí: https://github.com/ethereum/go-ethereum/wiki/Management-APIs#debug_tracetransaction
La lógica de cómo manejar los códigos de operación se puede encontrar aquí https://github.com/Arachnid/etherquery/blob/master/etherquery/trace.go#L102 (para la implementación de go) o aquí https://github.com/tet32 /etherscanner/blob/master/traceStepFunction.js (para la implementación de nodejs)
De acuerdo con el anuncio de la versión 1.1 de Parity , podría hacerlo si cambia a este cliente. Citando:
Nuevas API JSONRPC para rastrear, rastrear e inspeccionar todas las llamadas de mensajes y transferencias de saldo, incluidas las que ocurren como "transacciones internas";
Aunque todavía no lo he probado.
Actualmente no hay forma de hacer esto usando la API de Web3. Sus dos opciones son (a) ejecutar un nodo Parity (puede ser costoso y demorar hasta semanas en sincronizarse) o (b) usar el seguimiento de la actividad de la dirección (como transacciones internas) de Alchemy Notify.
Recomiendo encarecidamente usar Alchemy Notify, era gratis y estaba listo y funcionando en menos de 5 minutos. Aquí hay un enlace a sus documentos: https://docs.alchemyapi.io/alchemy/guides/using-webhooks#address-activity
¡La mejor de las suertes!
Si bien las transacciones internas tienen consecuencias reales en los saldos de las cuentas, sorprendentemente, las transacciones internas en sí mismas no se almacenan en la cadena. Para ver las transacciones internas, debe ejecutar la transacción y rastrear las llamadas que realiza. Si bien algunos contratos registran eventos en la cadena que registran la actividad interna, muchos no lo hacen porque hacerlo requiere gas adicional.
^ del blog Blocknative.com: https://blog.blocknative.com/blog/eth-internal-transactions
Su sistema Notify ahora admite transacciones internas. Puede obtener una actualización a través de su API cuando su billetera o contrato sea parte de una transacción interna
Usando la API de Etherscan, puede hacer el trabajo.
Para obtener más información sobre el concepto, consulte esta respuesta detallada .
Una manera fácil de hacer esto es averiguar el bloque en el que ocurrió la transacción. Sabiendo que realiza una llamada web3 a un nodo archivado completo. web3.eth.getBalance(address, block)
que restar 1 bloque y hacerlo de nuevo. Resta la diferencia y ahí está tu valor.
Creo que solo miras los registros de transacciones. Si hay una "transacción interna", esa transacción debe ser uno de los registros en el objeto de recibo de la transacción. Pero podría estar equivocado. @vitalikbuterin
Si conoce el bloque de la transacción, puede conocer el valor transferido:
let tx;
const txs = await web3.eth.getPastLogs({
fromBlock: block,
toBlock: block,
address: contractAddress
});
if(txs){
for(let i=0;i<txs.length;i++){
const tx_ = await web3.eth.getTransaction(txs[i].transactionHash);
if(tx_ && tx_.from === from){
tx = tx_;
break;
}
}
}
Para obtener el valor, llame a:tx.value
pablo s
pablo yabo
pablo s
tjaden hess
address.send()
oaddress.call()
en Soliditypablo yabo