简体   繁体   中英

Web3j java function call returns empty list on solidity contract

I'm trying to call the function getPrice from this solidity contract

pragma solidity ^0.4.0;

contract DataExchangeOfferContract {    
    uint price;

    constructor(uint _price) public {
        price = _price;
    }

    function getPrice() public constant returns (uint) {
        return price;
    }
}

I'm running a private blockchain client in debug mode using geth , and I deployed a contract with a value. Here is how I try to call the function of the only contract deployed:

EthBlock.Block block = web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, true).send().getBlock();
Transaction transaction = web3j.ethGetTransactionByBlockHashAndIndex(block.getHash(), BigInteger.ZERO).send().getTransaction().get();
String hash = transaction.getHash();

Function function = new Function(DataExchangeOfferContract.FUNC_GETPRICE, Collections.emptyList(), Collections.singletonList(new TypeReference<Uint256>() {}));
String functionEncoder = FunctionEncoder.encode(function);

Transaction transaction = Transaction.createEthCallTransaction(address, functionEncoder, null);
EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
List<Type> types = FunctionReturnDecoder.decode(response.getValue(), function.getOutputParameters());
BigInteger price = (BigInteger) types.get(0).getValue();

Here types has 0 elements. What am I doing wrong?

EDIT:

The missing thing is that the contract address is not the transaction hash. The contract address is retrieved like this:

EthGetTransactionReceipt transactionReceipt = web3j.ethGetTransactionReceipt(hash).send();
String address = transactionReceipt.getTransactionReceipt().get().getContractAddress();

Then as pointed out in the responses, the call can be called using the contract wrapper, or using the previously described approach, passing the contract address and not the transaction hash as parameter .

If your goal is to just get the price from the latest block, you're making it more complicated than it needs to be. Assuming DataExchangeOfferContract is your generated stub (your Solidity code just says Contract ), you already have a getPrice method defined. To use it, your code should look something like this:

Web3j web3j = Web3j.build(new HttpService());

TransactionManager manager = new ReadonlyTransactionManager(web3j, "YOUR_ADDRESS");
DataExchangeOfferContract contract = DataExchangeOfferContract.load("CONTRACT_ADDRESS", web3j, 
                                                                    manager, Contract.GAS_PRICE,
                                                                    Contract.GAS_LIMIT);
RemoteCall<BigInteger> remoteCall = contract.getPrice();
BigInteger price = remoteCall.send();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM