esaulpaugh / headlong Goto Github PK
View Code? Open in Web Editor NEWHigh-performance Contract ABI and RLP for Ethereum
License: Apache License 2.0
High-performance Contract ABI and RLP for Ethereum
License: Apache License 2.0
using this abi
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "specId",
"type": "bytes32"
},
{
"indexed": false,
"name": "requester",
"type": "address"
},
{
"indexed": false,
"name": "requestId",
"type": "bytes32"
},
{
"indexed": false,
"name": "payment",
"type": "uint256"
},
{
"indexed": false,
"name": "callbackAddr",
"type": "address"
},
{
"indexed": false,
"name": "callbackFunctionId",
"type": "bytes4"
},
{
"indexed": false,
"name": "cancelExpiration",
"type": "uint256"
},
{
"indexed": false,
"name": "dataVersion",
"type": "uint256"
},
{
"indexed": false,
"name": "data",
"type": "bytes"
}
],
"name": "OracleRequest",
"type": "event"
}
with this event
{
"logIndex": "0x82",
"transactionIndex": "0x55",
"transactionHash": "0xda2b8561b0074d954ea33a26692e93ebff9710d2220e0eb5003abdc468bb0d8d",
"blockHash": "0x7203fb7525cc8fc2cfa53960013a56fce83f02594fcc691f27e324959d4f2d4e",
"blockNumber": "0xb7b059",
"address": "0x60B2582FB902Dff0B99c7AC30ABC08AaEfEEB309",
"data": "0x000000000000000000000000f9fc2b4a0e487297b05285e9b3327f26e70c4e9b6b7ff4ffa51b345e8459b03fdb280ac7f99caaf432142a1b800c581d8b4ed39f00000000000000000000000000000000000000000000000000ee59ddf89580d6000000000000000000000000f9fc2b4a0e487297b05285e9b3327f26e70c4e9b042f2b650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000604e53520000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000976375726c787e68747470733a2f2f6d61726b65742e6c696e6b2f76312f6e6f6465732f66373662653531392d653431652d343861302d393433302d3437333139656461306634332f766572696669636174696f6e2f726573706f6e73653f746f6b656e3d663336613737333531626533346433323830333965623766643536626630303264706174686d726573706f6e7365546f6b656e",
"topics": [
"0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65",
"0x3431373466353064613337333431306161363430326265313263626538636463"
],
"type": null,
"timestamp": 1615745574,
"uuid": "9f04ac61-3d16-48de-917e-95d0a622f404",
"additionalFields": {
"removed": "false"
}
}
when using web3js web3.eth.abi.decodeLog
produces this output
Result {
'0': '0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65',
'1': '0xf9fc2b4a0E487297B05285e9B3327f26e70c4E9b',
'2': '0x6b7ff4ffa51b345e8459b03fdb280ac7f99caaf432142a1b800c581d8b4ed39f',
'3': '67089854350328022',
'4': '0xf9fc2b4a0E487297B05285e9B3327f26e70c4E9b',
'5': '0x042f2b65',
'6': '1615745874',
'7': '1',
'8': '0x6375726c787e68747470733a2f2f6d61726b65742e6c696e6b2f76312f6e6f6465732f66373662653531392d653431652d343861302d393433302d3437333139656461306634332f766572696669636174696f6e2f726573706f6e73653f746f6b656e3d663336613737333531626533346433323830333965623766643536626630303264706174686d726573706f6e7365546f6b656e',
__length__: 9,
specId: '0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65',
requester: '0xf9fc2b4a0E487297B05285e9B3327f26e70c4E9b',
requestId: '0x6b7ff4ffa51b345e8459b03fdb280ac7f99caaf432142a1b800c581d8b4ed39f',
payment: '67089854350328022',
callbackAddr: '0xf9fc2b4a0E487297B05285e9B3327f26e70c4E9b',
callbackFunctionId: '0x042f2b65',
cancelExpiration: '1615745874',
dataVersion: '1',
data: '0x6375726c787e68747470733a2f2f6d61726b65742e6c696e6b2f76312f6e6f6465732f66373662653531392d653431652d343861302d393433302d3437333139656461306634332f766572696669636174696f6e2f726573706f6e73653f746f6b656e3d663336613737333531626533346433323830333965623766643536626630303264706174686d726573706f6e7365546f6b656e'
}
but we get this error using headlong
tuple index 7: not enough bytes remaining: 151 < 160
Please update Bouncy Castle, new CVEs
Hi @esaulpaugh and thanks again for an excellent library.
We're having some troubles using the library on this transaction: 0x996a15ed678a5276dbf446587a9bf53f90c3b961b7f711d58a5ec74d44b7d1c2
As seen in the parity traces number 2, the trace goes to 0xcd9dab5e666de980cecdc180cb31f296733e2587 with the following input data:
0x128acb08000000000000000000000000da3a20aad0c34fa742bd9813d45bbf67c787ae0b0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffdb9328a9ba5635a80846cdf000000000000000000000000fffd8963efd1fc6a506488495d951d5263988d2500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000016200163301ee63fb29f863f2333bd4466acb46cd8323e620cd9dab5e666de980cecdc180cb31f296733e258700000246cd75645a9ca57f7b9320004bb0641100000000000000beebe34d7e60da18da3a20aad0c34fa742bd9813d45bbf67c787ae0b0000000000000000c34333f9af9c04005800132f152689a72b0a484b49a37fc85a862006f4138f1b000000000000000a31acd25057ef0000000000e17c19c8ee8c58656d0035189628a3e880960bd07f47bdfeb91de21a4c9b431a00000000000000000dbaac192510fe00940106450dee7fd2fb8e39061434babcfc05599a6fb8202a9d2ba41aba912316d16742f259412b681898db00000007f5368cf7b9ce855960c0004bb0641100000000000000475b46c4aab2f8109f5b65fa97d1fd596e9d111d483f90f69cd8102a000000000004ac23d1c23b55042949007118742f53651043cbab06602299064d59deb60a745300000000000000004e3fe9b51a631e
This maps to the swap
function of the UniswapV3Pool
with the following ABI:
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "bool",
"name": "zeroForOne",
"type": "bool"
},
{
"internalType": "int256",
"name": "amountSpecified",
"type": "int256"
},
{
"internalType": "uint160",
"name": "sqrtPriceLimitX96",
"type": "uint160"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "swap",
"outputs": [
{
"internalType": "int256",
"name": "amount0",
"type": "int256"
},
{
"internalType": "int256",
"name": "amount1",
"type": "int256"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
The transaction is successful and the corresponding Swap event is emitted.
However, trying to decode this data with headlong
gives the following stack trace:
Caused by: java.lang.IllegalArgumentException: tuple index 4: not enough bytes remaining: 354 < 384
at com.esaulpaugh.headlong.abi.TupleType.decodeException(TupleType.java:316)
at com.esaulpaugh.headlong.abi.TupleType.decode(TupleType.java:246)
at com.esaulpaugh.headlong.abi.TupleType.decode(TupleType.java:30)
at com.esaulpaugh.headlong.abi.ABIType.decode(ABIType.java:176)
at com.esaulpaugh.headlong.abi.Function.decodeCall(Function.java:231)
After some debugging it seems like the offset for the last bytes array is wrong. It is probably set incorrectly in the data? However, the transaction goes through, so I'm a little unsure whats the expected behaviour for this trace.
Let me know what you think!
Håkon
Function function = new Function("foo(address)");
ByteBuffer byteBuffer = function.encodeCallWithArgs("f85a7c4b088c07ec9e982f158b63385ff20d6757");
throw exception as follow:
Exception in thread "main" java.lang.IllegalArgumentException: tuple index 0: class mismatch: java.lang.String not assignable to java.math.BigInteger (String not instanceof BigInteger/address)
please help me, thank you
Hi, I have a question on how to encode a uint256[] parameter. Creating a tuple for the following works just fine:
Function func = new Function("test(uint256[],bool)");
BigInteger[] bigints = new BigInteger[] { BigInteger.valueOf(7), BigInteger.valueOf(8), BigInteger.valueOf(9) };
Tuple args = Tuple.of(bigints, true);
ByteBuffer bb = func.encodeCall(args);
System.out.println(Function.formatCall(bb.array()));
but if the function argument is a pure uint256[] such as
Function func = new Function("test(uint256[])");
BigInteger[] bigints = new BigInteger[] { BigInteger.valueOf(7), BigInteger.valueOf(8), BigInteger.valueOf(9) };
Tuple args = Tuple.of(bigints);
ByteBuffer bb = func.encodeCall(args);
System.out.println(Function.formatCall(bb.array()));
the encoding fails with the following trace:
java.lang.IllegalArgumentException: tuple length mismatch: actual != expected: 3 != 1
at com.esaulpaugh.headlong.abi.TupleType.validate(TupleType.java:146)
at com.esaulpaugh.headlong.abi.Function.validatedCallLength(Function.java:193)
at com.esaulpaugh.headlong.abi.Function.encodeCall(Function.java:205)
Any suggestions on how to pass the pure uint256[] correctly in this case?
Thank you
Hi, I would like to decode function return. I am testing this returning single element array of structs. Tried using:
public Tuple decodeReturn(ByteBuffer buf) { return outputTypes.decode(buf); }
but I am receiving error that unsigned val exceeds bit limit: 160 > 31
. Going through stacktrace I am landing in UnitType<J>
which as description says is not suitable for arrays... Is there a way that I can decode output of my function?
Thanks!
Hi @esaulpaugh,
I initially asked on gitter, but thought I'd create an issue here directly.
Is there a way to decode events, like there is Function.decodeCall()
?
If not, I'd be happy to help implement that.
I really appreciate all the work you've done for this lib, it saved me so much time and the API is very well designed.
Hi @esaulpaugh ,
Thank you so much for a great library!
We've reached an edge case in decoding where we hit the exception mentioned in the title, IllegalArgumentException("unconsumed bytes: ...")
, when decoding a function's output.
We have the following input and output data data:
Input: 0xc37f68e200000000000000000000000037cab7add0393689fa50e979cc9bd8db7a9905aa
Output: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052f1a067938685bf66f0a400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ABI:
{
"constant": true,
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "getAccountSnapshot",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
The library throws the following exception with stack trace:
java.lang.IllegalArgumentException: unconsumed bytes: 64 remaining
at com.esaulpaugh.headlong.abi.ABIType.decode(ABIType.java:190)
at com.esaulpaugh.headlong.abi.Function.decodeReturn(Function.java:240)
The problem was quite easy to identify. The output data contains 6 x 32 bytes, while the decoder only expects 4 x 32 bytes ((uint256,uint256,uint256,uint256)
). This causes the exception.
One could argue that we do have the wrong data in the first place. Which might be the case, but I've triple checked our node provider API and this is what we get.
We do have a golang
implementation of decoding which uses geth which doesn't crash on this data. I've also created a quick test script which uses the official eth-abi library. Both implementations consume the data they need and disregard the last 64 bytes.
This begs the question: Does throwing an exception on unconsumed bytes adhere to the standard? Should we consider removing that check?
If not, we would be happy to discuss alternative APIs for us to use which doesn't do this check.
Let me know what you think!
Håkon
I've got problem with creation function that returns struct array.
My function looks like: getPoolsInfo(address[]) then the output is array of structs. Struct has fields: address, string, string
I tried to create function like this:
val f = Function("getPoolsInfo(address[])", "(address,string,string)[]")
But ide is screaming that it cannot cast arraytype to tupletype.
Can you tell me how to construct this function properly?
Hi,
I have been using the RLP library with examples, and discovered that:
FloatingPoint.java is under package com.esaulpaugh.headlong.rlp.util
;
But Integers.java and Strings.java is under package com.esaulpaugh.headlong.util
;
Maybe it is better to put them together under some package?
When trying to decode the data for this log
{
"logIndex": "0xae",
"transactionIndex": "0x51",
"transactionHash": "0xb304d3c6df4222f8d40722b37a88c6f9b25e0dfab931b7df67b7c6e58aa3e59c",
"blockHash": "0x12dcda41bfeee8190410ac00ead9af24f14d9142e076fb22480a8be383c1bc50",
"blockNumber": "0xc3757d",
"address": "0x6758B7d441a9739b98552B373703d8d3d14f9e62",
"data": "0x000000000000000000000000000000000000000000000034e2c0e23567d500000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100",
"topics": [
"0xe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16",
"0x00000000000000000000000080dfb2ec0c6e1cc2425b47eff16c26e2ff8ca1c8",
"0x000000000000000000000000d819e948b14ca6aad2b7ffd333ccdf732b129eed"
],
"type": null
}
using this abi
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "from",
"type": "address"
},
{
"indexed": true,
"name": "to",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
},
{
"indexed": false,
"name": "data",
"type": "bytes"
}
],
"name": "Transfer",
"type": "event"
}
doing
val event = Event.fromJson(abi)
event.getNonIndexedParams
.asInstanceOf[ABIType[Tuple]]
.decode(ByteBuffer.wrap(FastHex.decode(log.data.stripLeadingHex)))
we see the error
tuple index 1: not enough bytes remaining: 1 < 32
doing
event.getNonIndexedParams.decode
yields a similar result
tuple index 1: unsigned val exceeds bit limit: 254 > 31
i would expect it to be just returning empty for the data bytes parameter instead, any suggestions?
Here is the abi and it happens for Transfer and Approval events: uniswappairabi
val blockNumber = 14918135
val transactionHash = "0x72bf1f4c584163e06f951a92fda5e790cb6a0c87cf549866a6043699d8cc5053"
val data = Array[Byte]()
var topics = Array("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", "0x000000000000000000000000bdd95abe8a7694ccd77143376b0fbea183e6a740","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000002646")
val eventName = "Approval"
val event = AbiEvent(eventABI).toHeadlongEvent
val topics = topicsHex.map(decodeHex)
Some(event.decodeArgs(topics, data))
If I change the value parameter in the abi to be indexed then it worked perfectly fine but if not then it throws an exception:
expected topics.length == 3 but found length 4 which I think is related to how that function only counts indexedParams and not nonIndexedParams. Is their a better fix than just changing the abi for each event I want to decode and hoping it gives consistent data?
val args = Tuple.of("My new Name")
val function = com.esaulpaugh.headlong.abi.Function("setName(string)")
val encodedFunction = function.encodeCall(args)
val arr: ByteArray = encodedFunction.array()
val formattedEncoding =
com.esaulpaugh.headlong.abi.Function.formatCall(arr, 0, arr.size)
print(formattedEncoding)
Actual Result: ID c47f0027
0 0000000000000000000000000000000000000000000000000000000000000020
1 000000000000000000000000000000000000000000000000000000000000000b
2 4d79206e6577204e616d65000000000000000000000000000000000000000000
Expected Result: c47f00270000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b4d79206e6577204e616d65000000000000000000000000000000000000000000
I want the above code to return the expected result but it returns the above actual result. Please have a look @esaulpaugh
I have a funciton signature like this:
functionName((address,uint256))
i donot know how pass the params. there is always a error named tuple length mismatch
really thanks, by the way, may be we need more demos.
Hi,
I've noticed that this function, when called with on a Tuple
that looks like this ((address,int256))
and this manifest: [true]
, will still return ((address,int256))
even though I would expect to get (address,int256)
.
I'd be happy to help fix this issue, if it is actually an issue 🙂
Hi @esaulpaugh,
Thanks a lot for having done such a great job.
We use headlong as our core decoding facilitates at our open-source analytics library: https://github.com/datawaves-xyz/blockchain-spark. It is super fast, well maintained, and suits our use case.
Recently, we found some decoding errors from our server log. It almost failed on half of OpenSea's 'atomicMatch' function calls (address: 0x7f268357a8c2552623316e2562d90e642bb538e5
). I try to debug the program but hard to fix it by my self. So I am asking you for help.
Here's the stack trace:
java.lang.IllegalArgumentException: illegal backwards jump: (4+2848=2852)<2884
at com.esaulpaugh.headlong.abi.TupleType.decodeObjects(TupleType.java:306)
at com.esaulpaugh.headlong.abi.TupleType.decode(TupleType.java:193)
at com.esaulpaugh.headlong.abi.Function.decodeCall(Function.java:233)
(...)
I retrieve the data from our server. I decode it with Web3.py on my laptop then it works. The following code snippet is for reproducing the problem locally.
Function f = Function.fromJson("{\"constant\": false, \"inputs\": [{\"name\": \"addrs\", \"type\": \"address[14]\"}, {\"name\": \"uints\", \"type\": \"uint256[18]\"}, {\"name\": \"feeMethodsSidesKindsHowToCalls\", \"type\": \"uint8[8]\"}, {\"name\": \"calldataBuy\", \"type\": \"bytes\"}, {\"name\": \"calldataSell\", \"type\": \"bytes\"}, {\"name\": \"replacementPatternBuy\", \"type\": \"bytes\"}, {\"name\": \"replacementPatternSell\", \"type\": \"bytes\"}, {\"name\": \"staticExtradataBuy\", \"type\": \"bytes\"}, {\"name\": \"staticExtradataSell\", \"type\": \"bytes\"}, {\"name\": \"vs\", \"type\": \"uint8[2]\"}, {\"name\": \"rssMetadata\", \"type\": \"bytes32[5]\"}], \"name\": \"atomicMatch_\", \"outputs\": [], \"payable\": true, \"stateMutability\": \"payable\", \"type\": \"function\"}");
Tuple inputTuple = f.decodeCall(FastHex.decode("ab834bab0000000000000000000000007f268357a8c2552623316e2562d90e642bb538e5000000000000000000000000267011df2647c0a465a7d0aacb8257483db6b6c3000000000000000000000000f5962dd1cfb95bd15a598b721091b373fcf1e3d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000baf2127b49fc93cbca6269fade0f7f31df4c88a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f268357a8c2552623316e2562d90e642bb538e5000000000000000000000000f5962dd1cfb95bd15a598b721091b373fcf1e3d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b3256965e7c3cf26e11fcaf296dfc8807c01073000000000000000000000000baf2127b49fc93cbca6269fade0f7f31df4c88a70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ee0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000429d069189e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006235fb0800000000000000000000000000000000000000000000000000000000000000006d30435dda06a6f4136149c29818e18c3f3843728e80259fa66f1201fbdb91f000000000000000000000000000000000000000000000000000000000000002ee0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000429d069189e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006232b917000000000000000000000000000000000000000000000000000000006246314446231f8dcf1e298e1c8579f603c6fa74fa51f0f886c4ae376377eb08467f3c290000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c7596ed295fccb24c5008d11d537120b1b220dbe835bfd0ae15373d9f8e6a947c46c70ad794e802c20c451e530c4cf6962696174a2169e03f2f2a64000f93ea2a7596ed295fccb24c5008d11d537120b1b220dbe835bfd0ae15373d9f8e6a947c46c70ad794e802c20c451e530c4cf6962696174a2169e03f2f2a64000f93ea2a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4fb16a5950000000000000000000000000000000000000000000000000000000000000000000000000000000000000000267011df2647c0a465a7d0aacb8257483db6b6c3000000000000000000000000920a8d9e9f0defd6f86e4388a5503b04cac83b5700000000000000000000000000000000000000000000000000000000000031be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4fb16a595000000000000000000000000f5962dd1cfb95bd15a598b721091b373fcf1e3d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000920a8d9e9f0defd6f86e4388a5503b04cac83b5700000000000000000000000000000000000000000000000000000000000031be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e400000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
To get you to the site faster, the error happens when parsing the 8th element of the tuple:
Thanks again!
Yichao
Hi again :)
Is there possibility to encode abi params without function name itself? My workaround is empting first 4 bytes for example:
val args = Tuple(Address.wrap("0x5757371414417b8C6CAad45bAeF941aBc7d3Ab32"), 5)
val f = Function("(address,uint8)")
val callData = f.encodeCall(args)
it gives: 0xd6ec702b0000000000000000000000005757371414417b8c6caad45baef941abc7d3ab320000000000000000000000000000000000000000000000000000000000000005
then I clear first bytes. I bet that this library have such functionality.
Thanks!
I've a getName() that returns a string.
val function = com.esaulpaugh.headlong.abi.Function("getName()", "string")
val encodedFunction = function.encodeCallWithArgs()
val arr: ByteArray = encodedFunction.array()
val stringEncode =FastHex.encodeToString(arr,0, arr.size)
val response = web3j.ethCall(
Transaction.createEthCallTransaction(
credentials.address,
deployedContractAddress,
stringEncode
),
DefaultBlockParameterName.LATEST
)
.sendAsync().get()
val decodeResponse = function.decodeReturn(FastHex.decode(response.value))
I'm getting error that ArrayType cannot be cast to TupleType? How to get rid of this?
Hi @esaulpaugh ,
Thanks again for an amazing library!
I'm trying to decode the following.
Input Data:
0xab834bab0000000000000000000000007f268357a8c2552623316e2562d90e642bb538e50000000000000000000000002dba09471e78d26e42cc9b6057745bb0d430e38500000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b3256965e7c3cf26e11fcaf296dfc8807c01073000000000000000000000000baf2127b49fc93cbca6269fade0f7f31df4c88a70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007f268357a8c2552623316e2562d90e642bb538e5000000000000000000000000847236b8c34259a9bed67dcc1647cffba8fc01d40000000000000000000000002dba09471e78d26e42cc9b6057745bb0d430e3850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000baf2127b49fc93cbca6269fade0f7f31df4c88a70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ba800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000062727d6c000000000000000000000000000000000000000000000000000000006272b5fcba245d25e4e86afcbaf548aa790555f3467f38ba3078a2be2d7c057debc92214000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ba8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000627285c000000000000000000000000000000000000000000000000000000000000000006ff1fad6168460880a98b326f4c38e93fba0037fbe4fadf60939acddf28990510000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c099ee735236c1090e9eb80abde0b4ca69c81f84ba9deeab8710d7df0792ca90a1d302e1894b6bb588ab14ddf4c8c4218c30893ec9f622e7e019af865a0e96f1a099ee735236c1090e9eb80abde0b4ca69c81f84ba9deeab8710d7df0792ca90a1d302e1894b6bb588ab14ddf4c8c4218c30893ec9f622e7e019af865a0e96f1a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4fb16a59500000000000000000000000000000000000000000000000000000000000000000000000000000000000000002dba09471e78d26e42cc9b6057745bb0d430e3850000000000000000000000007d8820fa92eb1584636f4f5b8515b5476b75171a0000000000000000000000000000000000000000000000000000000000000d3d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4fb16a595000000000000000000000000847236b8c34259a9bed67dcc1647cffba8fc01d400000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d8820fa92eb1584636f4f5b8515b5476b75171a0000000000000000000000000000000000000000000000000000000000000d3d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e400000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ABI:
{
"constant": false,
"inputs": [
{
"name": "addrs",
"type": "address[14]"
},
{
"name": "uints",
"type": "uint256[18]"
},
{
"name": "feeMethodsSidesKindsHowToCalls",
"type": "uint8[8]"
},
{
"name": "calldataBuy",
"type": "bytes"
},
{
"name": "calldataSell",
"type": "bytes"
},
{
"name": "replacementPatternBuy",
"type": "bytes"
},
{
"name": "replacementPatternSell",
"type": "bytes"
},
{
"name": "staticExtradataBuy",
"type": "bytes"
},
{
"name": "staticExtradataSell",
"type": "bytes"
},
{
"name": "vs",
"type": "uint8[2]"
},
{
"name": "rssMetadata",
"type": "bytes32[5]"
}
],
"name": "atomicMatch_",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
However, I get the following error:
illegal backwards jump: (4+2368=2372)<2884
java.lang.IllegalArgumentException: illegal backwards jump: (4+2368=2372)<2884
at com.esaulpaugh.headlong.abi.TupleType.decodeObjects(TupleType.java:307)
at com.esaulpaugh.headlong.abi.TupleType.decode(TupleType.java:194)
at com.esaulpaugh.headlong.abi.Function.decodeCall(Function.java:230)
Do you happen to know why? The reason why I ask is that geth
seems to be able to decode it.
Thank you!
Hi, I'm getting
java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer;
at com.esaulpaugh.headlong.abi.TupleType.decodeObjects(TupleType.java:197)
at com.esaulpaugh.headlong.abi.TupleType.decode(TupleType.java:172)
at com.esaulpaugh.headlong.abi.Function.decodeCall(Function.java:236)
at com.esaulpaugh.headlong.abi.Function.decodeCall(Function.java:218)
when using headlong 5.6.0 from Maven central on Java 1.8.0_45.
If you plan to support Java 8 (as readme says) please consider building using maven.compiler.release=0 (see e.g. https://www.morling.dev/blog/bytebuffer-and-the-dreaded-nosuchmethoderror/).
Can you tell me the process of calling ABIV2 contract function on the chain of blocks ?
For more security, can you change old spongycastle (based on old bouncycastle) to bouncycastle?
I'm working in a code generation project and would like to generate the data structures for tuples instead of using Tuple
.
Would it be possible to parse and keep the internalType
JSON field in the ABI objects?
Thanks
this version is 9.1.1.
i try f.encodeCall(Tuple.singleton(w))
, w is new Boolean[]{false}
, An error has occurred, as shown below.
Of course, it's OK to use primitive types, such as new boolean[]{false}
.
In addition, it is no problem for non arrays, that is, it does not distinguish between Boolean and boolean
So, please support indistinguishable boolean as method encoding input parameter
The mistake of the original text is
tuple index 0: class mismatch: [Ljava.lang.Boolean; != [Z (bool[] requires boolean[] but found Boolean[]) java.lang.IllegalArgumentException: tuple index 0: class mismatch: [Ljava.lang.Boolean; != [Z (bool[] requires boolean[] but found Boolean[]) at com.esaulpaugh.headlong.abi.TupleType.countBytes(TupleType.java:139) at com.esaulpaugh.headlong.abi.TupleType.countBytes(TupleType.java:127) at com.esaulpaugh.headlong.abi.TupleType.validate(TupleType.java:146) at com.esaulpaugh.headlong.abi.Function.validatedCallLength(Function.java:193) at com.esaulpaugh.headlong.abi.Function.encodeCall(Function.java:205)
I've a function that takes a struct as an argument.
function addUser(User memory newUser) public payable{
users.push(newUser);
}
How can i parse this in headlong?
If i do the following, it does not work
val headLongFun = com.esaulpaugh.headlong.abi.Function("addUser(string)")
Hi @esaulpaugh ,
Thank you for a great library!
The library requires "receive"
ABI types to have name set to "receive"
. As far as I can tell, this is normally not a part of the ABI (example).
What this means is that if I use the ABIJSON
module to parse ABIs, I get errors for the "receive"
events, even though they look legit.
I'm curious what's the motivation behind this check and whether we could discuss ways of opting out of it?
Best,
Håkon
We are getting several un-decoded logs with the error: tuple index 7: not enough bytes remaining: 151 < 160
whereas these logs are decoded correctly by Etherscan and web3j.
As you mentioned in two of the previous issues we submitted (issue 1 and issue 2), the data length is not a multiple of 32 and should be padded.
We suspect the bytes
and string
fields are not padded correctly in some logs due to an old issue in Solidity where these were not encoded correctly and not padded resulting in several logs with a truncated data field. Here is the change in question: https://docs.soliditylang.org/en/latest/050-breaking-changes.html (See paragraph: "The ABI encoder now properly pads byte arrays and strings from calldata (msg.data and external function parameters) when used in external function calls and in abi.encode. For unpadded encoding, use abi.encodePacked.").
We believe other libraries are aware of this error and thus decode those logs and we were wondering if you would be considering adding this change to the library as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.