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.
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.
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.
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 08:11
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 07 '18 at 16:22Manually 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.
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 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:
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.
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.
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
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"
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