1

I am trying to update the state of a variable in the smart contract using python web3 library, when I call the function using the transact method, this error appears

ValueError: {'code': -32000, 'message': 'unknown account'}

And the account I am using actually exists in my geth blockchain

Here is my python code

from time import sleep
from web3 import Web3
from web3.middleware import geth_poa_middleware

web3 = Web3(Web3.HTTPProvider(r"http://127.0.0.1:8545"))

web3.middleware_onion.inject(geth_poa_middleware, layer=0)

print(web3.is_connected())

print(web3.from_wei(web3.eth.get_balance(web3.eth.accounts[0]), "ether"))

usersContract = web3.eth.contract(address="0x1fCD05eE0DE1D332375e236cE479F8E80627ca1E", abi='[{"inputs":[{"internalType":"address","name":"adr","type":"address"},{"internalType":"string","name":"userName","type":"string"}],"name":"addUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint16","name":"reputation","type":"uint16"}],"name":"updateUserReputation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"getUserNameOfAddress","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserReputation","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"}]');

i = 0


while True:
    usersContract.functions.updateUserReputation(userAddress=web3.to_checksum_address("0xeBc8Db75a4E5EFa2d86dfB44C305A0A18E34a434"), reputation=i).transact()
    i += 1
    result = usersContract.functions.getUserReputation(web3.to_checksum_address("0xeBc8Db75a4E5EFa2d86dfB44C305A0A18E34a434")).call()
    print(result)
    sleep(1)

And my solidity code

contract ExampleUsers {
    
    mapping(address => User) users;

    function addUser(address adr, string memory userName) public {
        users[adr] = new User(adr, userName);
    }

    function getUserNameOfAddress(address adr) public view returns (string memory) {
        return users[adr].getUserName();
    }

    function getUserReputation(address userAddress) public view returns (uint16) {
        return users[userAddress].getUserReputation();
    }

    function updateUserReputation(address userAddress, uint16 reputation) public {
        users[userAddress].setUserReputation(reputation);
    }

    function updateUserName(address userAddress, string memory newName) public {
        users[userAddress].setUserName(newName);
    }

}

user contract

contract User {
    
    address userAddress;
    uint16 userReputation;
    string userName;

    constructor(address adr, string memory name) {
        userAddress = adr;
        userName = name;
        userReputation = 0;
    }

    function getUserAddress() public view returns (address) {
        return userAddress;
    }

    function getUserReputation() public view returns (uint16) {
        return userReputation;
    }

    function setUserReputation(uint16 reputation) public {
        userReputation = reputation;
    }

    function getUserName() public view returns(string memory) {
        return userName;
    }

    function setUserName(string memory name) public {
        userName = name;
    }

}

1 Answer 1

1

Found the solution,

I needed to create a transaction and sign it using my private key, when I did that, everything worked fine

NB: send a transaction only when calling a function that will change the state of your smart contract variables, if not, the function call can be used instead of buildTransaction

Here is my solution

from web3 import Web3
from web3.middleware import geth_poa_middleware

web3 = Web3(Web3.HTTPProvider(r"http://127.0.0.1:8545"))

web3.middleware_onion.inject(geth_poa_middleware, layer=0)

# get your smart contract instance

usersContract = web3.eth.contract(address=your_smart_contract_address_here, abi=your_smart_contract_abi_here);

# your checksum address

my_account_checksum_address = web3.to_checksum_address(your_account_address_here)

nonce = web3.eth.get_transaction_count(my_account_checksum_address)
tx = {
'nonce': nonce,
'value': 0,
'gas': 2000000,
'gasPrice': web3.to_wei('50', 'gwei'),
"from": your_account_address_here
}

# create a transaction that will update the state of your contract variables based on the function you called

transaction = usersContract.functions.updateUserReputation(userAddress=my_account_checksum_address, reputation=i).build_transaction(tx)


# sign the transaction with your private key

signed_transaction = web3.eth.account.sign_transaction(transaction, private_key=your_account_private_key_here)

# send the transaction

send_tx = web3.eth.send_raw_transaction(signed_transaction.rawTransaction)

# wait for the transaction to be added to the blockchain


tx_receipt = web3.eth.wait_for_transaction_receipt(send_tx)

two useful links:

Execute a contract function from web3.py

https://cryptomarketpool.com/send-a-transaction-to-the-ethereum-blockchain-using-python-and-web3-py/

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.