From a12030ad29aa13c02aa75d9e0860f4986a0043b4 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Fri, 27 Sep 2019 21:54:10 -0400 Subject: [PATCH] Allow numeric values in a transaction to be odd-lengthed hexstrings (#614). --- packages/bytes/src.ts/index.ts | 24 ++++++++++++++++++------ packages/tests/src.ts/test-wallet.ts | 11 +++++++++++ packages/transactions/src.ts/index.ts | 14 ++++++++------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/bytes/src.ts/index.ts b/packages/bytes/src.ts/index.ts index 7f2927d16e..a0ed73b63c 100644 --- a/packages/bytes/src.ts/index.ts +++ b/packages/bytes/src.ts/index.ts @@ -13,7 +13,7 @@ export type BytesLike = Bytes | string; export type DataOptions = { allowMissingPrefix?: boolean; - allowOddLength?: boolean; + hexPad?: "left" | "right" | null; }; export interface Hexable { @@ -112,8 +112,14 @@ export function arrayify(value: BytesLike | Hexable | number, options?: DataOpti if (isHexString(value)) { let hex = (value).substring(2); - if (!options.allowOddLength && hex.length % 2) { - logger.throwArgumentError("hex data is odd-length", "value", value); + if (hex.length % 2) { + if (options.hexPad === "left") { + hex = "0x0" + hex.substring(2); + } else if (options.hexPad === "right") { + hex += "0"; + } else { + logger.throwArgumentError("hex data is odd-length", "value", value); + } } let result = []; @@ -212,8 +218,14 @@ export function hexlify(value: BytesLike | Hexable | number, options?: DataOptio if (isHexable(value)) { return value.toHexString(); } if (isHexString(value)) { - if (!options.allowOddLength && (value).length % 2) { - logger.throwArgumentError("hex data is odd-length", "value", value); + if ((value).length % 2) { + if (options.hexPad === "left") { + value = "0x0" + (value).substring(2); + } else if (options.hexPad === "right") { + value += "0"; + } else { + logger.throwArgumentError("hex data is odd-length", "value", value); + } } return (value).toLowerCase(); } @@ -273,7 +285,7 @@ export function hexConcat(items: Array): string { } export function hexValue(value: BytesLike | Hexable | number): string { - let trimmed = hexStripZeros(hexlify(value, { allowOddLength: true })); + let trimmed = hexStripZeros(hexlify(value, { hexPad: "left" })); if (trimmed === "0x") { return "0x0"; } return trimmed; } diff --git a/packages/tests/src.ts/test-wallet.ts b/packages/tests/src.ts/test-wallet.ts index 6316ee2ae3..1886241f03 100644 --- a/packages/tests/src.ts/test-wallet.ts +++ b/packages/tests/src.ts/test-wallet.ts @@ -270,3 +270,14 @@ describe('Test Signing Messages', function() { }); }); }); + +describe("Serialize Transactions", function() { + it("allows odd-length numeric values", function() { + const result = ethers.utils.serializeTransaction({ + gasLimit: "0x1", + gasPrice: "0x1", + value: "0x1" + }); + console.log(result); + }); +}); diff --git a/packages/transactions/src.ts/index.ts b/packages/transactions/src.ts/index.ts index b4c90eafe1..050bccc0f9 100644 --- a/packages/transactions/src.ts/index.ts +++ b/packages/transactions/src.ts/index.ts @@ -2,7 +2,7 @@ import { getAddress } from "@ethersproject/address"; import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; -import { arrayify, BytesLike, hexDataSlice, hexlify, hexZeroPad, SignatureLike, splitSignature, stripZeros, } from "@ethersproject/bytes"; +import { arrayify, BytesLike, DataOptions, hexDataSlice, hexlify, hexZeroPad, SignatureLike, splitSignature, stripZeros, } from "@ethersproject/bytes"; import { Zero } from "@ethersproject/constants"; import { keccak256 } from "@ethersproject/keccak256"; import { checkProperties } from "@ethersproject/properties"; @@ -60,11 +60,11 @@ function handleNumber(value: string): BigNumber { } const transactionFields = [ - { name: "nonce", maxLength: 32 }, - { name: "gasPrice", maxLength: 32 }, - { name: "gasLimit", maxLength: 32 }, + { name: "nonce", maxLength: 32, numeric: true }, + { name: "gasPrice", maxLength: 32, numeric: true }, + { name: "gasLimit", maxLength: 32, numeric: true }, { name: "to", length: 20 }, - { name: "value", maxLength: 32 }, + { name: "value", maxLength: 32, numeric: true }, { name: "data" }, ]; @@ -89,7 +89,9 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur transactionFields.forEach(function(fieldInfo) { let value = (transaction)[fieldInfo.name] || ([]); - value = arrayify(hexlify(value)); + const options: DataOptions = { }; + if (fieldInfo.numeric) { options.hexPad = "left"; } + value = arrayify(hexlify(value, options)); // Fixed-width field if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {