Allow numeric values in a transaction to be odd-lengthed hexstrings (#614).

This commit is contained in:
Richard Moore 2019-09-27 21:54:10 -04:00
parent 828c8cfd41
commit a12030ad29
No known key found for this signature in database
GPG Key ID: 665176BE8E9DC651
3 changed files with 37 additions and 12 deletions

@ -13,7 +13,7 @@ export type BytesLike = Bytes | string;
export type DataOptions = { export type DataOptions = {
allowMissingPrefix?: boolean; allowMissingPrefix?: boolean;
allowOddLength?: boolean; hexPad?: "left" | "right" | null;
}; };
export interface Hexable { export interface Hexable {
@ -112,9 +112,15 @@ export function arrayify(value: BytesLike | Hexable | number, options?: DataOpti
if (isHexString(value)) { if (isHexString(value)) {
let hex = (<string>value).substring(2); let hex = (<string>value).substring(2);
if (!options.allowOddLength && hex.length % 2) { 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); logger.throwArgumentError("hex data is odd-length", "value", value);
} }
}
let result = []; let result = [];
for (let i = 0; i < hex.length; i += 2) { for (let i = 0; i < hex.length; i += 2) {
@ -212,9 +218,15 @@ export function hexlify(value: BytesLike | Hexable | number, options?: DataOptio
if (isHexable(value)) { return value.toHexString(); } if (isHexable(value)) { return value.toHexString(); }
if (isHexString(value)) { if (isHexString(value)) {
if (!options.allowOddLength && (<string>value).length % 2) { if ((<string>value).length % 2) {
if (options.hexPad === "left") {
value = "0x0" + (<string>value).substring(2);
} else if (options.hexPad === "right") {
value += "0";
} else {
logger.throwArgumentError("hex data is odd-length", "value", value); logger.throwArgumentError("hex data is odd-length", "value", value);
} }
}
return (<string>value).toLowerCase(); return (<string>value).toLowerCase();
} }
@ -273,7 +285,7 @@ export function hexConcat(items: Array<BytesLike>): string {
} }
export function hexValue(value: BytesLike | Hexable | number): 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"; } if (trimmed === "0x") { return "0x0"; }
return trimmed; return trimmed;
} }

@ -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);
});
});

@ -2,7 +2,7 @@
import { getAddress } from "@ethersproject/address"; import { getAddress } from "@ethersproject/address";
import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; 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 { Zero } from "@ethersproject/constants";
import { keccak256 } from "@ethersproject/keccak256"; import { keccak256 } from "@ethersproject/keccak256";
import { checkProperties } from "@ethersproject/properties"; import { checkProperties } from "@ethersproject/properties";
@ -60,11 +60,11 @@ function handleNumber(value: string): BigNumber {
} }
const transactionFields = [ const transactionFields = [
{ name: "nonce", maxLength: 32 }, { name: "nonce", maxLength: 32, numeric: true },
{ name: "gasPrice", maxLength: 32 }, { name: "gasPrice", maxLength: 32, numeric: true },
{ name: "gasLimit", maxLength: 32 }, { name: "gasLimit", maxLength: 32, numeric: true },
{ name: "to", length: 20 }, { name: "to", length: 20 },
{ name: "value", maxLength: 32 }, { name: "value", maxLength: 32, numeric: true },
{ name: "data" }, { name: "data" },
]; ];
@ -89,7 +89,9 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur
transactionFields.forEach(function(fieldInfo) { transactionFields.forEach(function(fieldInfo) {
let value = (<any>transaction)[fieldInfo.name] || ([]); let value = (<any>transaction)[fieldInfo.name] || ([]);
value = arrayify(hexlify(value)); const options: DataOptions = { };
if (fieldInfo.numeric) { options.hexPad = "left"; }
value = arrayify(hexlify(value, options));
// Fixed-width field // Fixed-width field
if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) { if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {