Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src.ts/contract/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract
operation: "sendTransaction" });

const sentTx = await this.runner.sendTransaction(tx);
const address = getCreateAddress(sentTx);
const deployNonce = sentTx.nonce;
assertArgument(deployNonce != null,
"cannot compute CREATE address without transaction nonce; try again after the RPC returns a full transaction payload",
"sentTx.nonce", sentTx.nonce);
const address = getCreateAddress({ from: sentTx.from, nonce: deployNonce });
return new (<any>BaseContract)(address, this.interface, this.runner, sentTx);
}

Expand Down
15 changes: 13 additions & 2 deletions src.ts/providers/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ export function formatUint256(value: any): string {
return zeroPadValue(value, 32);
}

// Some nodes omit nonce or return non-numeric placeholder strings (e.g.
// "undefined"); return null instead of throwing when parsing the response.
function formatTransactionNonce(value: any): null | number {
if (value == null) { return null; }
if (typeof(value) === "string") {
const t = value.trim();
if (t === "" || t === "undefined" || t === "null") { return null; }
}
return getNumber(value);
}

const _formatLog = object({
address: getAddress,
blockHash: formatHash,
Expand Down Expand Up @@ -253,7 +264,7 @@ export function formatTransactionResponse(value: any): TransactionResponseParams
gasLimit: getBigInt,
to: allowNull(getAddress, null),
value: getBigInt,
nonce: getNumber,
nonce: formatTransactionNonce,
data: formatData,

creates: allowNull(getAddress, null),
Expand All @@ -266,7 +277,7 @@ export function formatTransactionResponse(value: any): TransactionResponseParams
})(value);

// If to and creates are empty, populate the creates from the value
if (result.to == null && result.creates == null) {
if (result.to == null && result.creates == null && result.nonce != null) {
result.creates = getCreateAddress(result);
}

Expand Down
5 changes: 4 additions & 1 deletion src.ts/providers/formatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,11 @@ export interface TransactionResponseParams {

/**
* The nonce of the transaction, used for replay protection.
*
* May be ``null`` when the backend omits or returns an unusable
* ``nonce`` field.
*/
nonce: number;
nonce: null | number;

/**
* The maximum amount of gas this transaction is authorized to consume.
Expand Down
10 changes: 6 additions & 4 deletions src.ts/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1326,8 +1326,10 @@ export class TransactionResponse implements TransactionLike<string>, Transaction
*
* When sending a transaction, this must be equal to the number of
* transactions ever sent by [[from]].
*
* May be ``null`` if the node did not return a valid nonce.
*/
readonly nonce!: number;
readonly nonce!: null | number;

/**
* The maximum units of gas this transaction can consume. If execution
Expand Down Expand Up @@ -1425,7 +1427,7 @@ export class TransactionResponse implements TransactionLike<string>, Transaction
this.to = tx.to || null;

this.gasLimit = tx.gasLimit;
this.nonce = tx.nonce;
this.nonce = tx.nonce ?? null;
this.data = tx.data;
this.value = tx.value;

Expand Down Expand Up @@ -1543,7 +1545,7 @@ export class TransactionResponse implements TransactionLike<string>, Transaction

// No transaction or our nonce has not been mined yet; but we
// can start scanning later when we do start
if (nonce < this.nonce) {
if (this.nonce != null && nonce < this.nonce) {
startBlock = blockNumber;
return;
}
Expand Down Expand Up @@ -1578,7 +1580,7 @@ export class TransactionResponse implements TransactionLike<string>, Transaction
for (let i = 0; i < block.length; i++) {
const tx: TransactionResponse = await block.getTransaction(i);

if (tx.from === this.from && tx.nonce === this.nonce) {
if (this.nonce != null && tx.from === this.from && tx.nonce === this.nonce) {
// Get the receipt
if (stopScanning) { return null; }
const receipt = await this.provider.getTransactionReceipt(tx.hash);
Expand Down