graph-tooling icon indicating copy to clipboard operation
graph-tooling copied to clipboard

`ethereum.decode` does not work for all encodings

Open lazycoder1 opened this issue 2 years ago • 1 comments

I have the following bytecode which is an input of the following tx

0x1fad948c0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000dbd510f9ebb7a81209fccd12a56f6c6354aa8cab000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000003ba340bc4194d7315c6f9f19aabc5f4a5cdc2e220000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000005d7000000000000000000000000000000000000000000000000000000000597771400000000000000000000000000000000000000000000000000000000059682f0000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c4f34308ef00000000000000000000000040a2accbd92bca938b02010e17a5b8929b49130d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a48d80ff0a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000152007ddefa2f027691116d0a7aa6418246622d70b12a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000a275da33fe068cd62510b8e3af7818ede891cdff0000000000000000000000000000000000000000000000000005b7e11a47f000000014f33fc01017d9ac6762e8285b51ad07089e51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000649b890b700000000000000000000000003ba340bc4194d7315c6f9f19aabc5f4a5cdc2e22000000000000000000000000ffcc60e7dbf2c9accdb0b8caa699d7b50086c8070000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091a275da33fe068cd62510b8e3af7818ede891cdff0000000000000000000000000005ba1044cbc00000000000000000000000000000015549b2f3b4007ddefa2f027691116d0a7aa6418246622d70b12a6a27a1a4dd4981e40f406dcef00a654b997f0d1e97b9c9d904e497d6770822215c49b80b54abe913192231475ce47b6ca4a38518440e209941e0592d6bc414891b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000413a177d93f69420b30a4b870a016171e2b088b8db1ffddab4221c5e326c4bfd3101afb0daad0e623f926ac626248bdeb3b08ef2e9781478f3c78961af4fb4e7931b00000000000000000000000000000000000000000000000000000000000000

To do that , the only way right now would be to slice off the function name and then use ethabi decode function. But even then , the eth decode fails.

// Following function was used inside the mapping file.
function decodeUserOpInput(userOpInput: string): void {
  const inputParams = userOpInput.slice(10);
  log.info("{}", [inputParams]);
  
  const decoded = ethereum.decode("((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)", Bytes.fromHexString(inputParams));
  if (decoded == null) {
    return;
  }
  // log.info("{}",[decoded.toTuple()[1].toString()]);
}

The ABI for the tx input is

{
    "inputs": [
      {
        "components": [
          { "internalType": "address", "name": "sender", "type": "address" },
          { "internalType": "uint256", "name": "nonce", "type": "uint256" },
          { "internalType": "bytes", "name": "initCode", "type": "bytes" },
          { "internalType": "bytes", "name": "callData", "type": "bytes" },
          {
            "internalType": "uint256",
            "name": "callGasLimit",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "verificationGasLimit",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "preVerificationGas",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "maxFeePerGas",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "maxPriorityFeePerGas",
            "type": "uint256"
          },
          {
            "internalType": "bytes",
            "name": "paymasterAndData",
            "type": "bytes"
          },
          { "internalType": "bytes", "name": "signature", "type": "bytes" }
        ],
        "internalType": "struct UserOperation[]",
        "name": "ops",
        "type": "tuple[]"
      },
      {
        "internalType": "address payable",
        "name": "beneficiary",
        "type": "address"
      }
    ],
    "name": "handleOps",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }

Since the mapping decoding did not work , I tried doing it with ethabi and the following code had to be used to break it down. The ethabi needed multiple params to debug due to the following issue - https://github.com/rust-ethereum/ethabi/issues/245

ethabi decode 
params -t '(address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[]' 
-t 'address' 
0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000dbd510f9ebb7a81209fccd12a56f6c6354aa8cab000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000003ba340bc4194d7315c6f9f19aabc5f4a5cdc2e220000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000493e0000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000005d7000000000000000000000000000000000000000000000000000000000597771400000000000000000000000000000000000000000000000000000000059682f0000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c4f34308ef00000000000000000000000040a2accbd92bca938b02010e17a5b8929b49130d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a48d80ff0a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000152007ddefa2f027691116d0a7aa6418246622d70b12a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000a275da33fe068cd62510b8e3af7818ede891cdff0000000000000000000000000000000000000000000000000005b7e11a47f000000014f33fc01017d9ac6762e8285b51ad07089e51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000649b890b700000000000000000000000003ba340bc4194d7315c6f9f19aabc5f4a5cdc2e22000000000000000000000000ffcc60e7dbf2c9accdb0b8caa699d7b50086c8070000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000091a275da33fe068cd62510b8e3af7818ede891cdff0000000000000000000000000005ba1044cbc00000000000000000000000000000015549b2f3b4007ddefa2f027691116d0a7aa6418246622d70b12a6a27a1a4dd4981e40f406dcef00a654b997f0d1e97b9c9d904e497d6770822215c49b80b54abe913192231475ce47b6ca4a38518440e209941e0592d6bc414891b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000413a177d93f69420b30a4b870a016171e2b088b8db1ffddab4221c5e326c4bfd3101afb0daad0e623f926ac626248bdeb3b08ef2e9781478f3c78961af4fb4e7931b00000000000000000000000000000000000000000000000000000000000000  

I want to understand if it's possible to do it using the current implementation in the graph-ts library or if there is any work around for this ?

lazycoder1 avatar Feb 19 '23 17:02 lazycoder1

Hi, I have been trying to decode below input in the said decode signature and the ethereum.decode function from @graphprotocol/[email protected] is not able to decode and always returns null. I have mentioned the expected output below.

Encoded Data: 0x000000000000000000000000c9154424b823b10579895ccbe442d41b9abd96ed00000000000000000000000000000000000000000000000000000000000000404b1bd82c5788cdd04891805420fb25b998f04a9000000000000000000000004800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000342f697066732f516d5972774b507942736f634b7141644232547a6a51504548667a334a38676b6b647368445559636565725a594400000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004b1bd82c5788cdd04891805420fb25b998f04a90000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004b1bd82c5788cdd04891805420fb25b998f04a9000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000411f0520c593dc4abdab59c4d98857aecb5c2044fa54c38457a9af73d4a92643b60f20f43770e9e4eee28c308cfa280051214e21e4d569f53a610e25e971d1987d1b00000000000000000000000000000000000000000000000000000000000000

Decode Signature: (address,(uint,string,(address,uint96)[],(address,uint96)[],bytes[]))

Expected Output: address: addr 0xc9154424B823b10579895cCBE442d41b9Abd96Ed,tuple(uint256,string,tuple(address,uint96)[],tuple(address,uint96)[],bytes[]): mintData 33972660487161002881133299338343911466387578307505366653877749112949075607624,/ipfs/QmYrwKPyBsocKqAdB2TzjQPEHfz3J8gkkdshDUYceerZYD,0x4b1BD82c5788Cdd04891805420fb25B998f04A90,10000,0x4b1BD82c5788Cdd04891805420fb25B998f04A90,1000,0x1f0520c593dc4abdab59c4d98857aecb5c2044fa54c38457a9af73d4a92643b60f20f43770e9e4eee28c308cfa280051214e21e4d569f53a610e25e971d1987d1b

txHash: https://etherscan.io/tx/0x0061c42b5c653d330c90f5d4cd83b952b1e157a9d32a3394df20d13eb0eb9846

Expected solution: It would be great if graph-ts lib could support array decoding OR if subgraphs could support external libraries like ethers.js

rahul7668gupta avatar Mar 06 '23 10:03 rahul7668gupta