Skip to content

Commit

Permalink
Merge pull request #6017 from NomicFoundation/update-micro-signer
Browse files Browse the repository at this point in the history
micro-eth-signer issue when deploying local accounts
  • Loading branch information
ChristopherDedominici authored Dec 9, 2024
2 parents 7273a6a + 8a0b6bc commit e484a7a
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 24 deletions.
49 changes: 37 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions v-next/hardhat-errors/src/descriptors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,13 @@ Try using another mnemonic or deriving less keys.`,
websiteTitle: "Invalid network type",
websiteDescription: `The network manager only supports the network types 'http' and 'edr'.`,
},
DATA_FIELD_CANNOT_BE_NULL_WITH_NULL_ADDRESS: {
number: 721,
messageTemplate: `The "to" field is undefined, and the "data" field is also undefined; however, a transaction to the null address cannot have an undefined "data" field.`,
websiteTitle: "Transaction to null address cannot have undefined data",
websiteDescription:
"The transaction to the null address cannot have undefined data",
},
},
KEYSTORE: {
INVALID_KEYSTORE_FILE_FORMAT: {
Expand Down
2 changes: 1 addition & 1 deletion v-next/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"debug": "^4.1.1",
"enquirer": "^2.3.0",
"ethereum-cryptography": "^2.2.1",
"micro-eth-signer": "^0.12.0",
"micro-eth-signer": "^0.13.0",
"p-map": "^7.0.2",
"semver": "^7.6.3",
"solc": "^0.8.27",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,25 @@ export class LocalAccountsHandler extends ChainId implements RequestHandler {
};
});

// TODO: Fix after the alpha release
assertHardhatInvariant(
txData.to !== undefined,
"The alpha version doesn't support deploying contracts with local accounts yet",
);
if (
(txData.to === undefined || txData.to === null) &&
txData.data === undefined
) {
throw new HardhatError(
HardhatError.ERRORS.NETWORK.DATA_FIELD_CANNOT_BE_NULL_WITH_NULL_ADDRESS,
);
}

const checksummedAddress = addr.addChecksum(
bytesToHexString(txData.to).toLowerCase(),
);
let checksummedAddress;
if (txData.to === undefined || txData.to === null) {
// This scenario arises during contract deployment. The npm package "micro-eth-signer" does not support
// null or undefined addresses. Therefore, these values must be converted to "0x", the expected format.
checksummedAddress = "0x";
} else {
checksummedAddress = addr.addChecksum(
bytesToHexString(txData.to).toLowerCase(),
);
}

assertHardhatInvariant(
txData.nonce !== undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ export const rpcAddress: ZodType<Uint8Array> = conditionalUnionType(
],
"Expected a Buffer with correct length or a valid RPC address string",
).transform((v) => (typeof v === "string" ? hexStringToBytes(v) : v));

export const nullableRpcAddress: ZodType<Uint8Array | null> = rpcAddress
.or(z.null())
.describe(
"Expected a Buffer with correct length, a valid RPC address string, or the null value",
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ZodType } from "zod";
import { z } from "zod";

import { rpcAccessList } from "./access-list.js";
import { rpcAddress } from "./address.js";
import { nullableRpcAddress, rpcAddress } from "./address.js";
import { rpcData } from "./data.js";
import { rpcHash } from "./hash.js";
import { rpcQuantity } from "./quantity.js";
Expand All @@ -12,7 +12,7 @@ const optional = <T extends ZodType<any>>(schema: T) => schema.optional();

export interface RpcTransactionRequest {
from: Uint8Array;
to?: Uint8Array;
to?: Uint8Array | null;
gas?: bigint;
gasPrice?: bigint;
value?: bigint;
Expand All @@ -28,7 +28,7 @@ export interface RpcTransactionRequest {

export const rpcTransactionRequest: ZodType<RpcTransactionRequest> = z.object({
from: rpcAddress,
to: optional(rpcAddress),
to: optional(nullableRpcAddress),
gas: optional(rpcQuantity),
gasPrice: optional(rpcQuantity),
value: optional(rpcQuantity),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,66 @@ describe("LocalAccountsHandler", () => {
});

describe("modifyRequest", () => {
describe("sending transactions to the null address", () => {
const testCases = [null, undefined];

for (const testCase of testCases) {
it(`should succeed when the data field is not empty and the "to" field is ${testCase}`, async () => {
const tx = {
to: testCase,
from: "0xb5bc06d4548a3ac17d72b372ae1e416bf65b8ead",
gas: numberToHexString(30000),
nonce: numberToHexString(0),
value: numberToHexString(1),
chainId: numberToHexString(MOCK_PROVIDER_CHAIN_ID),
maxFeePerGas: numberToHexString(12),
maxPriorityFeePerGas: numberToHexString(2),
data: "0x01",
};

const jsonRpcRequest = getJsonRpcRequest(1, "eth_sendTransaction", [
tx,
]);

await localAccountsHandler.handle(jsonRpcRequest);

assert.ok(
Array.isArray(jsonRpcRequest.params),
"params should be an array",
);

const rawTransaction = hexStringToBytes(jsonRpcRequest.params[0]);
// The tx type is encoded in the first byte, and it must be the EIP-1559 one
assert.equal(rawTransaction[0], 2);
});

it(`should throw when the data field is undefined and the "to" field is ${testCase}`, async () => {
const tx = {
to: testCase,
// In this test scenario, the "data" field is omitted
from: "0xb5bc06d4548a3ac17d72b372ae1e416bf65b8ead",
gas: numberToHexString(30000),
nonce: numberToHexString(0),
value: numberToHexString(1),
chainId: numberToHexString(MOCK_PROVIDER_CHAIN_ID),
maxFeePerGas: numberToHexString(12),
maxPriorityFeePerGas: numberToHexString(2),
};

const jsonRpcRequest = getJsonRpcRequest(1, "eth_sendTransaction", [
tx,
]);

assertRejectsWithHardhatError(
() => localAccountsHandler.handle(jsonRpcRequest),
HardhatError.ERRORS.NETWORK
.DATA_FIELD_CANNOT_BE_NULL_WITH_NULL_ADDRESS,
{},
);
});
}
});

it("should, given two identical tx, return the same raw transaction", async () => {
const jsonRpcRequest = getJsonRpcRequest(1, "eth_sendTransaction", [
{
Expand Down

0 comments on commit e484a7a

Please sign in to comment.