0

I was wonder if it's possible to call a smart contract function based on a parameter sent to my function caller. From some research I did, i was able to find a function called getattr(). I was thinking that function coupled with the JSON abi file, i could do something. I would usually try to find the answer myself, but i dont even know where to begin. Thanks in advance.

Caller.py

#!/usr/bin/python3
import sys
import json
from web3 import Web3
import deployer

def caller(function):

    # Open up ABI for calling functions
    with open("deployed_abi.json") as file:
        abi = json.load(file)

    # Connect to Ethereum
    w3_caller = Web3(Web3.HTTPProvider(sys.argv[1]))
    print("Connection: " + str(w3_caller.isConnected()))

    # Call functions based on "function" parameter

    
if __name__ == "__main__":
    caller(sys.argv[1])

deployer.py

#!/usr/bin/python3
import sys
import json
from web3 import Web3
from solcx import compile_standard, install_solc

solc_version = '0.6.0'
install_solc(solc_version)

# Get Solcx Version from an enviorment variable.
def config():
    solc_version = input("Solc Version (Default - 0.6.0): ")
    install_solc(solc_version)

def deploy(node_address, solfile, eth_address):
    # Connect and Set address.
    print("Deploying ...")
    w3_deploy = Web3(Web3.HTTPProvider(node_address))
    print("Connection: " + str(w3_deploy.isConnected()))
    w3_deploy.eth.default_account = eth_address

    # Open Sol File and Compile
    with open(solfile, "r") as file:
        contract_file = file.read()
    compiled_contract = compile_standard(
        {
            "language": "Solidity",
            "sources": {solfile: {"content": contract_file}},
            "settings": {
                "outputSelection": {
                    "*": {"*": ["abi", "metadata", "evm.bytecode", "evm.sourceMap"]}
                }
            },
        },
        solc_version=solc_version,
    )
    with open("compiled_camel_coin.json", "w") as file:
        json.dump(compiled_contract, file)

    deployed_bytecode = compiled_contract["contracts"]["camelcoin.sol"]["camelcoin"]["evm"][
        "bytecode"
    ]["object"]
    deployed_abi = compiled_contract["contracts"]["camelcoin.sol"]["camelcoin"]["abi"]

    with open("deployed_abi.json", "w") as file:
        json.dump(deployed_abi, file)

    deploy_contract = w3_deploy.eth.contract(abi=deployed_abi, bytecode=deployed_bytecode)
    dep_hash = deploy_contract.constructor().transact()
    dep_receipt = w3_deploy.eth.wait_for_transaction_receipt(dep_hash)
    contract_addr = w3_deploy.eth.getTransactionReceipt(dep_hash).contractAddress
    print("Deployed at adress: " + str(contract_addr))

# Check arguments
if len(sys.argv) != 4:
    print("Improper Arguments: <node_address:port> <Solidity File> <Ethereum Address(0x prefix needed)>")
    exit()

if __name__ == "__main__":
    deploy(str(sys.argv[1]), str(sys.argv[2]), str(sys.argv[3]))
pragma solidity <= 0.9.0;

contract camelcoin {
    address public founder;
    uint256 public totalsupply;
    struct Shareholder {
        uint account_index;
        uint balance;
        uint escrow;
        uint stake;
    }
    mapping(address => Shareholder) public shareholders;

    constructor() public {
        founder = msg.sender;
    }

    function fetchFounder() public view returns(address){
        return founder;
    }

    function fetchTotalSupply() public view returns(uint){
        return totalsupply;
    }
1

1 Answer 1

6

Yes you can call functions based on parameters that you want in web3.py and is very simple.

  • Connect to a node provider (I recommend Chainstack.com as they provide nodes for many networks and supports all of the methods that other providers usually don't)
from web3 import Web3
import json

node_url = 'CHAINSTACK NODE URL'
web3 = Web3(Web3.HTTPProvider(node_url))
  • then create a contract instance, basically a Python object that you can use. You need the contract address and the ABI.
abi = json.loads('ABI JSON CODE HERE')
address = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'
   
contract = web3.eth.contract(address = address , abi = abi)

now you can call any function from that contract! Keep in mind that the .call method is used for functions that do not change any state, so functions such as name, symbol, balanceOf etc.

token_name = contract.functions.name().call() 
token_symbol = contract.functions.symbol().call()
balance = contract.functions.balanceOf(Web3.toChecksumAddress('ADDRESS')).call()

print('Name:', token_name)
print('Symbol:', token_symbol)
print('Balance:', web3.fromWei(balance, 'ether'))

At this point you can use regular Python logic to call the functions when certain conditions are met!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.