1

I want to get addresses of all instances of Contract X deployed by Account Y. How can I do that?

I have to do it programmatically and fastest possible way.

  • Can't be done in a minute from chain. Are you planning to use an offline store like DB or Elastic Search ? You can query this from chain and keep updates on the offline store. With that, querying the store will take ~100 ms (to list all contacts created by a given address) – Shamit Verma Nov 28 '18 at 3:06
  • When you say "all instances of Contract X" what attribute are you using to distinguish Contract X from say Contract Y, besides address? – foba Nov 28 '18 at 14:07
  • @foba Contract name would do the job. – ferit Nov 28 '18 at 14:34
  • @ShamitVerma I have to do this somehow and looking for the best way of doing it. – ferit Nov 28 '18 at 14:36
3
+50

The address of an Ethereum contract is deterministic: How is the address of an Ethereum contract computed?

Knowing this, you can get the current nonce of an address, and programmatically generate and iterate through all the possible contract addresses which could be generated by that account.

Once you have a hypothetical list of possible addresses, you can call the Web3 getCode() function to get any contract code at those addresses.

This process is untested, but may deliver the results you are looking for. This should require no external dependencies other than a Web3 provider.

| improve this answer | |
  • Interesting. With this, in step 1, do I get all possible txs or only contract creation tx? If I could get only contract addresses that would be better. – ferit Nov 29 '18 at 8:04
  • 1
    It would be all possible contract addresses, some which will probably not exist. However, when you call getCode() on an address which does not exist, it will return 0, so it should be easy to distinguish. Furthermore, you can do these calls in parallel, so it should be fast. – Shawn Tabrizi Nov 29 '18 at 8:11
  • Great answer! Can I ask how will the introduction of the CREATE2 opcode (eips.ethereum.org/EIPS/eip-1014) with Constantinople affect the answer. Briefly, with the new opcode the created address will not be computed simply from address of the creator and nonce but rather by information like the address of the creator and the salt (which is not known in advance, if I understand correctly) I don't know if smart contracts will use this new opcode, but I am curious ^^ – Briomkez Dec 7 '18 at 16:22
  • 1
    This pattern would not work for contracts created with the new opcode, so this would only give a subset of possible contracts created rather than the full list for a given user. To be more thorough, you would need to look up the transaction history of the user block by block. – Shawn Tabrizi Dec 7 '18 at 16:45
0

Manually you can look up at http://etherscan.io it can match contracts by their bytecode. Automatically you have to write code probably using web3.js or other lib, to pull all the contracts deployed by account Y, then pull their bytecode and compare it to bytecode of contract X. All the instances which do match are instances of contract X.

| improve this answer | |
0

Here is a "fast" solution if you don't have an indexed blockchain, it can be improved but it's better this way you see all proper steps

1 Get access to a synced node.

2 Create a node project and install web3 dependency

3 Connect your web3 node

var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));

4 Get latest block

web3.eth.getBlockNumber()

5 Read all blocks in a for loop

web3.eth.getBlock(3150)
.then(console.log);

> {
    "number": 3,
    "hash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46",
    "parentHash": "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88",
    "nonce": "0xfb6e1a62d119228b",
    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "transactionsRoot": "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee",
    "stateRoot": "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb",
    "miner": "0x8888f1f195afa192cfee860698584c030f4c9db1",
    "difficulty": '21345678965432',
    "totalDifficulty": '324567845321',
    "size": 616,
    "extraData": "0x",
    "gasLimit": 3141592,
    "gasUsed": 21662,
    "timestamp": 1429287689,
    "transactions": [
        "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b"
    ],
    "uncles": []
}

6 Do a for loop inside checking all transactions and check their from value

web3.eth.getTransaction('0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b§234')
.then(console.log);

> {
    "hash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b",
    "nonce": 2,
    "blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46",
    "blockNumber": 3,
    "transactionIndex": 0,
    "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
    "to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
    "value": '123450000000000000',
    "gas": 314159,
    "gasPrice": '2000000000000',
    "input": "0x57cb2fc4"
}

7 Put it all together

| improve this answer | |
0

IDEA

One way to do so, is to automatize the (manual) solution proposed by Igor, by exploiting etherscan.io API. In particular, by using module=account, address=<your-address> and action=txlistinternal if your address is a contract or action=txlist if the account is an externally owned account that triggers external transactions.

Once you obtain the list of transactions of your account here is an example of the json output, then you can get all contract creation transactions by selecting all transactions that have as sender your address, and have an empty receiver. If the input of this transaction correspond to the constructor of your account, then you can collect the "contractAddress" fields, that is the address of the newly created account.

MINIMAL EXAMPLE

Minimal example in python.

import requests
import json

# address of the original contract we want to track
# internal boolean value that determine if we want internal txs or normal ones
def create_url(address, internal):
    action = "txlistinternal" if internal else "txlist"
    return "https://api.etherscan.io/api?module=account&action=" + action + "&address=" + address + "&tag=latest"

address = "0x20d42f2e99a421147acf198d775395cac2e8b03d"
response = ""

# Possibly treat connection error or other exception that may raise
response = requests.get(create_url(address, True))

# Extract the json. Check for ValueErrors or other exceptions
json_resp = json.loads(response.text)

# If return message is not "OK". Exit ...
if json_resp["message"] != "OK":
    print("Something went wrong. Decide what to do")
    exit(1)

# Use list comprehension to get all contracts originated from the original address
originatedContracts = [i["contractAddress"] for i in json_resp["result"] if i["from"] == address and i["to"] == '']

print(originatedContracts)

Some additional notes:

  1. to perform more requests use an API token
  2. Maybe not all blocks are included in the search. To specify a range check the documentation!
  3. For externally owned accounts you have to set False in the txlist and for the contracts you have to set True. If you don't know it in advance, you have to get both responses for internal and external transactions.
  4. To improve the readability I removed the exceptions handling

N.B.

I know that etherscan has a limited number of API request, maybe you can get in touch with them to try to augment your quote.

SPEEDUP

If you know in advance the "original addresses" then you can cache the results (each day, for instance) to get immediate results for end-users. You can modify the example to create a dictionary in which the key is the original address and the values are the originated contracts and cache it in a file or in your database.

| improve this answer | |
  • "here is an example of the json output" link broken. – ferit Nov 23 '18 at 10:22
  • Sorry, here at this page you can find the examples I am referring to etherscan.io/apis#accounts in particular Get a list of 'Normal' Transactions By Address and Get a list of 'Internal' Transactions by Address. By clicking the links you will get a JSON output. (Note: To use the API you need an Etherscan Token). – Briomkez Nov 23 '18 at 10:27
  • I am expecting a working example from this bounty, actually. – ferit Nov 23 '18 at 10:54
  • 1
    Stack overflow is not about coding for points, its about helping each other, if you want someone to code a solution for you that just works, I don't think this is the right place – Enrique Alcazar Nov 23 '18 at 14:47
  • There is a difference between a working example and a solution. – ferit Nov 23 '18 at 20:25
0

You will have to scan all historical blocks and listen for future blocks to extract transactions. For each transaction; you can trace the transaction to find out all contracts created by the transaction.

This answer has steps to do that :

How to implement a watching wallet for thousands/millions of addresses

| improve this answer | |
0

I like using amberdata.io since it's not rate limited.

Grab an api key.

Run:

export API_KEY=<your_api_key>

Then run:

export ADDRESS_Y=0x521db06bf657ed1d6c98553a70319a8ddbac75a3

Note: I use that address as an example since it deployed so many contracts its a nice one to test with.

Then run:

curl \
-X GET \
-H "accept: application/json" \
-H "x-api-key: $API_KEY" \
"https://web3api.io/api/v1/addresses/$ADDRESS_Y/transactions?to=null"
| improve this answer | |

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.