Skip to content

Commit

Permalink
Merge pull request #859 from MDhondt/get-revert-reason
Browse files Browse the repository at this point in the history
Retrieve revert reason for EthCall
  • Loading branch information
snazha-blkio committed Mar 11, 2019
2 parents 21b2c15 + a4074df commit 5e56333
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
@@ -1,12 +1,42 @@
package org.web3j.protocol.core.methods.response;

import java.util.Collections;
import java.util.List;

import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.generated.AbiTypes;
import org.web3j.protocol.core.Response;

/**
* eth_call.
*/
public class EthCall extends Response<String> {

// Numeric.toHexString(Hash.sha3("Error(string)".getBytes())).substring(0, 10)
private static final String errorMethodId = "0x08c379a0";

@SuppressWarnings("unchecked")
private static final List<TypeReference<Type>> revertReasonType = Collections.singletonList(
TypeReference.create((Class<Type>) AbiTypes.getType("string")));

public String getValue() {
return getResult();
}
}

public boolean reverts() {
return getValue() != null && getValue().startsWith(errorMethodId);
}

public String getRevertReason() {
if (reverts()) {
String hexRevertReason = getValue().substring(errorMethodId.length());
List<Type> decoded = FunctionReturnDecoder.decode(hexRevertReason, revertReasonType);
Utf8String decodedRevertReason = (Utf8String) decoded.get(0);
return decodedRevertReason.getValue();
}
return null;
}
}
33 changes: 33 additions & 0 deletions core/src/test/java/org/web3j/protocol/core/ResponseTest.java
Expand Up @@ -70,6 +70,7 @@

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -504,6 +505,38 @@ public void testEthCall() {

EthCall ethCall = deserialiseResponse(EthCall.class);
assertThat(ethCall.getValue(), is("0x"));
assertFalse(ethCall.reverts());
assertNull(ethCall.getRevertReason());
}

@Test
public void testEthCallReverted() {
buildResponse(
"{\n"
+ " \"id\":1,\n"
+ " \"jsonrpc\": \"2.0\",\n"
+ " \"result\": \"0x08c379a0"
+ "0000000000000000000000000000000000000000000000000000000000000020"
+ "00000000000000000000000000000000000000000000000000000000000000ee"
+ "536f6c696469747920757365732073746174652d726576657274696e67206578"
+ "63657074696f6e7320746f2068616e646c65206572726f72732e205468652072"
+ "6571756972652066756e6374696f6e2073686f756c6420626520757365642074"
+ "6f20656e737572652076616c696420636f6e646974696f6e732c207375636820"
+ "617320696e707574732c206f7220636f6e747261637420737461746520766172"
+ "6961626c657320617265206d65742c206f7220746f2076616c69646174652072"
+ "657475726e2076616c7565732066726f6d2063616c6c7320746f206578746572"
+ "6e616c20636f6e7472616374732e000000000000000000000000000000000000\"\n"
+ "}"
);

EthCall ethCall = deserialiseResponse(EthCall.class);
assertTrue(ethCall.reverts());
assertThat(ethCall.getRevertReason(), is("Solidity uses state-reverting exceptions to "
+ "handle errors. The require function should be "
+ "used to ensure valid conditions, such as inputs, "
+ "or contract state variables are met, or to "
+ "validate return values from calls to "
+ "external contracts."));
}

@Test
Expand Down

0 comments on commit 5e56333

Please sign in to comment.