Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions src/main/java/org/arkecosystem/crypto/utils/AbiDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,44 @@ public Map<String, Object> decodeFunctionData(String data) throws Exception {
return result;
}

public String decodeError(String data) throws Exception {
data = stripHexPrefix(data);

String errorSelector = data.substring(0, 8);

Map<String, Object> abiItem = findErrorBySelector(errorSelector);
if (abiItem == null) {
throw new Exception("Function selector not found in ABI: " + errorSelector);
}

return (String) abiItem.get("name");
}

private Map<String, Object> findFunctionBySelector(String selector) {
for (Map<String, Object> item : this.abi) {
if ("function".equals(item.get("type"))) {
String functionSignature = getFunctionSignature(item);
String functionSelector =
stripHexPrefix(keccak256(functionSignature)).substring(0, 8);
if (functionSelector.equals(selector)) {
return item;
}
if (!"function".equals(item.get("type"))) {
continue;
}

String functionSignature = getFunctionSignature(item);
String functionSelector = stripHexPrefix(keccak256(functionSignature)).substring(0, 8);
if (functionSelector.equals(selector)) {
return item;
}
}
return null;
}

private Map<String, Object> findErrorBySelector(String selector) {
for (Map<String, Object> item : this.abi) {
if (!"error".equals(item.get("type"))) {
continue;
}

String errorSignature = getFunctionSignature(item);
String errorSelector = stripHexPrefix(keccak256(errorSignature)).substring(0, 8);
if (errorSelector.equals(selector)) {
return item;
}
}
return null;
Expand Down
38 changes: 38 additions & 0 deletions src/test/java/org/arkecosystem/crypto/utils/AbiDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,42 @@ void it_should_decode_vote_payload() throws Exception {

assertEquals(expectedData, decodedData);
}

@Test
void it_should_decode_error_payload() throws Exception {
assertEquals("CallerIsNotValidator", decoder.decodeError("cd03235e"));
}

@Test
void it_should_decode_error_payload_with_hex_prefix() throws Exception {
assertEquals("CallerIsNotValidator", decoder.decodeError("0xcd03235e"));
}

@Test
void it_should_decode_error_with_parameters() throws Exception {
String selector = stripSelector("InvalidRange(uint256,uint256)");

assertEquals("InvalidRange", decoder.decodeError(selector));
}

@Test
void it_should_throw_when_error_selector_is_not_found() {
Exception thrown = assertThrows(Exception.class, () -> decoder.decodeError("123456ab"));

assertEquals("Function selector not found in ABI: 123456ab", thrown.getMessage());
}

@Test
void it_should_not_decode_function_selectors_as_errors() {
String voteSelector = "6dd7d8ea";

Exception thrown = assertThrows(Exception.class, () -> decoder.decodeError(voteSelector));

assertEquals("Function selector not found in ABI: " + voteSelector, thrown.getMessage());
}

private String stripSelector(String signature) {
String hash = org.web3j.crypto.Hash.sha3String(signature);
return hash.startsWith("0x") ? hash.substring(2, 10) : hash.substring(0, 8);
}
}
Loading