我正在玩以太坊和蟒蛇,我遇到了一些我无法理解的奇怪行为 . 在使用python w3客户端调用 Contract 函数时,我无法理解返回值的工作原理 . 这是一个最小的例子,它以几种不同的方式使我困惑:

Contract :

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())

我有三种方法对 Contract 中的功能进行测试 . 在其中一个中,返回非 True 值,而是返回 HexBytes . 在另一个中, Contract 函数返回一个地址常量,但python看到的值与预期值不同 . 在另一种情况下,我在没有气体的情况下调用 return_true Contract 函数,并且python看到 True 常量 .

  • 为什么用 transact={"from": self.w3.eth.accounts[0]} 调用 return_true 导致函数的返回值为 HexBytes(...)

  • 为什么 return_address 返回的地址与我的预期不同?

我想我对气体如何影响函数调用有一些基本的误解 .