Я играю с ethereum и python, и у меня какое-то странное поведение, которое я не могу понять. У меня возникают проблемы с пониманием того, как возвращаемые значения работают при вызове функции контракта с клиентом Python w3. Вот минимальный пример, который смущает меня несколькими способами:
Контракт:
pragma solidity ^0.4.0;
contract test {
function test(){
}
function return_true() public returns (bool) {
return true;
}
function return_address() public returns (address) {
return 0x111111111111111111111111111111111111111;
}
}
Код юнит-теста Python
from web3 import Web3, EthereumTesterProvider
from solc import compile_source
from web3.contract import ConciseContract
import unittest
import os
def get_contract_source(file_name):
with open(file_name) as f:
return f.read()
class TestContract(unittest.TestCase):
CONTRACT_FILE_PATH = "test.sol"
DEFAULT_PROPOSAL_ADDRESS = "0x1111111111111111111111111111111111111111"
def setUp(self):
# copied from https://github.com/ethereum/web3.py/tree/1802e0f6c7871d921e6c5f6e43db6bf2ef06d8d1 with MIT licence
# has slight modifications to work with this unittest
contract_source_code = get_contract_source(self.CONTRACT_FILE_PATH)
compiled_sol = compile_source(contract_source_code) # Compiled source code
contract_interface = compiled_sol[':test']
# web3.py instance
self.w3 = Web3(EthereumTesterProvider())
# Instantiate and deploy contract
self.contract = self.w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
# Get transaction hash from deployed contract
tx_hash = self.contract.constructor().transact({'from': self.w3.eth.accounts[0]})
# Get tx receipt to get contract address
tx_receipt = self.w3.eth.getTransactionReceipt(tx_hash)
self.contract_address = tx_receipt['contractAddress']
# Contract instance in concise mode
abi = contract_interface['abi']
self.contract_instance = self.w3.eth.contract(address=self.contract_address, abi=abi,
ContractFactoryClass=ConciseContract)
def test_return_true_with_gas(self):
# Fails with HexBytes('0xd302f7841b5d7c1b6dcff6fca0cd039666dbd0cba6e8827e72edb4d06bbab38f') != True
self.assertEqual(True, self.contract_instance.return_true(transact={"from": self.w3.eth.accounts[0]}))
def test_return_true_no_gas(self):
# passes
self.assertEqual(True, self.contract_instance.return_true())
def test_return_address(self):
# fails with AssertionError: '0x1111111111111111111111111111111111111111' != '0x0111111111111111111111111111111111111111'
self.assertEqual(self.DEFAULT_PROPOSAL_ADDRESS, self.contract_instance.return_address())
У меня есть три метода, выполняющих тестирование функций в контракте. В одном из них возвращается не True
значение и вместо него HexBytes
. В другом случае функции контракта возвращают адресную константу, но python видит значение, отличное от ожидаемого. В еще одном случае я вызываю контрактную функцию return_true
без газа, а постоянная True
видна Python.
- Почему при вызове
return_true
с transact={"from": self.w3.eth.accounts[0]}
возвращаемое значение функции будет HexBytes(...)
?
- Почему адрес, возвращаемый
return_address
, отличается от того, что я ожидал?
Я думаю, что у меня есть какое-то фундаментальное неправильное понимание того, как газ влияет на вызовы функций.