1
1
"use strict" ;
2
2
3
- import { BlockTag , Provider , TransactionRequest , TransactionResponse } from "@ethersproject/abstract-provider" ;
3
+ import { BlockTag , FeeData , Provider , TransactionRequest , TransactionResponse } from "@ethersproject/abstract-provider" ;
4
4
import { BigNumber , BigNumberish } from "@ethersproject/bignumber" ;
5
5
import { Bytes , BytesLike } from "@ethersproject/bytes" ;
6
6
import { Deferrable , defineReadOnly , resolveProperties , shallowCopy } from "@ethersproject/properties" ;
@@ -19,12 +19,6 @@ const forwardErrors = [
19
19
Logger . errors . REPLACEMENT_UNDERPRICED ,
20
20
] ;
21
21
22
- export interface FeeData {
23
- maxFeePerGas : null | BigNumber ;
24
- maxPriorityFeePerGas : null | BigNumber ;
25
- gasPrice : null | BigNumber ;
26
- }
27
-
28
22
// EIP-712 Typed Data
29
23
// See: https://eips.ethereum.org/EIPS/eip-712
30
24
@@ -146,21 +140,8 @@ export abstract class Signer {
146
140
}
147
141
148
142
async getFeeData ( ) : Promise < FeeData > {
149
- this . _checkProvider ( "getFeeStats" ) ;
150
-
151
- const { block, gasPrice } = await resolveProperties ( {
152
- block : this . provider . getBlock ( - 1 ) ,
153
- gasPrice : this . provider . getGasPrice ( )
154
- } ) ;
155
-
156
- let maxFeePerGas = null , maxPriorityFeePerGas = null ;
157
-
158
- if ( block && block . baseFee ) {
159
- maxFeePerGas = block . baseFee . mul ( 2 ) ;
160
- maxPriorityFeePerGas = BigNumber . from ( "1000000000" ) ;
161
- }
162
-
163
- return { maxFeePerGas, maxPriorityFeePerGas, gasPrice } ;
143
+ this . _checkProvider ( "getFeeData" ) ;
144
+ return await this . provider . getFeeData ( ) ;
164
145
}
165
146
166
147
@@ -230,26 +211,23 @@ export abstract class Signer {
230
211
} ) ;
231
212
}
232
213
233
- if ( ( tx . type === 2 || tx . type == null ) && ( tx . maxFeePerGas != null && tx . maxPriorityFeePerGas != null ) ) {
234
- // Fully-formed EIP-1559 transaction
235
-
236
- // Check the gasPrice == maxFeePerGas
237
- if ( tx . gasPrice != null && ! BigNumber . from ( tx . gasPrice ) . eq ( < BigNumberish > ( tx . maxFeePerGas ) ) ) {
238
- logger . throwArgumentError ( "gasPrice/maxFeePerGas mismatch " , "transaction" , transaction ) ;
239
- }
214
+ // Do not allow mixing pre-eip-1559 and eip-1559 proerties
215
+ const hasEip1559 = ( tx . maxFeePerGas != null || tx . maxPriorityFeePerGas != null ) ;
216
+ if ( tx . gasPrice != null && ( tx . type === 2 || hasEip1559 ) ) {
217
+ logger . throwArgumentError ( "eip-1559 transaction do not support gasPrice" , "transaction" , transaction ) ;
218
+ } else if ( ( tx . type === - 1 || tx . type === 1 ) && hasEip1559 ) {
219
+ logger . throwArgumentError ( "pre-eip-1559 transaction do not support maxFeePerGas/maxPriorityFeePerGas " , "transaction" , transaction ) ;
220
+ }
240
221
222
+ if ( ( tx . type === 2 || tx . type == null ) && ( tx . maxFeePerGas != null && tx . maxPriorityFeePerGas != null ) ) {
223
+ // Fully-formed EIP-1559 transaction (skip getFeeData)
241
224
tx . type = 2 ;
242
225
243
226
} else if ( tx . type === - 1 || tx . type === 1 ) {
244
- // Explicit EIP-2930 or Legacy transaction
245
-
246
- // Do not allow EIP-1559 properties
247
- if ( tx . maxFeePerGas != null || tx . maxPriorityFeePerGas != null ) {
248
- logger . throwArgumentError ( `transaction type ${ tx . type } does not support eip-1559 keys` , "transaction" , transaction ) ;
249
- }
227
+ // Explicit Legacy or EIP-2930 transaction
250
228
229
+ // Populate missing gasPrice
251
230
if ( tx . gasPrice == null ) { tx . gasPrice = this . getGasPrice ( ) ; }
252
- tx . type = ( tx . accessList ? 1 : - 1 ) ;
253
231
254
232
} else {
255
233
@@ -262,23 +240,19 @@ export abstract class Signer {
262
240
if ( feeData . maxFeePerGas != null && feeData . maxPriorityFeePerGas != null ) {
263
241
// The network supports EIP-1559!
264
242
265
- if ( tx . gasPrice != null && tx . maxFeePerGas == null && tx . maxPriorityFeePerGas == null ) {
266
- // Legacy or EIP-2930 transaction, but without its type set
267
- tx . type = ( tx . accessList ? 1 : - 1 ) ;
243
+ // Upgrade transaction from null to eip-1559
244
+ tx . type = 2 ;
245
+
246
+ if ( tx . gasPrice != null ) {
247
+ // Using legacy gasPrice property on an eip-1559 network,
248
+ // so use gasPrice as both fee properties
249
+ const gasPrice = tx . gasPrice ;
250
+ delete tx . gasPrice ;
251
+ tx . maxFeePerGas = gasPrice ;
252
+ tx . maxPriorityFeePerGas = gasPrice ;
268
253
269
254
} else {
270
- // Use EIP-1559; no gas price or one EIP-1559 property was specified
271
-
272
- // Check that gasPrice == maxFeePerGas
273
- if ( tx . gasPrice != null ) {
274
- // The first condition fails only if gasPrice and maxPriorityFeePerGas
275
- // were specified, which is a weird thing to do
276
- if ( tx . maxFeePerGas == null || ! BigNumber . from ( tx . gasPrice ) . eq ( < BigNumberish > ( tx . maxFeePerGas ) ) ) {
277
- logger . throwArgumentError ( "gasPrice/maxFeePerGas mismatch" , "transaction" , transaction ) ;
278
- }
279
- }
280
-
281
- tx . type = 2 ;
255
+ // Populate missing fee data
282
256
if ( tx . maxFeePerGas == null ) { tx . maxFeePerGas = feeData . maxFeePerGas ; }
283
257
if ( tx . maxPriorityFeePerGas == null ) { tx . maxPriorityFeePerGas = feeData . maxPriorityFeePerGas ; }
284
258
}
@@ -287,14 +261,17 @@ export abstract class Signer {
287
261
// Network doesn't support EIP-1559...
288
262
289
263
// ...but they are trying to use EIP-1559 properties
290
- if ( tx . maxFeePerGas != null || tx . maxPriorityFeePerGas != null ) {
264
+ if ( hasEip1559 ) {
291
265
logger . throwError ( "network does not support EIP-1559" , Logger . errors . UNSUPPORTED_OPERATION , {
292
266
operation : "populateTransaction"
293
267
} ) ;
294
268
}
295
269
296
- tx . gasPrice = feeData . gasPrice ;
297
- tx . type = ( tx . accessList ? 1 : - 1 ) ;
270
+ // Populate missing fee data
271
+ if ( tx . gasPrice == null ) { tx . gasPrice = feeData . gasPrice ; }
272
+
273
+ // Explicitly set untyped transaction to legacy
274
+ tx . type = - 1 ;
298
275
299
276
} else {
300
277
// getFeeData has failed us.
@@ -306,11 +283,7 @@ export abstract class Signer {
306
283
} else if ( tx . type === 2 ) {
307
284
// Explicitly using EIP-1559
308
285
309
- // Check gasPrice == maxFeePerGas
310
- if ( tx . gasPrice != null && ! BigNumber . from ( tx . gasPrice ) . eq ( < BigNumberish > ( tx . maxFeePerGas ) ) ) {
311
- logger . throwArgumentError ( "gasPrice/maxFeePerGas mismatch" , "transaction" , transaction ) ;
312
- }
313
-
286
+ // Populate missing fee data
314
287
if ( tx . maxFeePerGas == null ) { tx . maxFeePerGas = feeData . maxFeePerGas ; }
315
288
if ( tx . maxPriorityFeePerGas == null ) { tx . maxPriorityFeePerGas = feeData . maxPriorityFeePerGas ; }
316
289
}
0 commit comments