How to call a Smart Contract function using Python and web3.py
Asked Answered
C

2

9

I have a contract deployed on Ethereum test network which has some functions in it and they all happen to work while using the Remix interface. When trying to call those functions using web3.py in Python, I'm able to call only for public functions and that part works fine. The problem is calling a function with a "restriction" such as having an "owner requirement", meaning only the address which created the contract can call that specific function. I've Googled it but no luck. I'm guessing that I am supposed to use both the "address" and the "password" for that Ethereum account as parameters when calling the function but I have no idea how to do it. Function is called "set()" and it takes only 2 string values.

Here is the part of Solidity code which makes the function "set()" accessible only by the owner of this contract.

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

modifier onlyOwner() {
    require(msg.sender == owner);
    _;
}

function set(string memory _lastHash,
             string memory _fullHash) public onlyOwner {
    lastHash = _lastHash;
    fullHash = _fullHash;
}

Here is the python function which i'm using to get the return values from the other 2 functions which i've not included:

data = contract.functions.getFullHash().call()

Function is called "getFullHash()". Given Python code doesn't work with the function "set()".

Canonical answered 20/8, 2019 at 19:53 Comment(2)
to set values you have to call function as contract.functions.set(arg1, arg2).transact().Vanegas
That didn't work for me, what worked was the following: signed_txn = web3.eth.account.signTransaction(transaction, private_key=private_key). And transaction needs to look like this: transaction = contract.functions.set( 'string1', 'string2' ).buildTransaction({ 'gas': 70000, 'gasPrice': web3.toWei('1', 'gwei'), 'from': adress, 'nonce': nonce })Canonical
C
13

Since my original comment got deleted I'll post it one last time.

I've managed to do it with the instructions provided on this link. Here is the code that worked for me:

transaction = contract.functions.set(
    'string1',
    'string2' ).buildTransaction({
    'gas': 70000,
    'gasPrice': web3.toWei('1', 'gwei'),
    'from': adress,
    'nonce': nonce
    }) 
private_key = "enter_your_key_here" 
signed_txn = web3.eth.account.signTransaction(transaction, private_key=private_key)
web3.eth.sendRawTransaction(signed_txn.rawTransaction)

I read somewhere that Infura only accepts raw signed transactions, not sure if its true but it worked this way.

Canonical answered 21/8, 2019 at 8:48 Comment(2)
sendRawTransaction return Hash, but there is not any transaction . getTransaction with that hash show this {'blockHash': None, 'blockNumber': None, 'from': '0xA6f8021540Ec3609696e22f170144e47c8c88127', 'gas': 118685, 'gasPrice': 1000000000, ..., 'to': 'My address', 'transactionIndex': None, 'v': 42, 'value': 0}Magi
You need to set "gasPrice" to like 160 gwei currently if you operate on the mainnet.Clancy
D
1

Moltenpowa answered correctly. However, I had problems defining nonce. Here are full solution for this:

CHAIN_ID = 97  # Testnet
GAS_AMOUNT = 65000
GAS_PRICE = 10  # gwei
SC_ADDRESS = '0x....'
SC_OWNER_ADDR = '0x...'
SC_OWNER_ADDR_PRIV_KEY_FILE_PATH = '/opt/.priv_key.txt'

def change_contract_state(wallet):
    nonce = w3.eth.getTransactionCount(SC_OWNER_ADDR)
    private_key = read_private_key_from_file(SC_OWNER_ADDR_PRIV_KEY_FILE_PATH)
    nonce = w3.eth.getTransactionCount(SC_OWNER_ADDR)
    private_key = read_private_key_from_file(SC_OWNER_ADDR_PRIV_KEY_FILE_PATH)
    transaction = contract.functions.updateWinner(wallet).buildTransaction({
        'chainId': CHAIN_ID,
        'gas': GAS_AMOUNT,
        'gasPrice': Web3.toWei(GAS_PRICE, 'gwei'),
        'from': SC_OWNER_ADDR,
        'nonce': nonce
    })
    # print(transaction)
    signed_txn = w3.eth.account.signTransaction(transaction, private_key=private_key)
    tx_hash = w3.toHex(w3.keccak(signed_txn.rawTransaction))
    print(tx_hash)
Dorena answered 19/6, 2021 at 8:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.