Safer transaction serialization, matching signature.v with chainId (#708).
This commit is contained in:
parent
15bb840907
commit
edb7c5da91
@ -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, DataOptions, hexDataSlice, hexlify, hexZeroPad, SignatureLike, splitSignature, stripZeros, } from "@ethersproject/bytes";
|
import { arrayify, BytesLike, DataOptions, hexDataSlice, hexlify, hexZeroPad, isBytesLike, 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";
|
||||||
@ -109,17 +109,30 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur
|
|||||||
raw.push(hexlify(value));
|
raw.push(hexlify(value));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (transaction.chainId != null && transaction.chainId !== 0) {
|
let chainId = 0;
|
||||||
raw.push(hexlify(transaction.chainId));
|
if (transaction.chainId != null) {
|
||||||
|
// A chainId was provided; if non-zero we'll use EIP-155
|
||||||
|
chainId = transaction.chainId;
|
||||||
|
|
||||||
|
if (typeof(chainId) !== "number") {
|
||||||
|
logger.throwArgumentError("invalid transaction.chainId", "transaction", transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (signature && !isBytesLike(signature) && signature.v > 28) {
|
||||||
|
// No chainId provided, but the signature is signing with EIP-155; derive chainId
|
||||||
|
chainId = Math.floor((signature.v - 35) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have an EIP-155 transaction (chainId was specified and non-zero)
|
||||||
|
if (chainId !== 0) {
|
||||||
|
raw.push(hexlify(chainId));
|
||||||
raw.push("0x");
|
raw.push("0x");
|
||||||
raw.push("0x");
|
raw.push("0x");
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsignedTransaction = RLP.encode(raw);
|
|
||||||
|
|
||||||
// Requesting an unsigned transation
|
// Requesting an unsigned transation
|
||||||
if (!signature) {
|
if (!signature) {
|
||||||
return unsignedTransaction;
|
return RLP.encode(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The splitSignature will ensure the transaction has a recoveryParam in the
|
// The splitSignature will ensure the transaction has a recoveryParam in the
|
||||||
@ -128,11 +141,18 @@ export function serialize(transaction: UnsignedTransaction, signature?: Signatur
|
|||||||
|
|
||||||
// We pushed a chainId and null r, s on for hashing only; remove those
|
// We pushed a chainId and null r, s on for hashing only; remove those
|
||||||
let v = 27 + sig.recoveryParam
|
let v = 27 + sig.recoveryParam
|
||||||
if (raw.length === 9) {
|
if (chainId !== 0) {
|
||||||
raw.pop();
|
raw.pop();
|
||||||
raw.pop();
|
raw.pop();
|
||||||
raw.pop();
|
raw.pop();
|
||||||
v += transaction.chainId * 2 + 8;
|
v += chainId * 2 + 8;
|
||||||
|
|
||||||
|
// If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it!
|
||||||
|
if (sig.v > 28 && sig.v !== v) {
|
||||||
|
logger.throwArgumentError("transaction.chainId/signature.v mismatch", "signature", signature);
|
||||||
|
}
|
||||||
|
} else if (sig.v !== v) {
|
||||||
|
logger.throwArgumentError("transaction.chainId/signature.v mismatch", "signature", signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
raw.push(hexlify(v));
|
raw.push(hexlify(v));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user