Go-Ethereum

從合約 web3j 返回的空值 (0x)

  • March 22, 2022

我正在嘗試使用Web3j 4.2.0在 Windows 10 上部署一個非常簡單的契約。我已經使用 Mist 創建了一個帳戶。我已經在我的機器上設置了一個本地乙太坊節點(使用geth),並且我能夠使案例如部署合約並與之互動。薄霧。但是當我一直試圖從 Java 程式碼中做同樣的事情時,我得到

org.web3j.tx.exceptions.ContractCallException: Empty value (0x) returned from contract

at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:250)
at org.web3j.tx.Contract.lambda$executeRemoteCallSingleValueReturn$1(Contract.java:317)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:30)

這是我的穩固契約:

pragma solidity ^0.5.5;

contract SampleContract{
uint256 sampleVariable = 0;

   function setSample(uint256 x) public{
       sampleVariable = x;
   }
   function getSample() public view returns(uint256){
       return sampleVariable;
   }
}

我使用solidity編譯器和web3j CLI 4.2.0創建了一個java包裝類:

/**
* <p>Auto generated code.
* <p><strong>Do not modify!</strong>
* <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
* or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the 
* <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 4.2.0.
*/
public class SampleContract extends Contract {
   private static final String BINARY = "60806040526000805534801561001457600080fd5b5060a2806100236000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806331c8039b146037578063e221818b14604f575b600080fd5b603d606b565b60408051918252519081900360200190f35b606960048036036020811015606357600080fd5b50356071565b005b60005490565b60005556fea165627a7a72305820de9e3ced16dc30cb74a4215c04b4b6f5f61df43a4bc0c38fbbd23e798b6b805d0029";

   public static final String FUNC_GETSAMPLE = "getSample";

   public static final String FUNC_SETSAMPLE = "setSample";

   @Deprecated
   protected SampleContract(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
       super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
   }

   protected SampleContract(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
       super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
   }

   @Deprecated
   protected SampleContract(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
       super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
   }

   protected SampleContract(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
       super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
   }

   public RemoteCall<BigInteger> getSample() {
       final Function function = new Function(FUNC_GETSAMPLE, 
               Arrays.<Type>asList(), 
               Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
       return executeRemoteCallSingleValueReturn(function, BigInteger.class);
   }

   public RemoteCall<TransactionReceipt> setSample(BigInteger x) {
       final Function function = new Function(
               FUNC_SETSAMPLE, 
               Arrays.<Type>asList(new Uint256(x)),
               Collections.<TypeReference<?>>emptyList());
       return executeRemoteCallTransaction(function);
   }

   @Deprecated
   public static SampleContract load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
       return new SampleContract(contractAddress, web3j, credentials, gasPrice, gasLimit);
   }

   @Deprecated
   public static SampleContract load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
       return new SampleContract(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
   }

   public static SampleContract load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
       return new SampleContract(contractAddress, web3j, credentials, contractGasProvider);
   }

   public static SampleContract load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
       return new SampleContract(contractAddress, web3j, transactionManager, contractGasProvider);
   }

   public static RemoteCall<SampleContract> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
       return deployRemoteCall(SampleContract.class, web3j, credentials, contractGasProvider, BINARY, "");
   }

   @Deprecated
   public static RemoteCall<SampleContract> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
       return deployRemoteCall(SampleContract.class, web3j, credentials, gasPrice, gasLimit, BINARY, "");
   }

   public static RemoteCall<SampleContract> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
       return deployRemoteCall(SampleContract.class, web3j, transactionManager, contractGasProvider, BINARY, "");
   }

   @Deprecated
   public static RemoteCall<SampleContract> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
       return deployRemoteCall(SampleContract.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "");
   }
} 

下面是合約創建的java程式碼:

Credentials credentials = WalletUtils.loadCredentials(password,
       keystorePath);

SampleContract sampleContract= SampleContract.deploy(web3j, credentials, new DefaultGasProvider()).send();

LOGGER.info("Contract deployed under address: " + sampleContract.getContractAddress());

LOGGER.info("Is contract valid : " + sampleContract.isValid());

BigInteger sampleNumber = sampleContract.getSample().send();

我能夠部署契約,獲取它的地址,還檢查這個契約是否有效返回 true。但是當我嘗試從中讀取(最後一行程式碼)時,它總是拋出 org.web3j.tx.exceptions.ContractCallException。你知道這是什麼原因嗎?感謝幫助。

使用 SampleContract Wrapper 中的 load(…) 方法,然後呼叫 getSample()

我現在無法測試它,但它應該看起來像這樣

// your code for deploy and wait until it deployed
SampleContract myContract = SampleContract.load(<your-contract-address>, web3j, credentails, ......etc);
BigInteger sNumber = myContract.getSample().send();   
//or BigInteger sNumber = myContract.getSample().sendAsync().get(); 

你有沒有解決這個問題。我也有同樣的問題

引用自:https://ethereum.stackexchange.com/questions/69654