ponder-sh / ponder

A backend framework for crypto apps
https://ponder.sh
MIT License
646 stars 102 forks source link

The transactions in zksync era sometimes created without "r s v", which can cause error at db store. #705

Closed XmoDVO closed 8 months ago

XmoDVO commented 8 months ago

input

curl https://mainnet.era.zksync.io \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params": ["0x065f05d79e4d36fa57ce52f0483b082e4ee5cd9a008cd6ac6a6aa83930ee7795"],"id":1}'

no r s v singnature in output

{"jsonrpc":"2.0","result":{"hash":"0x065f05d79e4d36fa57ce52f0483b082e4ee5cd9a008cd6ac6a6aa83930ee7795","nonce":"0x6c","blockHash":"0x05c394d05381a88b41d9bc2f8e235ece9ad16906b69d28b681c9357a1eb3cb65","blockNumber":"0x15b9330","transactionIndex":"0xc","from":"0x3aa508f07a8c8a06a4380026579ef1d623f4d6f6","to":"0x240d5645bffaf6f8bc3586e459a4155f270bcb3b","value":"0x8f3ed38d58000","gasPrice":"0x8f0d180","gas":"0x238980","input":"0xac9650d800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a480e6331c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000001d8efef4880000000000000000000000000005aea5775959fbc2557cc8789bc1bf90a239d9a91000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fc00dac251711508d4dd7b0c310e9135759888380000000000000000000000005aea5775959fbc2557cc8789bc1bf90a239d9a910000000000000000000000003aa508f07a8c8a06a4380026579ef1d623f4d6f6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","type":"0x71","maxFeePerGas":"0x8f0d180","maxPriorityFeePerGas":"0x0","chainId":"0x144","l1BatchNumber":"0x5ac1b","l1BatchTxIndex":"0x303"},"id":1}

however, r s v is not optional to function rpcToSqliteTransaction

export function rpcToSqliteTransaction(
  transaction: RpcTransaction,
): Omit<InsertableTransaction, "chainId"> {
  return {
    accessList: transaction.accessList
      ? JSON.stringify(transaction.accessList)
      : undefined,
    blockHash: transaction.blockHash!,
    blockNumber: encodeAsText(transaction.blockNumber!),
    from: toLowerCase(transaction.from),
    gas: encodeAsText(transaction.gas),
    gasPrice: transaction.gasPrice ? encodeAsText(transaction.gasPrice) : null,
    hash: transaction.hash,
    input: transaction.input,
    maxFeePerGas: transaction.maxFeePerGas
      ? encodeAsText(transaction.maxFeePerGas)
      : null,
    maxPriorityFeePerGas: transaction.maxPriorityFeePerGas
      ? encodeAsText(transaction.maxPriorityFeePerGas)
      : null,
    nonce: hexToNumber(transaction.nonce),
    r: transaction.r,
    s: transaction.s,
    to: transaction.to ? toLowerCase(transaction.to) : null,
    transactionIndex: Number(transaction.transactionIndex),
    type: transaction.type ?? "0x0",
    value: encodeAsText(transaction.value),
    v: encodeAsText(transaction.v),
  };
}

encodeAsText will throw an error since transaction.v is undefined;

export function encodeAsText(value: bigint | number | Hex) {
  if (typeof value === "string" || typeof value === "number")
    value = BigInt(value);

  if (value > EVM_MAX_UINT)
    throw new Error(`Value cannot be greater than EVM_MAX_UINT (${value})`);
  if (value < EVM_MIN_INT)
    throw new Error(`Value cannot be less than EVM_MIN_INT (${value})`);

  const signChar = value >= 0n ? "0" : "-";

  // If the value is negative, add the minimum integer to it.
  if (value < 0n) value = value - EVM_MIN_INT;

  const chars = value.toString(10);  // <- value is undefined, toString cannot be called. !!!

  // Pad the hex string with leading zeros and add the sign byte.
  return signChar + chars.padStart(78, "0");
}

and it will causing unstoppable warning image

error stack image

0xOlias commented 8 months ago

Hi, thanks for reporting. We can fix this by making those fields optional. Out of curiosity, do you know if there's a technical reason for rsv sometimes being undefined on this chain, or is it just an error on the part of the RPC provider?

XmoDVO commented 8 months ago

I asked my colleague, hope it helps you, https://docs.zksync.io/build/developer-reference/account-abstraction.html#signature-validation zksync support another kind of signature (EIP-1271), Smart contract accounts have their own TX validation flow, not necessarily ECDSA, so r,s,v are empty.