Enable Contract Creation tracking

The Problem

Currently, the subgraph starting point must be a contract address (or many) which serve a lot of the use cases. But, what if you want dinamically index current and future contracts following a certain pattern/standard? That’s currently not possible.


If you could create a data source that can be triggered any time the node finds transaction creating a new contract you could attach a handler to it. Then it’s up to the developer what to do in the mapping code. It could test if it’s fits a specific standard and trigger a template creation for that address.

Solidity Docs

If the target account is not set (the transaction does not have a recipient or the recipient is set to null ), the transaction creates a new contract .

Note: I’m not too sure on how to identify contract creations from factory contracts yet. Will update if I find a way, but etherscan flags the internal transactions as Create so there should be a way.

Use Cases

  • Historical and current ERC20 balances
  • Public NFT Index
  • Any kind of dynamic aggregation based on grouping rules defined by developers

I’m currently working at SimpleFi and we would love to build the first 2 use-cases and I believe a lot of people would benefit from those subgraphs.

Speaking to one of my collegues (tarun), he found that it could be possible to identify contract creation calls using trace_transaction - Ethereum RPC method documentation - QuickNode

Hey @NelsonG! Interesting idea - you would like contractCreationHandlers?

The use cases you mention make sense - though I think the subgraphs that do those things at the moment instead rely on event signatures (without a source.address, so all matching events are returned). That has the downside that you can’t detect contracts before there are any transfers. I think there are some interesting edge cases for upgradeable contracts, where the “type” of the contract could actually change over time.

But Firehose support I think contractCreationHandlers would be easier than with the RPC interface (the trace API is not that performant), what do you think @abourget ? Could just pluck the trace out of the stream?

I’ve also stumbled upon this issue a few times in the past, usually it’s possible to find workarounds, but they are often not very nice at all (like having an initialization check on each handler so any handler will be able to properly initialize your entity, or at least on the first event triggered, if you know which of them will be the first beforehand).

It’d be greatly beneficial from a developer perspective, so that your code is more organized and elegant, but I don’t think it will enable new use cases that aren’t possible right now (although, being able to have your code a lot more organized is in an on itself a huge improvement!)

Thanks for the feedback @adamfuller & @juanmardefago!

Yes indeed @adamfuller something like contractCreationHandler (guess it will only be one as it’s generic).

First, I didn’t know I could skip the source address, that opens the possibility to do a lot more things and it’s quite interesting!

Secondly, the thing that comes to my mind (without any tests / PoCs ran yet) is that it will be a lot more expensive (or never fully sync at all) to track every single Transfer event in history rather than just Contract Creations + filtering the contracts that are actually useful for the specific use-case to track events.

I will run some tests later this week and see how it goes!

@juanmardefago we’ve already implemented those kind of workarounds for different solutions! (If you interested you can check our docs). But as I said above to Adam, my concern is more about sync time as we already have some subgraphs that have been syncing for 3 months and haven’t finished and some others where blocks are produced faster than what the subgraph can process, and we don’t really use contract-calls for our use-case (only ocasionally when a new token is discovered to get the name/symbol)

PS: wen firehose :cupid:?

1 Like

How would you expect to do this? Would you check interfaces / make contract calls?

Yes that was the plan! Some validation checks against the contract to see if it fits certain criteria to be included on a template to start tracking.

I could still do that same thing tracking generic Transfer events (now I know it’s possible), but that handler will be trigger way more times than a contract creation handler. I’m not sure if tracking every Transfer event will ever finish syncing (I will test though)

1 Like

@adamfuller as promised I deployed a PoC subgraph using no source and tracking the ERC20 Transfer event signature. Deployed a very small version tracking minimum data possible. Only balances.


As suspected is quite slow on mainnet because handler is being triggered massively. So it will be a lot slower on fast-blocks chains like Polygon, BSC, etc.

Question is, will this contract creation handler speed things up considerably?


Seems that it encountered an overflow:

"Mapping aborted at ~lib/@graphprotocol/graph-ts/index.ts, line 380, column 8, with message: overflow converting 0x143cca56f032e934e97f58d3634530ee9e415ba800 to i32\twasm backtrace:\t    0: 0x1841 - <unknown>!~lib/@graphprotocol/graph-ts/chain/ethereum/ethereum.Value#toI32\t    1: 0x194f - <unknown>!generated/ERC20Factory/ERC20/ERC20#try_decimals\t    2: 0x1982 - <unknown>!~lib/@graphprotocol/graph-ts/index/Value.fromBigInt\t    3: 0x1b64 - <unknown>!~lib/@graphprotocol/graph-ts/chain/ethereum/ethereum.Value#toAddress\t    4: 0x1e05 - <unknown>!~lib/internal/memory/memcmp\t in handler `handleTransfer` at block #4740054 (36090eaac6c441a2f41bfdb6bac67dccf9a647ecc94c2e8f49baac15a09a766c)"

I don’t think a contract creation handler would help with performance here, what is needed for this many events is parallel processing, which we are investigating currently with @abourget

1 Like

@adamfuller yeh I’m trying to debug it. There is a contract returning a weird decimals() that causes an overflow issue.

But I’ve deployed it on many chains so you can check the Optimism version which is fully sync.