I have a contract that creates other contracts. It then pushes these contracts in an array, address[] public newContracts. The only problem is I'm having trouble calling them from python.
factory.json is my abi and the address and web3 seem to connect fine, just can't call the variables correctly.
Thanks for any help
from web3 import Web3
import json
from web3.providers.rpc import HTTPProvider
contractAddress = '0x3c7bec02bd4fa73dce24413d2a13c02e1a91e858'
web3 = Web3(HTTPProvider('https://ropsten.infura.io'))
with open('factory.json', 'r') as abi_definition:
abi = json.load(abi_definition)
print (web3.eth.blockNumber)
fContract = web3.eth.contract(abi,contractAddress)
print ('Creator',fContract.call().creator)
print ('Contracts',fContract.call().newContracts)
print ('OracleName',fContract.call().oracleName)
Best Answer
Two Issues
Retrieving the creator value
Use
fContract.call().creator()
here.Creating the contract
Use
web3.eth.contract(contractAddress, abi=abi)
here.Why?
Any time you access data in a contract from outside the EVM, you access it using a function. This is true even when you are accessing a public variable. Take a look at the ABI, which sets
{"type":"function"}
on your public variable.The arguments
(abi, contractAddress)
will work in Web3.py v3, but break in v4. The reversed order andabi
as a keyword argument will work in both v3 and v4, so it's best to always use the newer syntax:(contractAddress, abi=abi)
See the API docs for more.Where can I read more?
Here are some lightly edited examples from the web3.py Contract call docs, using the newest Web3.py v4 syntax:
The docs also discuss a slightly more succinct access, with a bit more setup. An example for your contract looks like: