Skip to content

Commit

Permalink
Merge pull request #3302 from NomicFoundation/add-flag-to-ignore-unkn…
Browse files Browse the repository at this point in the history
…own-eip-2718-hh-998

Process transactions with unknown tx types
  • Loading branch information
fvictorio committed Oct 27, 2022
2 parents 7027e82 + 53ff90c commit 8575354
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/nine-kangaroos-marry.md
@@ -0,0 +1,5 @@
---
"hardhat": patch
---

Fixed an issue when forking networks like Arbitrum Nitro that use non-standard transaction types (#2995, #3194).
Expand Up @@ -24,6 +24,7 @@ import { ReadOnlyValidTransaction } from "../transactions/ReadOnlyValidTransacti
import { HardhatBlockchainInterface } from "../types/HardhatBlockchainInterface";

import { ReadOnlyValidEIP1559Transaction } from "../transactions/ReadOnlyValidEIP1559Transaction";
import { ReadOnlyValidUnknownTypeTransaction } from "../transactions/ReadOnlyValidUnknownTypeTransaction";
import { rpcToBlockData } from "./rpcToBlockData";
import { rpcToTxData } from "./rpcToTxData";

Expand Down Expand Up @@ -297,9 +298,20 @@ export class ForkBlockchain
rpcToTxData(transaction) as FeeMarketEIP1559TxData
);
} else {
throw new InternalError(
`Unknown transaction type ${transaction.type.toString()}`
);
// we try to interpret unknown txs as legacy transactions, to support
// networks like Arbitrum that have non-standards tx types
try {
tx = new ReadOnlyValidUnknownTypeTransaction(
new Address(transaction.from),
Number(transaction.type),
rpcToTxData(transaction)
);
} catch (e: any) {
throw new InternalError(
`Could not process transaction with type ${transaction.type.toString()}`,
e
);
}
}

block.transactions.push(tx);
Expand Down
@@ -0,0 +1,162 @@
import { Common } from "@nomicfoundation/ethereumjs-common";
import { Transaction, TxData, TxOptions } from "@nomicfoundation/ethereumjs-tx";
import { Address } from "@nomicfoundation/ethereumjs-util";

import { InternalError } from "../../../core/providers/errors";

/* eslint-disable @nomiclabs/hardhat-internal-rules/only-hardhat-error */

/**
* This class is like `ReadOnlyValidTransaction` but for
* a transaction with an unknown tx type.
*/
export class ReadOnlyValidUnknownTypeTransaction extends Transaction {
public static fromTxData(_txData: TxData, _opts?: TxOptions): never {
throw new InternalError(
"`fromTxData` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public static fromSerializedTx(
_serialized: Buffer,
_opts?: TxOptions
): never {
throw new InternalError(
"`fromSerializedTx` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public static fromRlpSerializedTx(
_serialized: Buffer,
_opts?: TxOptions
): never {
throw new InternalError(
"`fromRlpSerializedTx` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public static fromValuesArray(_values: Buffer[], _opts?: TxOptions): never {
throw new InternalError(
"`fromRlpSerializedTx` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public readonly common: Common;

private readonly _sender: Address;
private readonly _actualType: number;

constructor(sender: Address, type: number, data: TxData = {}) {
super(data, { freeze: false });

this.common = this._getCommon();
this._sender = sender;
this._actualType = type;
}

public get type(): number {
return this._actualType;
}

public verifySignature(): boolean {
return true;
}

public getSenderAddress(): Address {
return this._sender;
}

public sign(): never {
throw new InternalError(
"`sign` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public getDataFee(): never {
throw new InternalError(
"`getDataFee` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public getBaseFee(): never {
throw new InternalError(
"`getBaseFee` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public getUpfrontCost(): never {
throw new InternalError(
"`getUpfrontCost` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public validate(_stringError?: false): never;
public validate(_stringError: true): never;
public validate(_stringError: boolean = false): never {
throw new InternalError(
"`validate` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public toCreationAddress(): never {
throw new InternalError(
"`toCreationAddress` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public getSenderPublicKey(): never {
throw new InternalError(
"`getSenderPublicKey` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public getMessageToVerifySignature(): never {
throw new InternalError(
"`getMessageToVerifySignature` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}

public getMessageToSign(): never {
throw new InternalError(
"`getMessageToSign` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
}
}

// Override private methods

const ReadOnlyValidUnknownTypeTransactionPrototype: any =
ReadOnlyValidUnknownTypeTransaction.prototype;

ReadOnlyValidUnknownTypeTransactionPrototype._validateTxV = function (
_v: any,
common: any
) {
return this._getCommon(common);
};

ReadOnlyValidUnknownTypeTransactionPrototype._signedTxImplementsEIP155 =
function () {
throw new InternalError(
"`_signedTxImplementsEIP155` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
};

ReadOnlyValidUnknownTypeTransactionPrototype._unsignedTxImplementsEIP155 =
function () {
throw new InternalError(
"`_unsignedTxImplementsEIP155` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
};

ReadOnlyValidUnknownTypeTransactionPrototype._getMessageToSign = function () {
throw new InternalError(
"`_getMessageToSign` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
};

ReadOnlyValidUnknownTypeTransactionPrototype._processSignature = function () {
throw new InternalError(
"`_processSignature` is not implemented in ReadOnlyValidUnknownTypeTransaction"
);
};

0 comments on commit 8575354

Please sign in to comment.