package org.web3j.abi; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.junit.Test; import org.web3j.abi.datatypes.DynamicArray; import org.web3j.abi.datatypes.DynamicBytes; import org.web3j.abi.datatypes.Function; import org.web3j.abi.datatypes.StaticArray; import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.Uint; import org.web3j.abi.datatypes.Utf8String; import org.web3j.abi.datatypes.generated.Bytes16; import org.web3j.abi.datatypes.generated.Bytes32; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.crypto.Hash; import org.web3j.utils.Numeric; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; public class FunctionReturnDecoderTest { @Test public void testSimpleFunctionDecode() { Function function = new Function( "test", Collections.<Type>emptyList(), Collections.singletonList(new TypeReference<Uint>(){}) ); assertThat(FunctionReturnDecoder.decode( "0x0000000000000000000000000000000000000000000000000000000000000037", function.getOutputParameters()), equalTo(Collections.singletonList(new Uint(BigInteger.valueOf(55))))); } @Test public void testSimpleFunctionStringResultDecode() { Function function = new Function("simple", Arrays.asList(), Collections.singletonList(new TypeReference<Utf8String>() { })); List<Type> utf8Strings = FunctionReturnDecoder.decode( "0x0000000000000000000000000000000000000000000000000000000000000020" + "000000000000000000000000000000000000000000000000000000000000000d" + "6f6e65206d6f72652074696d6500000000000000000000000000000000000000", function.getOutputParameters()); assertThat(utf8Strings.get(0).getValue(), is("one more time")); } @Test public void testFunctionEmptyStringResultDecode() { Function function = new Function("test", Collections.emptyList(), Collections.singletonList(new TypeReference<Utf8String>() { })); List<Type> utf8Strings = FunctionReturnDecoder.decode( "0x0000000000000000000000000000000000000000000000000000000000000020" + "0000000000000000000000000000000000000000000000000000000000000000", function.getOutputParameters()); assertThat(utf8Strings.get(0).getValue(), is("")); } @Test public void testMultipleResultFunctionDecode() { Function function = new Function( "test", Collections.<Type>emptyList(), Arrays.asList(new TypeReference<Uint>() { }, new TypeReference<Uint>() { }) ); assertThat(FunctionReturnDecoder.decode( "0x0000000000000000000000000000000000000000000000000000000000000037" + "0000000000000000000000000000000000000000000000000000000000000007", function.getOutputParameters()), equalTo(Arrays.asList(new Uint(BigInteger.valueOf(55)), new Uint(BigInteger.valueOf(7))))); } @Test public void testDecodeMultipleStringValues() { Function function = new Function("function", Collections.<Type>emptyList(), Arrays.asList( new TypeReference<Utf8String>() { }, new TypeReference<Utf8String>() { }, new TypeReference<Utf8String>() { }, new TypeReference<Utf8String>() { })); assertThat(FunctionReturnDecoder.decode( "0x0000000000000000000000000000000000000000000000000000000000000080" + "00000000000000000000000000000000000000000000000000000000000000c0" + "0000000000000000000000000000000000000000000000000000000000000100" + "0000000000000000000000000000000000000000000000000000000000000140" + "0000000000000000000000000000000000000000000000000000000000000004" + "6465663100000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000004" + "6768693100000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000004" + "6a6b6c3100000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000004" + "6d6e6f3200000000000000000000000000000000000000000000000000000000", function.getOutputParameters()), equalTo(Arrays.asList( new Utf8String("def1"), new Utf8String("ghi1"), new Utf8String("jkl1"), new Utf8String("mno2")))); } @Test @SuppressWarnings("unchecked") public void testDecodeStaticArrayValue() { List<TypeReference<Type>> outputParameters = new ArrayList<>(1); outputParameters.add((TypeReference) new TypeReference.StaticArrayTypeReference<StaticArray<Uint256>>(2) {}); outputParameters.add((TypeReference) new TypeReference<Uint256>() {}); List<Type> decoded = FunctionReturnDecoder.decode( "0x0000000000000000000000000000000000000000000000000000000000000037" + "0000000000000000000000000000000000000000000000000000000000000001" + "000000000000000000000000000000000000000000000000000000000000000a", outputParameters); List<Type> expected = Arrays.asList( new StaticArray<>(new Uint256(BigInteger.valueOf(55)), new Uint256(BigInteger.ONE)), new Uint256(BigInteger.TEN)); assertThat(decoded, equalTo(expected)); } @Test public void testVoidResultFunctionDecode() { Function function = new Function( "test", Collections.emptyList(), Collections.emptyList()); assertThat(FunctionReturnDecoder.decode("0x", function.getOutputParameters()), is(Collections.emptyList())); } @Test public void testEmptyResultFunctionDecode() { Function function = new Function( "test", Collections.emptyList(), Collections.singletonList(new TypeReference<Uint>() { })); assertThat(FunctionReturnDecoder.decode("0x", function.getOutputParameters()), is(Collections.emptyList())); } @Test public void testDecodeIndexedUint256Value() { Uint256 value = new Uint256(BigInteger.TEN); String encoded = TypeEncoder.encodeNumeric(value); assertThat(FunctionReturnDecoder.decodeIndexedValue( encoded, new TypeReference<Uint256>() {}), equalTo(value)); } @Test public void testDecodeIndexedStringValue() { Utf8String string = new Utf8String("some text"); String encoded = TypeEncoder.encodeString(string); String hash = Hash.sha3(encoded); assertThat(FunctionReturnDecoder.decodeIndexedValue( hash, new TypeReference<Utf8String>() {}), equalTo(new Bytes32(Numeric.hexStringToByteArray(hash)))); } @Test public void testDecodeIndexedBytes32Value() { String rawInput = "0x1234567890123456789012345678901234567890123456789012345678901234"; byte[] rawInputBytes = Numeric.hexStringToByteArray(rawInput); assertThat(FunctionReturnDecoder.decodeIndexedValue( rawInput, new TypeReference<Bytes32>(){}), equalTo(new Bytes32(rawInputBytes))); } @Test public void testDecodeIndexedBytes16Value() { String rawInput = "0x1234567890123456789012345678901200000000000000000000000000000000"; byte[] rawInputBytes = Numeric.hexStringToByteArray(rawInput.substring(0, 34)); assertThat(FunctionReturnDecoder.decodeIndexedValue( rawInput, new TypeReference<Bytes16>(){}), equalTo(new Bytes16(rawInputBytes))); } @Test public void testDecodeIndexedDynamicBytesValue() { DynamicBytes bytes = new DynamicBytes(new byte[]{ 1, 2, 3, 4, 5}); String encoded = TypeEncoder.encodeDynamicBytes(bytes); String hash = Hash.sha3(encoded); assertThat(FunctionReturnDecoder.decodeIndexedValue( hash, new TypeReference<DynamicBytes>() {}), equalTo(new Bytes32(Numeric.hexStringToByteArray(hash)))); } @Test public void testDecodeIndexedDynamicArrayValue() { DynamicArray<Uint256> array = new DynamicArray<>(new Uint256(BigInteger.TEN)); String encoded = TypeEncoder.encodeDynamicArray(array); String hash = Hash.sha3(encoded); assertThat(FunctionReturnDecoder.decodeIndexedValue( hash, new TypeReference<DynamicArray>() {}), equalTo(new Bytes32(Numeric.hexStringToByteArray(hash)))); } }