Etherscan/Polygonscan API Solution:
I did finally find the proper endpoint for these requests. You can batch a max of 5 contracts per request. The etherscan API seems more reliable than JSON RPC method mentioned below. Additionally the etherscan API is much faster. Use npm lib node-fetch
if in a node-js context. Solution also works with polygonscan:
// You can get an API key on the free-tier of etherscan/polygonscan
const APIKEY="YourApiKey"
async function getContractCreators(
// Array of contract-address strings (Maximum 5 per API call)
contracts
){
const url = `https://api.etherscan.io/api?module=contract&action=getcontractcreation&apiKey=${APIKEY}&contractaddresses=${contracts.toString()}`;
const req = await fetch(url);
const res = await req.json()
// Make sure req was success
if(res.status!='1'){
console.warn("Handle req error here",res)
return []
}
res.result.forEach(c => {
let contract = c.contractAddress; // contract-address
let creator = c. contractCreator; // creator-wallet-address
console.log("🔎 Found Creator"
console.log(" -> contract :" + contract);
console.log(" -> creator :" + creator)
})
return res.result
}
getContractCreators(["0xB83c27805aAcA5C7082eB45C868d955Cf04C337F","0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45","0xe4462eb568E2DFbb5b0cA2D3DbB1A35C9Aa98aad","0xdAC17F958D2ee523a2206206994597C13D831ec7","0xf5b969064b91869fBF676ecAbcCd1c5563F591d0"]);
Old Solution With EVM JSON RPC:
See this answer https://ethereum.stackexchange.com/a/65210/125787
The code looks like this and it may not work if the creator of the contract was another contract and not a wallet.
import Web3 from "web3";
// Here we use alchemy but you can use others http or websocket
const web3 = new Web3("https://eth-mainnet.alchemyapi.io/v2/<YourAPIKey>")
async function search_contract_cretion_block(contract_address) {
var highest_block = await web3.eth.getBlockNumber();
var lowest_block = 0;
var contract_code = await web3.eth.getCode(contract_address, highest_block);
if (contract_code == "0x") {
console.error("Contract " + contract_address + " does not exist!");
return -1;
}
while (lowest_block <= highest_block) {
let search_block = parseInt((lowest_block + highest_block) / 2)
contract_code = await web3.eth.getCode(contract_address, search_block);
//console.log(highest_block, lowest_block, search_block, contract_code);
if (contract_code != "0x") {
highest_block = search_block;
} else if (contract_code == "0x") {
lowest_block = search_block;
}
if (highest_block == lowest_block + 1) {
return highest_block;
}
}
}
async function search_contract_creator (contract_address, block) {
var block = await web3.eth.getBlock(block);
var transactions = block.transactions;
for (let transaction in transactions) {
let receipt = await web3.eth.getTransactionReceipt(transactions[transaction]);
if (receipt.contractAddress?.toLowerCase() == contract_address.toLowerCase()) {
return receipt.from
}
}
return -1;
}
async function find_contract_creator (contract_address) {
var block = await search_contract_cretion_block(contract_address);
var creator = await search_contract_creator(contract_address, block);
console.log(creator)
return creator;
}
find_contract_creator("0x40e85735ff7c7230177589b4e52295b899ccc23e");