0

I'm trying to sign locally a transaction to a smart contract method using web3.py. I'm using ganache and there is one interesting issue when I send a transaction as the contract deployer everything is OK. Whenever I call the contract from a different address I get a message "the tx doesn't have the correct nonce. account has nonce of: 11 tx has nonce of: 0" and a RPC error is thrown.

It's my code:

from web3 import Web3

import json
import asyncio


class Client:
    def __init__(self, provider, contract_address, private_key):
       self.web3 = Web3(Web3.HTTPProvider(provider))
       with open("abi.json") as abi_file:
           abi = json.load(abi_file)
       self.contract_instance = self.web3.eth.contract(
           address=contract_address, abi=abi)
       self.account = self.web3.eth.account.privateKeyToAccount(private_key)

    async def asset_emit(self, to_address, meta):
       raw_tx = self.contract_instance.functions.assign(to_address, meta).buildTransaction({
        'nonce': self.web3.eth.getTransactionCount(self.account._address)
    })

       signed_tx = self.web3.eth.account.signTransaction(
        raw_tx, private_key=self.account._privateKey)

       sent_tx = self.web3.eth.sendRawTransaction(signed_tx.rawTransaction)

       return Web3.toHex(sent_tx)


provider = "http://localhost:7545"
contract_address = "0x1a6bBC4F4759053A3EAc90ECF2b8458c26C6420f"
private_keys = [
"0a62d720053110c9ece23ca0b1aef887dd8107e246e8ed646cadd8f86c5cff72",
"4867ce02e3d309962375b368065623f9ff33adbf50b754f15f9f0dab3b5311b8",
"0dc0af03cf395fe7d617ca4c2951d4240c4fdcc67cf78b3e0a5e666662b543b6",
"5cf0c6d817044434fc94ca40a2f8434658195575d19d0732034edbc4e63709b6",
"75093f0ec4bdc9e4b442bfd19a0550c939de81d287bcedeca46e6048b19b983d",
"0fd5c5c6e2b641741c59952b78cb7b979a7564c1c7926cc6fbc77d96f5c3a38e"
]


async def test():
for i in range(0, len(private_keys)):
    try:
        client = Client(provider, contract_address, private_keys[i])
        await gts_sdk.asset_emit(
            "0x91F64E8D876690b617B252445790B5e3fCc9322D", "0x10")
        print(True)
    except:
        print(False)
await client.asset_emit(
    "0x91F64E8D876690b617B252445790B5e3fCc9322D", "0x10")


event_loop = asyncio.get_event_loop()

tasks = [
asyncio.ensure_future(test())
]

event_loop.run_until_complete(asyncio.wait(tasks))
event_loop.close()

Thanks for help

2

I found the problem I did not define 'from' property in the raw_tx dictionary object so web3 was substituting it with accounts[0] it means the address which deployed the contract. it's how the object should look like:

raw_tx = self.contract_instance.functions.assign(to_address, meta).buildTransaction({
        'from': self.account._address,
        'nonce': self.web3.eth.getTransactionCount(self.account._address)
    })
  • Mate, if that work I will love you – btc4cash Feb 4 '19 at 6:45

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.