Web3.py – Error When Interacting with Ethereum Smart Contract Using Web3.py

go-ethereumparitypythonsolidityweb3.py

I'm using web3.py to interact with an Ethereum Smart Contract which is:

pragma solidity ^0.4.0;

contract Coin {
    address public minter;
    string public name;
    mapping (address => uint) public balances;

    event Sent(address from, address to, uint amount);

    function Coin() public {
        minter = msg.sender;
        name = 'MyCoin';
    }

    // Create new Tokens
    function mint(address _reciever, uint _amount) public {
        if (msg.sender != minter) return;
        balances[_reciever] += _amount;
    }

    // Send tokens
    function send(address _reciever, uint _amount) public {
        if (balances[msg.sender] < _amount) return;
        balances[msg.sender] -= _amount;
        balances[_reciever] += _amount;
        Sent(msg.sender, _reciever, _amount);
    }

    function getBalance(address _user) public view returns (uint){
        return balances[_user];
    }

    function balances(address _account) public view returns (uint, string) {
        return (balances[_account], name);
    }
}

Compiling, deploying and generating ABI and contract address were successful. Hower, when i try to access to the deployed smart contract using web3.py i got a strange exception when i call the function balances() in the smart contract.

eth_abi.exceptions.InsufficientDataBytes: Tried to read 32 bytes.  Only got 0 bytes

I used geth with a custom genesis block and parity chain dev node, but without any success.

Here is my Python code:

import json
from web3 import Web3, RPCProvider
from web3.contract import ConciseContract
import time

RPC_IP = '127.0.0.1'
RPC_PORT = '8545'

# read the contract informations then convert them into a Python dict
with open('contract_informations.json', 'r') as f:
    data = json.loads(f.read())

ABI = data.get('abi')
CONTARCT_ADDRESS = data.get('contract_address')

w3 = Web3(RPCProvider(RPC_IP, RPC_PORT))

contract_instance = w3.eth.contract(ABI, CONTARCT_ADDRESS, ContractFactoryClass=ConciseContract)

contract_instance.mint('0x00a329c0648769A73afAc7F9381E08FB43dBEA72', 1000, transact={'from': w3.eth.accounts[0]})


print(contract_instance.getBalance('0x00a329c0648769A73afAc7F9381E08FB43dBEA72'))

When i run the Python code there is two exceptions:

web3.exceptions.BadFunctionCallOutput: Could not transact with/call contract function, is contract deployed correctly and chain synced?

and

eth_abi.exceptions.InsufficientDataBytes: Tried to read 32 bytes.  Only got 0 bytes

However, when i deploy the contract using Parity web interface, everything works fine.

Did, web3.py has some limitations or did i miss something ?

Thanks for your answers.

Best Answer

Compiling, deploying and generating ABI and contract address were successful.

How do you know deployment was successful? Can you add the code where you wait for the transaction to complete and then you retrieve the contract address?

For what it's worth, a typical compiler would turn your public mapping into a function in the ABI that is exactly equivalent to the getBalance that you wrote. So you could also call contract_instance.balances('0x00a329c0648769A73afAc7F9381E08FB43dBEA72').

However, when i deploy the contract using Parity web interface, everything works fine.

This strongly indicates that something is going wrong during your deployment that you haven't identified. Right now, there is not enough information in the question to debug the deployment.