44

I'd like to get the contract internal transactions like: https://etherscan.io/address/0xd654bdd32fc99471455e86c2e7f7d7b6437e9179#internaltx

I'm using web3 API. Is there any way to do it? Where do they appear in the blockchain?

  • 1
    hopefully the answer will explain what an internal transaction is – Paul S Apr 27 '16 at 18:47
  • They are the transactions triggered by the contracts. – Pablo Yabo Apr 27 '16 at 19:20
  • sure, but still not sure what it means. I don't recall a solidity keyword for this. link? – Paul S Apr 27 '16 at 19:47
  • 3
    @PaulS It's any transaction sent via the address.send() or address.call() functions in Solidity – Tjaden Hess Apr 27 '16 at 23:19
  • No, there are other ways to 'send' ether like suicide() or when you create a new contract – Pablo Yabo Apr 17 '17 at 22:03
45

There's not currently any way to do this using the web3 API. Internal transactions, despite the name (which isn't part of the yellowpaper; it's a convention people have settled on) aren't actual transactions, and aren't included directly in the blockchain; they're value transfers that were initiated by executing a contract.

As such, they're not stored explicitly anywhere: they're the effects of running the transaction in question on the blockchain state. Blockchain explorers like etherscan obtain them by running a modified node with an instrumented EVM, which record all the value transfers that took place as part of transaction execution, storing them separately.

  • 2
    Got it! Do you know if there is a plan to add a sort of mechanism to get these transactions or I must create an instrumented EVM. – Pablo Yabo Apr 28 '16 at 19:31
  • 1
    I'm not aware of ongoing work to add an API like this, though there could be; if your goal is to get internal transfers for a given transaction, that'd be practical. If your goal is to get all transfers into an account, though, this isn't sufficient - and there's a bug for that. – Nick Johnson Apr 28 '16 at 19:59
  • 1
    I already have the tx list for non contract transactions but I'd like to add the 'internal transactions' to the transaction list. Do you think that an instrumented EVM could work for that? – Pablo Yabo Apr 28 '16 at 20:37
  • 1
    @PabloYabo It would, but if what you care about is "all transactions to this account", you have to run every single transaction through it, in case it produced a transfer to the account you care about. If you care about "all value transfers initiated by this transaction", then you can run it just on that transaction. – Nick Johnson Apr 29 '16 at 8:52
  • 1
    @PabloYabo In that case, such a hypothetical API would probably serve your purposes - but in the meantime, you'll have to instrument the EVM yourself. – Nick Johnson Apr 29 '16 at 13:16
21

In the Ethereum protocol there's only transactions and message calls. A transaction is a type of message call.

A transaction may perform other message calls, but these are not transactions (even though blockchain explorers may label them inaccurately as "internal transactions"). These (internal) message calls are not published on the blockchain. To find the internal calls, the transaction needs to be processed through the EVM (for example, https://github.com/ethereumjs/ethereumjs-vm).

To try illustrating, a transaction in Javascript looks like:

{
  from: ...,
  to: "C1",
  value: ...,
  gas: ...,
  data: ...,
  gasPrice: ...,
  nonce: ...
}

This is what you will see on the blockchain. Internal calls are the effects of taking the data part, feeding it to the contract C1, and executing the Ethereum Virtual Machine. The data is what tells C1 that it should call another contract C2: there is no separate {from:C1, to:C2,...} object on the blockchain that's needed.

The data is encoded according to an ABI that says things like which function should be called and what the arguments are.

Note: With @Nick's answer, all value transfers are a message call. But not all message calls are value transfers. A value transfer is when a contract is simply paid some Ether/wei (data is zero), but contracts can call each other without paying each other (data is non-zero, value is zero).

  • Is it possible to get all those logs? – Pablo Yabo Jun 23 '16 at 20:16
  • 2
    Yes, executing the EVM includes all LOG opcodes. – eth Jun 23 '16 at 20:31
14

Fortunately, Geth EVM has new tools to get this done. It's possible to use debug_traceTransaction with RPC API.

In NodeJS:

var web3 = require('web3').web3;
web3.currentProvider.sendAsync({
    method: "debug_traceTransaction",
    params: ['0x3fac854179691e377fc1aa180b71a4033b6bb3bde2a7ef00bc8e78f849ad356e', {}],
    jsonrpc: "2.0",
    id: "2"
}, function (err, result) {
    ...
});

Then, you'll need to'CREATE', 'CALL', 'CALLCODE' and 'DELEGATECALL' opcodes and keep track of the stack. You can read Nick Johnson detailed explanation: Instrumenting EVM

If I finally implement it I'll write a full article with the code.

  • The problem here is that any contract can call into the contract you're interested in at any time--if you want every internal transaction sent to your contract, the only way to do that is to search the traces of every transaction that happened since your contract was deployed. One semi-shortcut is to filter events, but this ignores 'internal transactions' that do not generate events. I posted some code here in C++ a couple of days ago: github.com/Great-Hill-Corporation/ethrpc – Thomas Jay Rush Oct 21 '16 at 20:58
  • Yes, I know, it was just an example. Then, you'll need to do the same for each transaction. My idea is to index everything and then put the information in a database. – Pablo Yabo Oct 22 '16 at 0:05
  • I'm working on the same exact idea. Index everything and put it in a database. The trouble I see with this is that this centralizes that data. If I create that data, how I you know I didn't fake it? I've been trying to figure out a way to both index it and decentralize the 'indexing calculation.' I know how to decentralize the storage (IPFS), but not how to decentralize the indexing calculation. Do you have any thoughts on that? Do you have a github I can check out? A very rough start of mine is at github.com/Great-Hill-Corporation/ethrpc. Maybe Golem allows to decentralize the calc. – Thomas Jay Rush Oct 26 '16 at 15:47
  • Why there is web3.web3 instead of only using web3. ? – alper Dec 19 '16 at 10:00
3

You can use callTracer introduced in 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"}]}

The API will stream back one IPC notification per non-empty block. An exception is the very last block, which will be reported even if empty so the user knows the stream is done.

{"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"}}}

Individual block tracing is concurrent in the transactions (limited to num cores) and also makes chain tracing concurrent in the blocks (limited to num cores).

3

According to Parity's 1.1 version announcement, you could do it with it if you switch to this client. Quoting:

New JSONRPC APIs for tracking, tracing and inspecting all message-calls and balance transfers, including those that happen as "internal transactions";

Haven't tested it yet though.

2

For get information about internal transactions, you can use the debug_traceTransaction The method will return a full trace of the transaction. By the opcodes and parameters of each step, you can get the information you need.

There are 2 main problems: 1. Identify the working principle of the opcodes, because for example, not always CALL results in an internal transaction 2. With a large number of steps in the trace, the response may not fit in the buffer

The second problem can be solved by passing the second parameter to the methods for processing the steps on the geth side. More details can be found here - https://github.com/ethereum/go-ethereum/wiki/Management-APIs#debug_tracetransaction

The logic of how to handle opcodes can be found here https://github.com/Arachnid/etherquery/blob/master/etherquery/trace.go#L102 (for go implementation) or here https://github.com/tet32/etherscanner/blob/master/traceStepFunction.js (for nodejs implementation)

2

With recent versions of Parity (tested on 1.8.3) it is also possible. The RPC method is trace_replayTransaction. The corresponding code is something like

web3.currentProvider.sendAsync({
    method: "trace_replayTransaction",
    params: [desiredTransactionHash, ['trace']],
    jsonrpc: "2.0",
    id: "1"
}, function (err, out) {
    console.log(out);
}

Documentation is at the parity github repository.

0

Easy way to do this is to figure out the block the transaction happened. Knowing that you make a web3 call to a full archived node.web3.eth.getBalance(address, block) than subtract 1 block and do it again. Subtract the difference and there is your value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.