2

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.

3

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.

  • 1
    The public mapping is named balances and there is also a function explicitly declared with the same name balances which also takes an address as the only argument. However, the explicitly declared function has a different return type, i.e. (uint, string). Perhaps, this could cause a problem. – Ajoy Bhatia Jan 22 '18 at 23:21
  • Well the part when i return (uint, string) is the part that causes the problem. For example if i modify it to (uint) and i modify the functio to return an uint everything goes okay. Otherwise, the same code using parity works fine. – Chiheb Nexus Jan 23 '18 at 1:07
  • Also did the mapping balances and the function balances can throw thses errors? Should the variable names and functions have a unique names? – Chiheb Nexus Jan 23 '18 at 1:09
  • 1
    Thanks to @AjoyBhatia for pointing that out. I'm frankly a bit surprised it compiles this way. Notice that if you switch the visibility on balances (the variable) to private, that it will not compile. Definitely pick a different name for public variables and public functions. Try that and report back. – carver Jan 23 '18 at 1:30
  • @carver did your ran the python code in the question ? did you get a valid response ? – Chiheb Nexus Jan 23 '18 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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