Skip to content

Commit

Permalink
Bug fix for Int256 decode range [2^248, type(int256).max] and [ type(…
Browse files Browse the repository at this point in the history
…int256.min), -(2^248) ) (#2070)

* Bug fix for Int256 decode

Signed-off-by: tonykwok1992 <[email protected]>

* Change log

Signed-off-by: tonykwok1992 <[email protected]>

* Test int16/Uint16 min max only

Signed-off-by: tonykwok1992 <[email protected]>

---------

Signed-off-by: tonykwok1992 <[email protected]>
  • Loading branch information
tonykwok1992 committed Jun 26, 2024
1 parent 9af565b commit 1e83c60
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 10 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline

### Bug Fixes

*
* Bug fix for Int256 decode range [2^248, type(int256).max] and [ type(int256.min), -(2^248) )

### Features

Expand Down
15 changes: 6 additions & 9 deletions abi/src/main/java/org/web3j/abi/TypeDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,14 @@ public static <T extends NumericType> T decodeNumeric(String input, Class<T> typ
try {
byte[] inputByteArray = Numeric.hexStringToByteArray(input);
int typeLengthAsBytes = getTypeLengthInBytes(type);

byte[] resultByteArray = new byte[typeLengthAsBytes + 1];

if (Int.class.isAssignableFrom(type) || Fixed.class.isAssignableFrom(type)) {
resultByteArray[0] = inputByteArray[0]; // take MSB as sign bit
}

int valueOffset = Type.MAX_BYTE_LENGTH - typeLengthAsBytes;
System.arraycopy(inputByteArray, valueOffset, resultByteArray, 1, typeLengthAsBytes);

BigInteger numericValue = new BigInteger(resultByteArray);
BigInteger numericValue;
if (Uint.class.isAssignableFrom(type) || Ufixed.class.isAssignableFrom(type)) {
numericValue = new BigInteger(1, inputByteArray, valueOffset, typeLengthAsBytes);
} else {
numericValue = new BigInteger(inputByteArray, valueOffset, typeLengthAsBytes);
}
return type.getConstructor(BigInteger.class).newInstance(numericValue);

} catch (NoSuchMethodException
Expand Down
57 changes: 57 additions & 0 deletions abi/src/test/java/org/web3j/abi/TypeDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -858,11 +858,68 @@ public void testIntDecode() throws Exception {
Int256.class),
(new Int256(BigInteger.valueOf(-1))));

assertEquals(
TypeDecoder.decodeNumeric(
TypeEncoder.encodeNumeric(new Int256(BigInteger.TWO.pow(248))),
Int256.class),
new Int256(BigInteger.TWO.pow(248)));

assertEquals(
TypeDecoder.decodeNumeric(
TypeEncoder.encodeNumeric(
new Int256(
BigInteger.TWO.pow(248).negate().subtract(BigInteger.ONE))),
Int256.class),
new Int256(BigInteger.TWO.pow(248).negate().subtract(BigInteger.ONE)));

assertEquals(
TypeDecoder.decodeNumeric(
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
Int256.class),
new Int256(
new BigInteger(
"57896044618658097711785492504343953926634992332820282019728792003956564819967")));

assertEquals(
TypeDecoder.decodeNumeric(
"0x8000000000000000000000000000000000000000000000000000000000000000",
Int256.class),
new Int256(
new BigInteger(
"-57896044618658097711785492504343953926634992332820282019728792003956564819968")));

assertEquals(TypeDecoder.instantiateType("int", 123), (new Int(BigInteger.valueOf(123))));

assertEquals(TypeDecoder.instantiateType("int", -123), (new Int(BigInteger.valueOf(-123))));
}

@Test
public void testInt16MinMax() throws Exception {
assertEquals(
TypeDecoder.decodeNumeric(
TypeEncoder.encodeNumeric(
new Int16(BigInteger.valueOf((long) Math.pow(2, 15) - 1))),
Int16.class),
new Int16(BigInteger.valueOf((long) Math.pow(2, 15) - 1)));

assertEquals(
TypeDecoder.decodeNumeric(
TypeEncoder.encodeNumeric(
new Int16(BigInteger.valueOf((long) -Math.pow(2, 15)))),
Int16.class),
new Int16(BigInteger.valueOf((long) -Math.pow(2, 15))));
}

@Test
public void testUint16Max() throws Exception {
assertEquals(
TypeDecoder.decodeNumeric(
TypeEncoder.encodeNumeric(
new Uint16(BigInteger.valueOf((long) Math.pow(2, 16) - 1))),
Uint16.class),
new Uint16(BigInteger.valueOf((long) Math.pow(2, 16) - 1)));
}

/*
TODO: Enable once Solidity supports fixed types - see
https://github.com/ethereum/solidity/issues/409
Expand Down

0 comments on commit 1e83c60

Please sign in to comment.