Recupere el valor devuelto por una función que se invocó con 'transact'

Estoy usando Python web3para implementar y probar un contrato de Solidity.

Estos son mis pasos iniciales:

from web3 import Web3
from web3 import RPCProvider
from json import loads

eth = Web3(RPCProvider()).eth
abi = open(ABI_FILE_NAME).read()
bin = open(BIN_FILE_NAME).read()
transaction = {'from':eth.accounts[0]}

contract = eth.contract(abi=loads(abi),bytecode=bin)
tx_hash  = contract.deploy(transaction=transaction)
address  = eth.getTransactionReceipt(tx_hash)['contractAddress']
handle   = contract(address).transact(transaction)

En este punto, invoco una función en el contrato:

tx_hash = handle.some_func()

Y esto es lo que me sale cuando llamo eth.getTransactionReceipt(tx_hash):

{
    'transactionHash'   : '0x...',
    'transactionIndex'  : 0,
    'blockHash'         : '0x...',
    'blockNumber'       : 3710,
    'gasUsed'           : 72597,
    'cumulativeGasUsed' : 72597,
    'contractAddress'   : None,
    'logs'              : [],
    'status'            : 1
}

¿ Cómo puedo recuperar el valor real que some_funcha devuelto?

Encontré una respuesta muy detallada que parece referirse a este problema, pero no he podido concluir los pasos reales requeridos.

Gracias.

Respuestas (2)

Desafortunadamente, no hay un "valor de retorno" para una transacción. Hay dos patrones típicos para simular un valor de retorno:

  1. Mute el estado a través de una transacción y luego lea el estado resultante llamando a una viewfunción. (Tenga en cuenta que esto le da el estado en el momento en que llama a la viewfunción, no necesariamente el estado justo después de la transacción, ya que es posible que se hayan interpuesto otras transacciones).
  2. Mute el estado a través de una transacción y emita un mensaje eventque sea observado por la persona que llama.

Dependiendo de su escenario, uno u otro puede ser un ajuste más natural.

Sí, ya he recopilado esta información más o menos. La primera opción no es aceptable, debido a la razón que mencionas explícitamente. Necesito sumergirme en la segunda opción. ¿Tienes un buen ejemplo de codificación? Ambos lados (Solidity y Python-web3) serían geniales. Si no, entonces al menos en el lado de la Solidez. Gracias.
solidity.readthedocs.io/en/develop/contracts.html#events es bastante bueno, aunque es Solidity+JavaScript, no Solidity+Python.
Gracias, finalmente pude lograr este propósito. Respuesta práctica dada debajo de la tuya.

Así es como pude resolver este problema:

  1. En el contrato de Solidity, justo antes de devolver, genero un correo electrónico eventque contiene el valor a punto de devolver.
  2. En el código de Python, extraigo el valor devuelto con:

    retVal = eth.getTransactionReceipt(tx_hash)['logs'][0]['data']

Este valor resulta ser una cadena hexadecimal en mi caso, por lo que lo uso int(retVal,16)para obtener el valor entero correspondiente.