Skip to content

Commit

Permalink
chore: re-work for Java 8 (Android compatibility)
Browse files Browse the repository at this point in the history
  • Loading branch information
rvullriede committed Jun 21, 2024
1 parent 5264504 commit 49fc6dc
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 37 deletions.
10 changes: 6 additions & 4 deletions src/main/java/net/osslabz/evm/abi/decoder/AbiDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -53,10 +52,12 @@ public DecodedFunctionCall decodeFunctionCall(String inputData) {
}
AbiDefinition.Entry abiEntry = this.methodSignatures.get(methodBytes);

if (!(abiEntry instanceof AbiDefinition.Function abiFunction)) {
if (!(abiEntry instanceof AbiDefinition.Function)) {
throw new IllegalArgumentException("Input data is not a function call, it's of type '" + abiEntry.type + "'.");
}

AbiDefinition.Function abiFunction = (AbiDefinition.Function) abiEntry;

List<DecodedFunctionCall.Param> params = new ArrayList<>(abiFunction.inputs.size());
List<?> decoded = abiFunction.decode(Hex.decode(inputNoPrefix));

Expand Down Expand Up @@ -122,7 +123,8 @@ public DecodedFunctionCall decodeLogEvent(List<String> topics, String data) {
if (abiEntry == null) {
throw new IllegalStateException("Couldn't find method with signature " + funcSignature);
} else {
if (abiEntry instanceof AbiDefinition.Event abiEvent) {
if (abiEntry instanceof AbiDefinition.Event) {
AbiDefinition.Event abiEvent = (AbiDefinition.Event) abiEntry;
List<?> decoded = abiEvent.decode(hexBytes(data), topics
.stream()
.map(AbiDecoder::hexBytes)
Expand All @@ -148,4 +150,4 @@ private static String cleanup(String hex) {
private static byte[] hexBytes(String hex) {
return Hex.decode(cleanup(hex));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public Param(String name, String type, Object value) {
this.type = type;
if (value instanceof byte[]) {
this.value = "0x" + ByteUtil.toHexString((byte[]) value);
} else if (value instanceof Object[] valueAsObjectArray) {
} else if (value instanceof Object[]) {
Object[] valueAsObjectArray = (Object[]) value;
this.value = new Object[valueAsObjectArray.length];
for (int i = 0; i < valueAsObjectArray.length; i++) {
Object o = valueAsObjectArray[i];
Expand All @@ -73,4 +74,4 @@ public String toString() {
return this.getClass().getName() + "(name=" + this.name + ", type=" + this.getType() + ", value=" + valueString + ")";
}
}
}
}
40 changes: 29 additions & 11 deletions src/main/java/net/osslabz/evm/abi/definition/AbiDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ public Entry.Param convert(Entry.Param param) {
for (Entry.Param c : param.components) {
((SolidityType.TupleType) param.type).getTypes().add(c.getType());
}
} else if (param.type instanceof SolidityType.ArrayType t && t.elementType instanceof SolidityType.TupleType) {
for (AbiDefinition.Entry.Param c : param.components) {
((SolidityType.TupleType) t.elementType).getTypes().add(c.getType());
} else if (param.type instanceof SolidityType.ArrayType) {
SolidityType.ArrayType arrayType = (SolidityType.ArrayType) param.type;
if (arrayType.elementType instanceof SolidityType.TupleType) {
for (AbiDefinition.Entry.Param c : param.components) {
((SolidityType.TupleType) arrayType.elementType).getTypes().add(c.getType());
}
}
}
return param;
Expand Down Expand Up @@ -141,12 +144,27 @@ public static Entry create(@JsonProperty("anonymous") boolean anonymous,
@JsonProperty("outputs") List<Param> outputs,
@JsonProperty("type") Type type,
@JsonProperty(value = "payable", required = false, defaultValue = "false") Boolean payable) {
return switch (type) {
case constructor -> new Constructor(inputs, outputs);
case function, fallback, receive -> new Function(constant, name, inputs, outputs, payable);
case event -> new Event(anonymous, name, inputs, outputs);
case error -> new Error(name, inputs);
};
Entry result = null;
switch (type) {
case constructor:
result = new Constructor(inputs, outputs);
break;
case function:
case fallback:
result = new Function(constant, name, inputs, outputs, payable);
break;
case receive:
result = new Function(constant, name, inputs, outputs, payable);
break;
case event:
result = new Event(anonymous, name, inputs, outputs);
break;
case error:
result = new Error(name, inputs);
break;
}

return result;
}

public String formatSignature() {
Expand All @@ -165,7 +183,7 @@ public String formatParamSignature(Param param) {
String type = param.type.getCanonicalName();
if (param.type instanceof SolidityType.TupleType) {
type = "(" + StringUtils.join(param.getComponents().stream().map(this::formatParamSignature).collect(Collectors.toList()), ",") + ")";
} else if (param.type instanceof SolidityType.ArrayType t && t.elementType instanceof SolidityType.TupleType) {
} else if (param.type instanceof SolidityType.ArrayType && ((SolidityType.ArrayType)param.type).elementType instanceof SolidityType.TupleType) {
type = "(" + StringUtils.join(param.getComponents().stream().map(this::formatParamSignature).collect(Collectors.toList()), ",") + ")[]";
}
return type;
Expand Down Expand Up @@ -371,4 +389,4 @@ public String toString() {
return format("error %s(%s);", name, join(inputs, ", "));
}
}
}
}
28 changes: 19 additions & 9 deletions src/main/java/net/osslabz/evm/abi/definition/SolidityType.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.util.List;


@Getter
public abstract class SolidityType {
private final static int Int32Size = 32;
/**
Expand Down Expand Up @@ -41,6 +40,13 @@ public static SolidityType getType(String typeName) {
throw new RuntimeException("Unknown type: " + typeName);
}

/**
* The type name as it was specified in the interface description
*/
public String getName() {
return name;
}

/**
* The canonical type name (used for the method signature creation)
* E.g. 'int' - canonical 'int256'
Expand Down Expand Up @@ -81,7 +87,6 @@ public String toString() {
}


@Getter
public static abstract class ArrayType extends SolidityType {
SolidityType elementType;

Expand All @@ -108,14 +113,14 @@ public byte[] encode(Object value) {
elems.add(Array.get(value, i));
}
return encodeList(elems);
} else if (value instanceof List<?>) {
return encodeList((List<?>) value);
} else if (value instanceof List) {
return encodeList((List) value);
} else {
throw new RuntimeException("List value expected for type " + getName());
}
}

protected byte[] encodeTuple(List<?> l) {
protected byte[] encodeTuple(List l) {
byte[][] elems;
if (elementType.isDynamicType()) {
elems = new byte[l.size() * 2][];
Expand Down Expand Up @@ -151,7 +156,11 @@ public Object[] decodeTuple(byte[] encoded, int origOffset, int len) {
}


public abstract byte[] encodeList(List<?> l);
public SolidityType getElementType() {
return elementType;
}

public abstract byte[] encodeList(List l);
}

public static class StaticArrayType extends ArrayType {
Expand All @@ -171,7 +180,7 @@ public String getCanonicalName() {
}

@Override
public byte[] encodeList(List<?> l) {
public byte[] encodeList(List l) {
if (l.size() != size)
throw new RuntimeException("List size (" + l.size() + ") != " + size + " for type " + getName());
return encodeTuple(l);
Expand Down Expand Up @@ -208,7 +217,7 @@ public String getCanonicalName() {
}

@Override
public byte[] encodeList(List<?> l) {
public byte[] encodeList(List l) {
return ByteUtil.merge(IntType.encodeInt(l.size()), encodeTuple(l));
}

Expand Down Expand Up @@ -299,7 +308,8 @@ public byte[] encode(Object value) {
byte[] bytes = ((String) value).getBytes(StandardCharsets.UTF_8);
System.arraycopy(bytes, 0, ret, 0, bytes.length);
return ret;
} else if (value instanceof byte[] bytes) {
} else if (value instanceof byte[]) {
byte[] bytes = (byte[]) value;
byte[] ret = new byte[Int32Size];
System.arraycopy(bytes, 0, ret, Int32Size - bytes.length, bytes.length);
return ret;
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/net/osslabz/evm/abi/util/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

@UtilityClass
public class FileUtil {

public String read(String path) throws URISyntaxException, IOException {
return Files.readString(Path.of(Objects.requireNonNull(FileUtil.class
.getClassLoader()
.getResource(path)).toURI()));
public String readFileIntoString(String path) throws URISyntaxException, IOException {
URL resource = Objects.requireNonNull(FileUtil.class.getClassLoader().getResource(path));
return new String(Files.readAllBytes(Paths.get(resource.toURI())), StandardCharsets.UTF_8);
}
}
}
10 changes: 5 additions & 5 deletions src/test/java/net/osslabz/evm/abi/AbiDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void testTupleArrayParamsDecode() throws URISyntaxException, IOException
AbiDecoder decoder = new AbiDecoder(this.getClass()
.getClassLoader()
.getResourceAsStream("abiFiles/ZkSync.json"));
DecodedFunctionCall decode = decoder.decodeFunctionCall(FileUtil.read("abiFiles/zkSync-input/input_0xe35a7dceb1536dfbd819ab6f756e4dcb19ea09541df54abf0f40064ba1163981"));
DecodedFunctionCall decode = decoder.decodeFunctionCall(FileUtil.readFileIntoString("abiFiles/zkSync-input/input_0xe35a7dceb1536dfbd819ab6f756e4dcb19ea09541df54abf0f40064ba1163981"));
Assertions.assertNotNull(decode);
Assertions.assertEquals(funcName, decode.getName());
Assertions.assertEquals(2, decode.getParams().size());
Expand Down Expand Up @@ -234,7 +234,7 @@ public void testUniswapV3Router() throws URISyntaxException, IOException {
AbiDecoder decoder = new AbiDecoder(this.getClass()
.getClassLoader()
.getResourceAsStream("abiFiles/UniswapV3Router.json"));
DecodedFunctionCall decode = decoder.decodeFunctionCall(FileUtil.read("abiFiles/uniswapV3Router-input/input_0xeb154fb38972106bfc0e9bce28130379c44d80be292de775e0f43e2c861e0f48"));
DecodedFunctionCall decode = decoder.decodeFunctionCall(FileUtil.readFileIntoString("abiFiles/uniswapV3Router-input/input_0xeb154fb38972106bfc0e9bce28130379c44d80be292de775e0f43e2c861e0f48"));
Assertions.assertNotNull(decode);
Assertions.assertEquals(funcName, decode.getName());
Assertions.assertEquals(1, decode.getParams().size());
Expand All @@ -256,7 +256,7 @@ public void testUSDTTransferLog() {
AbiDecoder decoder = new AbiDecoder(this.getClass()
.getClassLoader()
.getResourceAsStream("abiFiles/TetherToken.json"));
DecodedFunctionCall log = decoder.decodeLogEvent(List.of(
DecodedFunctionCall log = decoder.decodeLogEvent(Arrays.asList(
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef",
"0x00000000000000000000000047c27dea4d3625169a3dcad8c1fc4375e1c0a8fc"),
Expand All @@ -273,9 +273,9 @@ public void testLogWrongInput() {
AbiDecoder decoder = new AbiDecoder(this.getClass()
.getClassLoader()
.getResourceAsStream("abiFiles/TetherToken.json"));
Assertions.assertThrows(IllegalStateException.class, () -> decoder.decodeLogEvent(List.of("0xefef619ae4a542a2b8810b4efeccd8478bd683e985354ee31dd2d644aff6d0ca",
Assertions.assertThrows(IllegalStateException.class, () -> decoder.decodeLogEvent(Arrays.asList("0xefef619ae4a542a2b8810b4efeccd8478bd683e985354ee31dd2d644aff6d0ca",
"0x000000000000000000000000a5ece9bab9a0e56ad63ad0734033c944eeb00e1a",
"0x0000000000000000000000000000000000000000000000000000000000000000"),
"0x0000000000000000000000000000000000000000000000000020affce72f5800"));
}
}
}

0 comments on commit 49fc6dc

Please sign in to comment.