Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
a8c9cd67
Unverified
Commit
a8c9cd67
authored
Aug 05, 2021
by
Karl Floersch
Committed by
GitHub
Aug 05, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1024 from ethereum-optimism/fix/broken-estimate-gas-when-pending-tx-in-mempool
fix: estimate gas when pending tx in mempool
parents
6702ce41
e2985bf7
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
411 additions
and
242 deletions
+411
-242
silent-dolphins-hammer.md
.changeset/silent-dolphins-hammer.md
+5
-0
batch-submitter.ts
...es/batch-submitter/src/batch-submitter/batch-submitter.ts
+34
-66
state-batch-submitter.ts
...ch-submitter/src/batch-submitter/state-batch-submitter.ts
+21
-35
tx-batch-submitter.ts
...batch-submitter/src/batch-submitter/tx-batch-submitter.ts
+38
-59
run-batch-submitter.ts
packages/batch-submitter/src/exec/run-batch-submitter.ts
+25
-7
index.ts
packages/batch-submitter/src/index.ts
+1
-0
transaction-chain-contract.ts
packages/batch-submitter/src/transaction-chain-contract.ts
+31
-15
index.ts
packages/batch-submitter/src/utils/index.ts
+1
-0
tx-submission.ts
packages/batch-submitter/src/utils/tx-submission.ts
+94
-0
batch-submitter.spec.ts
...ch-submitter/test/batch-submitter/batch-submitter.spec.ts
+30
-60
tx-submission.spec.ts
packages/batch-submitter/test/utils/tx-submission.spec.ts
+131
-0
No files found.
.changeset/silent-dolphins-hammer.md
0 → 100644
View file @
a8c9cd67
---
'
@eth-optimism/batch-submitter'
:
patch
---
Fix tx resubmission estimateGas bug in batch submitter
packages/batch-submitter/src/batch-submitter/batch-submitter.ts
View file @
a8c9cd67
/* External Imports */
/* External Imports */
import
{
Contract
,
Signer
,
utils
,
providers
}
from
'
ethers
'
import
{
import
{
TransactionReceipt
}
from
'
@ethersproject/abstract-provider
'
Contract
,
Signer
,
utils
,
providers
,
PopulatedTransaction
,
}
from
'
ethers
'
import
{
TransactionReceipt
,
TransactionResponse
,
}
from
'
@ethersproject/abstract-provider
'
import
{
Gauge
,
Histogram
,
Counter
}
from
'
prom-client
'
import
{
Gauge
,
Histogram
,
Counter
}
from
'
prom-client
'
import
*
as
ynatm
from
'
@eth-optimism/ynatm
'
import
{
RollupInfo
,
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
RollupInfo
,
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
Logger
,
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
Logger
,
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
getContractFactory
}
from
'
old-contracts
'
import
{
getContractFactory
}
from
'
old-contracts
'
/* Internal Imports */
import
{
TxSubmissionHooks
}
from
'
..
'
export
interface
BlockRange
{
export
interface
BlockRange
{
start
:
number
start
:
number
end
:
number
end
:
number
}
}
export
interface
ResubmissionConfig
{
resubmissionTimeout
:
number
minGasPriceInGwei
:
number
maxGasPriceInGwei
:
number
gasRetryIncrement
:
number
}
interface
BatchSubmitterMetrics
{
interface
BatchSubmitterMetrics
{
batchSubmitterETHBalance
:
Gauge
<
string
>
batchSubmitterETHBalance
:
Gauge
<
string
>
...
@@ -49,10 +53,6 @@ export abstract class BatchSubmitter {
...
@@ -49,10 +53,6 @@ export abstract class BatchSubmitter {
readonly
finalityConfirmations
:
number
,
readonly
finalityConfirmations
:
number
,
readonly
addressManagerAddress
:
string
,
readonly
addressManagerAddress
:
string
,
readonly
minBalanceEther
:
number
,
readonly
minBalanceEther
:
number
,
readonly
minGasPriceInGwei
:
number
,
readonly
maxGasPriceInGwei
:
number
,
readonly
gasRetryIncrement
:
number
,
readonly
gasThresholdInGwei
:
number
,
readonly
blockOffset
:
number
,
readonly
blockOffset
:
number
,
readonly
logger
:
Logger
,
readonly
logger
:
Logger
,
readonly
defaultMetrics
:
Metrics
readonly
defaultMetrics
:
Metrics
...
@@ -190,69 +190,37 @@ export abstract class BatchSubmitter {
...
@@ -190,69 +190,37 @@ export abstract class BatchSubmitter {
return
true
return
true
}
}
public
static
async
getReceiptWithResubmission
(
protected
_makeHooks
(
txName
:
string
):
TxSubmissionHooks
{
txFunc
:
(
gasPrice
)
=>
Promise
<
TransactionReceipt
>
,
return
{
resubmissionConfig
:
ResubmissionConfig
,
beforeSendTransaction
:
(
tx
:
PopulatedTransaction
)
=>
{
logger
:
Logger
this
.
logger
.
info
(
`Submitting
${
txName
}
transaction`
,
{
):
Promise
<
TransactionReceipt
>
{
gasPrice
:
tx
.
gasPrice
,
const
{
nonce
:
tx
.
nonce
,
resubmissionTimeout
,
contractAddr
:
this
.
chainContract
.
address
,
minGasPriceInGwei
,
})
maxGasPriceInGwei
,
},
gasRetryIncrement
,
onTransactionResponse
:
(
txResponse
:
TransactionResponse
)
=>
{
}
=
resubmissionConfig
this
.
logger
.
info
(
`Submitted
${
txName
}
transaction`
,
{
txHash
:
txResponse
.
hash
,
const
receipt
=
await
ynatm
.
send
({
from
:
txResponse
.
from
,
sendTransactionFunction
:
txFunc
,
})
minGasPrice
:
ynatm
.
toGwei
(
minGasPriceInGwei
),
this
.
logger
.
debug
(
`
${
txName
}
transaction data`
,
{
maxGasPrice
:
ynatm
.
toGwei
(
maxGasPriceInGwei
),
data
:
txResponse
.
data
,
gasPriceScalingFunction
:
ynatm
.
LINEAR
(
gasRetryIncrement
),
})
delay
:
resubmissionTimeout
,
},
})
logger
.
debug
(
'
Resubmission tx receipt
'
,
{
receipt
})
return
receipt
}
private
async
_getMinGasPriceInGwei
():
Promise
<
number
>
{
if
(
this
.
minGasPriceInGwei
!==
0
)
{
return
this
.
minGasPriceInGwei
}
let
minGasPriceInGwei
=
parseInt
(
utils
.
formatUnits
(
await
this
.
signer
.
getGasPrice
(),
'
gwei
'
),
10
)
if
(
minGasPriceInGwei
>
this
.
maxGasPriceInGwei
)
{
this
.
logger
.
warn
(
'
Minimum gas price is higher than max! Ethereum must be congested...
'
)
minGasPriceInGwei
=
this
.
maxGasPriceInGwei
}
}
return
minGasPriceInGwei
}
}
protected
async
_submitAndLogTx
(
protected
async
_submitAndLogTx
(
txFunc
:
(
gasPrice
)
=>
Promise
<
TransactionReceipt
>
,
submitTransaction
:
(
)
=>
Promise
<
TransactionReceipt
>
,
successMessage
:
string
successMessage
:
string
):
Promise
<
TransactionReceipt
>
{
):
Promise
<
TransactionReceipt
>
{
this
.
lastBatchSubmissionTimestamp
=
Date
.
now
()
this
.
lastBatchSubmissionTimestamp
=
Date
.
now
()
this
.
logger
.
debug
(
'
Waiting for receipt...
'
)
this
.
logger
.
debug
(
'
Submitting transaction & waiting for receipt...
'
)
const
resubmissionConfig
:
ResubmissionConfig
=
{
resubmissionTimeout
:
this
.
resubmissionTimeout
,
minGasPriceInGwei
:
await
this
.
_getMinGasPriceInGwei
(),
maxGasPriceInGwei
:
this
.
maxGasPriceInGwei
,
gasRetryIncrement
:
this
.
gasRetryIncrement
,
}
let
receipt
:
TransactionReceipt
let
receipt
:
TransactionReceipt
try
{
try
{
receipt
=
await
BatchSubmitter
.
getReceiptWithResubmission
(
receipt
=
await
submitTransaction
()
txFunc
,
resubmissionConfig
,
this
.
logger
)
}
catch
(
err
)
{
}
catch
(
err
)
{
this
.
metrics
.
failedSubmissions
.
inc
()
this
.
metrics
.
failedSubmissions
.
inc
()
if
(
err
.
reason
)
{
if
(
err
.
reason
)
{
...
...
packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts
View file @
a8c9cd67
...
@@ -13,6 +13,7 @@ import { Logger, Metrics } from '@eth-optimism/common-ts'
...
@@ -13,6 +13,7 @@ import { Logger, Metrics } from '@eth-optimism/common-ts'
/* Internal Imports */
/* Internal Imports */
import
{
BlockRange
,
BatchSubmitter
}
from
'
.
'
import
{
BlockRange
,
BatchSubmitter
}
from
'
.
'
import
{
TransactionSubmitter
}
from
'
../utils
'
export
class
StateBatchSubmitter
extends
BatchSubmitter
{
export
class
StateBatchSubmitter
extends
BatchSubmitter
{
// TODO: Change this so that we calculate start = scc.totalElements() and end = ctc.totalElements()!
// TODO: Change this so that we calculate start = scc.totalElements() and end = ctc.totalElements()!
...
@@ -23,6 +24,7 @@ export class StateBatchSubmitter extends BatchSubmitter {
...
@@ -23,6 +24,7 @@ export class StateBatchSubmitter extends BatchSubmitter {
protected
syncing
:
boolean
protected
syncing
:
boolean
protected
ctcContract
:
Contract
protected
ctcContract
:
Contract
private
fraudSubmissionAddress
:
string
private
fraudSubmissionAddress
:
string
private
transactionSubmitter
:
TransactionSubmitter
constructor
(
constructor
(
signer
:
Signer
,
signer
:
Signer
,
...
@@ -36,10 +38,7 @@ export class StateBatchSubmitter extends BatchSubmitter {
...
@@ -36,10 +38,7 @@ export class StateBatchSubmitter extends BatchSubmitter {
finalityConfirmations
:
number
,
finalityConfirmations
:
number
,
addressManagerAddress
:
string
,
addressManagerAddress
:
string
,
minBalanceEther
:
number
,
minBalanceEther
:
number
,
minGasPriceInGwei
:
number
,
transactionSubmitter
:
TransactionSubmitter
,
maxGasPriceInGwei
:
number
,
gasRetryIncrement
:
number
,
gasThresholdInGwei
:
number
,
blockOffset
:
number
,
blockOffset
:
number
,
logger
:
Logger
,
logger
:
Logger
,
metrics
:
Metrics
,
metrics
:
Metrics
,
...
@@ -57,15 +56,12 @@ export class StateBatchSubmitter extends BatchSubmitter {
...
@@ -57,15 +56,12 @@ export class StateBatchSubmitter extends BatchSubmitter {
finalityConfirmations
,
finalityConfirmations
,
addressManagerAddress
,
addressManagerAddress
,
minBalanceEther
,
minBalanceEther
,
minGasPriceInGwei
,
maxGasPriceInGwei
,
gasRetryIncrement
,
gasThresholdInGwei
,
blockOffset
,
blockOffset
,
logger
,
logger
,
metrics
metrics
)
)
this
.
fraudSubmissionAddress
=
fraudSubmissionAddress
this
.
fraudSubmissionAddress
=
fraudSubmissionAddress
this
.
transactionSubmitter
=
transactionSubmitter
}
}
/*****************************
/*****************************
...
@@ -159,14 +155,14 @@ export class StateBatchSubmitter extends BatchSubmitter {
...
@@ -159,14 +155,14 @@ export class StateBatchSubmitter extends BatchSubmitter {
endBlock
:
number
endBlock
:
number
):
Promise
<
TransactionReceipt
>
{
):
Promise
<
TransactionReceipt
>
{
const
batch
=
await
this
.
_generateStateCommitmentBatch
(
startBlock
,
endBlock
)
const
batch
=
await
this
.
_generateStateCommitmentBatch
(
startBlock
,
endBlock
)
const
tx
=
this
.
chainContract
.
interface
.
encodeFunctionData
(
const
calldata
=
this
.
chainContract
.
interface
.
encodeFunctionData
(
'
appendStateBatch
'
,
'
appendStateBatch
'
,
[
batch
,
startBlock
]
[
batch
,
startBlock
]
)
)
const
batchSizeInBytes
=
remove0x
(
tx
).
length
/
2
const
batchSizeInBytes
=
remove0x
(
calldata
).
length
/
2
this
.
logger
.
debug
(
'
State batch generated
'
,
{
this
.
logger
.
debug
(
'
State batch generated
'
,
{
batchSizeInBytes
,
batchSizeInBytes
,
tx
,
calldata
,
})
})
if
(
!
this
.
_shouldSubmitBatch
(
batchSizeInBytes
))
{
if
(
!
this
.
_shouldSubmitBatch
(
batchSizeInBytes
))
{
...
@@ -174,33 +170,23 @@ export class StateBatchSubmitter extends BatchSubmitter {
...
@@ -174,33 +170,23 @@ export class StateBatchSubmitter extends BatchSubmitter {
}
}
const
offsetStartsAtIndex
=
startBlock
-
this
.
blockOffset
const
offsetStartsAtIndex
=
startBlock
-
this
.
blockOffset
this
.
logger
.
debug
(
'
Submitting batch.
'
,
{
tx
})
this
.
logger
.
debug
(
'
Submitting batch.
'
,
{
calldata
})
const
nonce
=
await
this
.
signer
.
getTransactionCount
()
// Generate the transaction we will repeatedly submit
const
contractFunction
=
async
(
gasPrice
):
Promise
<
TransactionReceipt
>
=>
{
const
tx
=
await
this
.
chainContract
.
populateTransaction
.
appendStateBatch
(
this
.
logger
.
info
(
'
Submitting appendStateBatch transaction
'
,
{
batch
,
gasPrice
,
offsetStartsAtIndex
nonce
,
)
contractAddr
:
this
.
chainContract
.
address
,
const
submitTransaction
=
():
Promise
<
TransactionReceipt
>
=>
{
})
return
this
.
transactionSubmitter
.
submitTransaction
(
const
contractTx
=
await
this
.
chainContract
.
appendStateBatch
(
tx
,
batch
,
this
.
_makeHooks
(
'
appendStateBatch
'
)
offsetStartsAtIndex
,
{
nonce
,
gasPrice
}
)
this
.
logger
.
info
(
'
Submitted appendStateBatch transaction
'
,
{
txHash
:
contractTx
.
hash
,
from
:
contractTx
.
from
,
})
this
.
logger
.
debug
(
'
appendStateBatch transaction data
'
,
{
data
:
contractTx
.
data
,
})
return
this
.
signer
.
provider
.
waitForTransaction
(
contractTx
.
hash
,
this
.
numConfirmations
)
)
}
}
return
this
.
_submitAndLogTx
(
contractFunction
,
'
Submitted state root batch!
'
)
return
this
.
_submitAndLogTx
(
submitTransaction
,
'
Submitted state root batch!
'
)
}
}
/*********************
/*********************
...
...
packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts
View file @
a8c9cd67
...
@@ -22,6 +22,7 @@ import {
...
@@ -22,6 +22,7 @@ import {
}
from
'
../transaction-chain-contract
'
}
from
'
../transaction-chain-contract
'
import
{
BlockRange
,
BatchSubmitter
}
from
'
.
'
import
{
BlockRange
,
BatchSubmitter
}
from
'
.
'
import
{
TransactionSubmitter
}
from
'
../utils
'
export
interface
AutoFixBatchOptions
{
export
interface
AutoFixBatchOptions
{
fixDoublePlayedDeposits
:
boolean
fixDoublePlayedDeposits
:
boolean
...
@@ -35,6 +36,8 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
...
@@ -35,6 +36,8 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
protected
syncing
:
boolean
protected
syncing
:
boolean
private
disableQueueBatchAppend
:
boolean
private
disableQueueBatchAppend
:
boolean
private
autoFixBatchOptions
:
AutoFixBatchOptions
private
autoFixBatchOptions
:
AutoFixBatchOptions
private
transactionSubmitter
:
TransactionSubmitter
private
gasThresholdInGwei
:
number
constructor
(
constructor
(
signer
:
Signer
,
signer
:
Signer
,
...
@@ -47,10 +50,8 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
...
@@ -47,10 +50,8 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
resubmissionTimeout
:
number
,
resubmissionTimeout
:
number
,
addressManagerAddress
:
string
,
addressManagerAddress
:
string
,
minBalanceEther
:
number
,
minBalanceEther
:
number
,
minGasPriceInGwei
:
number
,
maxGasPriceInGwei
:
number
,
gasRetryIncrement
:
number
,
gasThresholdInGwei
:
number
,
gasThresholdInGwei
:
number
,
transactionSubmitter
:
TransactionSubmitter
,
blockOffset
:
number
,
blockOffset
:
number
,
logger
:
Logger
,
logger
:
Logger
,
metrics
:
Metrics
,
metrics
:
Metrics
,
...
@@ -73,16 +74,14 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
...
@@ -73,16 +74,14 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
0
,
// Supply dummy value because it is not used.
0
,
// Supply dummy value because it is not used.
addressManagerAddress
,
addressManagerAddress
,
minBalanceEther
,
minBalanceEther
,
minGasPriceInGwei
,
maxGasPriceInGwei
,
gasRetryIncrement
,
gasThresholdInGwei
,
blockOffset
,
blockOffset
,
logger
,
logger
,
metrics
metrics
)
)
this
.
disableQueueBatchAppend
=
disableQueueBatchAppend
this
.
disableQueueBatchAppend
=
disableQueueBatchAppend
this
.
autoFixBatchOptions
=
autoFixBatchOptions
this
.
autoFixBatchOptions
=
autoFixBatchOptions
this
.
gasThresholdInGwei
=
gasThresholdInGwei
this
.
transactionSubmitter
=
transactionSubmitter
}
}
/*****************************
/*****************************
...
@@ -140,34 +139,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
...
@@ -140,34 +139,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
)
)
if
(
!
this
.
disableQueueBatchAppend
)
{
if
(
!
this
.
disableQueueBatchAppend
)
{
const
nonce
=
await
this
.
signer
.
getTransactionCount
()
return
this
.
submitAppendQueueBatch
()
const
contractFunction
=
async
(
gasPrice
):
Promise
<
TransactionReceipt
>
=>
{
this
.
logger
.
info
(
'
Submitting appendQueueBatch transaction
'
,
{
gasPrice
,
nonce
,
contractAddr
:
this
.
chainContract
.
address
,
})
const
tx
=
await
this
.
chainContract
.
appendQueueBatch
(
99999999
,
{
nonce
,
gasPrice
,
})
this
.
logger
.
info
(
'
Submitted appendQueueBatch transaction
'
,
{
txHash
:
tx
.
hash
,
from
:
tx
.
from
,
})
this
.
logger
.
debug
(
'
appendQueueBatch transaction data
'
,
{
data
:
tx
.
data
,
})
return
this
.
signer
.
provider
.
waitForTransaction
(
tx
.
hash
,
this
.
numConfirmations
)
}
// Empty the queue with a huge `appendQueueBatch(..)` call
return
this
.
_submitAndLogTx
(
contractFunction
,
'
Cleared queue!
'
)
}
}
}
}
this
.
logger
.
info
(
'
Syncing mode enabled but queue is empty. Skipping...
'
)
this
.
logger
.
info
(
'
Syncing mode enabled but queue is empty. Skipping...
'
)
...
@@ -250,36 +222,43 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
...
@@ -250,36 +222,43 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
l1tipHeight
,
l1tipHeight
,
})
})
const
nonce
=
await
this
.
signer
.
getTransactionCount
()
return
this
.
submitAppendSequencerBatch
(
batchParams
)
const
contractFunction
=
async
(
gasPrice
):
Promise
<
TransactionReceipt
>
=>
{
this
.
logger
.
info
(
'
Submitting appendSequencerBatch transaction
'
,
{
gasPrice
,
nonce
,
contractAddr
:
this
.
chainContract
.
address
,
})
const
tx
=
await
this
.
chainContract
.
appendSequencerBatch
(
batchParams
,
{
nonce
,
gasPrice
,
})
this
.
logger
.
info
(
'
Submitted appendSequencerBatch transaction
'
,
{
txHash
:
tx
.
hash
,
from
:
tx
.
from
,
})
this
.
logger
.
debug
(
'
appendSequencerBatch transaction data
'
,
{
data
:
tx
.
data
,
})
return
this
.
signer
.
provider
.
waitForTransaction
(
tx
.
hash
,
this
.
numConfirmations
)
}
return
this
.
_submitAndLogTx
(
contractFunction
,
'
Submitted batch!
'
)
}
}
/*********************
/*********************
* Private Functions *
* Private Functions *
********************/
********************/
private
async
submitAppendQueueBatch
():
Promise
<
TransactionReceipt
>
{
const
tx
=
await
this
.
chainContract
.
populateTransaction
.
appendQueueBatch
(
ethers
.
constants
.
MaxUint256
// Completely empty the queue by appending (up to) an enormous number of queue elements.
)
const
submitTransaction
=
():
Promise
<
TransactionReceipt
>
=>
{
return
this
.
transactionSubmitter
.
submitTransaction
(
tx
,
this
.
_makeHooks
(
'
appendQueueBatch
'
)
)
}
// Empty the queue with a huge `appendQueueBatch(..)` call
return
this
.
_submitAndLogTx
(
submitTransaction
,
'
Cleared queue!
'
)
}
private
async
submitAppendSequencerBatch
(
batchParams
:
AppendSequencerBatchParams
):
Promise
<
TransactionReceipt
>
{
const
tx
=
await
this
.
chainContract
.
customPopulateTransaction
.
appendSequencerBatch
(
batchParams
)
const
submitTransaction
=
():
Promise
<
TransactionReceipt
>
=>
{
return
this
.
transactionSubmitter
.
submitTransaction
(
tx
,
this
.
_makeHooks
(
'
appendSequencerBatch
'
)
)
}
return
this
.
_submitAndLogTx
(
submitTransaction
,
'
Submitted batch!
'
)
}
private
async
_generateSequencerBatchParams
(
private
async
_generateSequencerBatchParams
(
startBlock
:
number
,
startBlock
:
number
,
endBlock
:
number
endBlock
:
number
...
...
packages/batch-submitter/src/exec/run-batch-submitter.ts
View file @
a8c9cd67
...
@@ -16,6 +16,11 @@ import {
...
@@ -16,6 +16,11 @@ import {
STATE_BATCH_SUBMITTER_LOG_TAG
,
STATE_BATCH_SUBMITTER_LOG_TAG
,
TX_BATCH_SUBMITTER_LOG_TAG
,
TX_BATCH_SUBMITTER_LOG_TAG
,
}
from
'
..
'
}
from
'
..
'
import
{
TransactionSubmitter
,
YnatmTransactionSubmitter
,
ResubmissionConfig
,
}
from
'
../utils
'
interface
RequiredEnvVars
{
interface
RequiredEnvVars
{
// The HTTP provider URL for L1.
// The HTTP provider URL for L1.
...
@@ -349,6 +354,18 @@ export const run = async () => {
...
@@ -349,6 +354,18 @@ export const run = async () => {
addressManagerAddress
:
requiredEnvVars
.
ADDRESS_MANAGER_ADDRESS
,
addressManagerAddress
:
requiredEnvVars
.
ADDRESS_MANAGER_ADDRESS
,
})
})
const
resubmissionConfig
:
ResubmissionConfig
=
{
resubmissionTimeout
:
requiredEnvVars
.
RESUBMISSION_TIMEOUT
*
1
_000
,
minGasPriceInGwei
:
MIN_GAS_PRICE_IN_GWEI
,
maxGasPriceInGwei
:
GAS_THRESHOLD_IN_GWEI
,
gasRetryIncrement
:
GAS_RETRY_INCREMENT
,
}
const
txBatchTxSubmitter
:
TransactionSubmitter
=
new
YnatmTransactionSubmitter
(
sequencerSigner
,
resubmissionConfig
,
requiredEnvVars
.
NUM_CONFIRMATIONS
)
const
txBatchSubmitter
=
new
TransactionBatchSubmitter
(
const
txBatchSubmitter
=
new
TransactionBatchSubmitter
(
sequencerSigner
,
sequencerSigner
,
l2Provider
,
l2Provider
,
...
@@ -360,10 +377,8 @@ export const run = async () => {
...
@@ -360,10 +377,8 @@ export const run = async () => {
requiredEnvVars
.
RESUBMISSION_TIMEOUT
*
1
_000
,
requiredEnvVars
.
RESUBMISSION_TIMEOUT
*
1
_000
,
requiredEnvVars
.
ADDRESS_MANAGER_ADDRESS
,
requiredEnvVars
.
ADDRESS_MANAGER_ADDRESS
,
requiredEnvVars
.
SAFE_MINIMUM_ETHER_BALANCE
,
requiredEnvVars
.
SAFE_MINIMUM_ETHER_BALANCE
,
MIN_GAS_PRICE_IN_GWEI
,
MAX_GAS_PRICE_IN_GWEI
,
GAS_RETRY_INCREMENT
,
GAS_THRESHOLD_IN_GWEI
,
GAS_THRESHOLD_IN_GWEI
,
txBatchTxSubmitter
,
BLOCK_OFFSET
,
BLOCK_OFFSET
,
logger
.
child
({
name
:
TX_BATCH_SUBMITTER_LOG_TAG
}),
logger
.
child
({
name
:
TX_BATCH_SUBMITTER_LOG_TAG
}),
metrics
,
metrics
,
...
@@ -371,6 +386,12 @@ export const run = async () => {
...
@@ -371,6 +386,12 @@ export const run = async () => {
autoFixBatchOptions
autoFixBatchOptions
)
)
const
stateBatchTxSubmitter
:
TransactionSubmitter
=
new
YnatmTransactionSubmitter
(
proposerSigner
,
resubmissionConfig
,
requiredEnvVars
.
NUM_CONFIRMATIONS
)
const
stateBatchSubmitter
=
new
StateBatchSubmitter
(
const
stateBatchSubmitter
=
new
StateBatchSubmitter
(
proposerSigner
,
proposerSigner
,
l2Provider
,
l2Provider
,
...
@@ -383,10 +404,7 @@ export const run = async () => {
...
@@ -383,10 +404,7 @@ export const run = async () => {
requiredEnvVars
.
FINALITY_CONFIRMATIONS
,
requiredEnvVars
.
FINALITY_CONFIRMATIONS
,
requiredEnvVars
.
ADDRESS_MANAGER_ADDRESS
,
requiredEnvVars
.
ADDRESS_MANAGER_ADDRESS
,
requiredEnvVars
.
SAFE_MINIMUM_ETHER_BALANCE
,
requiredEnvVars
.
SAFE_MINIMUM_ETHER_BALANCE
,
MIN_GAS_PRICE_IN_GWEI
,
stateBatchTxSubmitter
,
MAX_GAS_PRICE_IN_GWEI
,
GAS_RETRY_INCREMENT
,
GAS_THRESHOLD_IN_GWEI
,
BLOCK_OFFSET
,
BLOCK_OFFSET
,
logger
.
child
({
name
:
STATE_BATCH_SUBMITTER_LOG_TAG
}),
logger
.
child
({
name
:
STATE_BATCH_SUBMITTER_LOG_TAG
}),
metrics
,
metrics
,
...
...
packages/batch-submitter/src/index.ts
View file @
a8c9cd67
export
*
from
'
./batch-submitter
'
export
*
from
'
./batch-submitter
'
export
*
from
'
./utils
'
export
*
from
'
./transaction-chain-contract
'
export
*
from
'
./transaction-chain-contract
'
packages/batch-submitter/src/transaction-chain-contract.ts
View file @
a8c9cd67
/* External Imports */
/* External Imports */
import
{
Contract
,
BigNumber
}
from
'
ethers
'
import
{
Contract
,
ethers
}
from
'
ethers
'
import
{
import
{
TransactionResponse
,
TransactionResponse
,
TransactionRequest
,
TransactionRequest
,
...
@@ -9,7 +9,7 @@ import {
...
@@ -9,7 +9,7 @@ import {
AppendSequencerBatchParams
,
AppendSequencerBatchParams
,
BatchContext
,
BatchContext
,
encodeAppendSequencerBatch
,
encodeAppendSequencerBatch
,
encodeHe
x
,
remove0
x
,
}
from
'
@eth-optimism/core-utils
'
}
from
'
@eth-optimism/core-utils
'
export
{
encodeAppendSequencerBatch
,
BatchContext
,
AppendSequencerBatchParams
}
export
{
encodeAppendSequencerBatch
,
BatchContext
,
AppendSequencerBatchParams
}
...
@@ -19,6 +19,27 @@ export { encodeAppendSequencerBatch, BatchContext, AppendSequencerBatchParams }
...
@@ -19,6 +19,27 @@ export { encodeAppendSequencerBatch, BatchContext, AppendSequencerBatchParams }
* where the `appendSequencerBatch(...)` function uses a specialized encoding for improved efficiency.
* where the `appendSequencerBatch(...)` function uses a specialized encoding for improved efficiency.
*/
*/
export
class
CanonicalTransactionChainContract
extends
Contract
{
export
class
CanonicalTransactionChainContract
extends
Contract
{
public
customPopulateTransaction
=
{
appendSequencerBatch
:
async
(
batch
:
AppendSequencerBatchParams
):
Promise
<
ethers
.
PopulatedTransaction
>
=>
{
const
nonce
=
await
this
.
signer
.
getTransactionCount
()
const
to
=
this
.
address
const
data
=
getEncodedCalldata
(
batch
)
const
gasLimit
=
await
this
.
signer
.
provider
.
estimateGas
({
to
,
from
:
await
this
.
signer
.
getAddress
(),
data
,
})
return
{
nonce
,
to
,
data
,
gasLimit
,
}
},
}
public
async
appendSequencerBatch
(
public
async
appendSequencerBatch
(
batch
:
AppendSequencerBatchParams
,
batch
:
AppendSequencerBatchParams
,
options
?:
TransactionRequest
options
?:
TransactionRequest
...
@@ -31,29 +52,24 @@ export class CanonicalTransactionChainContract extends Contract {
...
@@ -31,29 +52,24 @@ export class CanonicalTransactionChainContract extends Contract {
* Internal Functions *
* Internal Functions *
*********************/
*********************/
const
APPEND_SEQUENCER_BATCH_METHOD_ID
=
'
appendSequencerBatch()
'
const
APPEND_SEQUENCER_BATCH_METHOD_ID
=
keccak256
(
Buffer
.
from
(
'
appendSequencerBatch()
'
)
).
slice
(
2
,
10
)
const
appendSequencerBatch
=
async
(
const
appendSequencerBatch
=
async
(
OVM_CanonicalTransactionChain
:
Contract
,
OVM_CanonicalTransactionChain
:
Contract
,
batch
:
AppendSequencerBatchParams
,
batch
:
AppendSequencerBatchParams
,
options
?:
TransactionRequest
options
?:
TransactionRequest
):
Promise
<
TransactionResponse
>
=>
{
):
Promise
<
TransactionResponse
>
=>
{
const
methodId
=
keccak256
(
Buffer
.
from
(
APPEND_SEQUENCER_BATCH_METHOD_ID
)
).
slice
(
2
,
10
)
const
calldata
=
encodeAppendSequencerBatch
(
batch
)
return
OVM_CanonicalTransactionChain
.
signer
.
sendTransaction
({
return
OVM_CanonicalTransactionChain
.
signer
.
sendTransaction
({
to
:
OVM_CanonicalTransactionChain
.
address
,
to
:
OVM_CanonicalTransactionChain
.
address
,
data
:
'
0x
'
+
methodId
+
calldata
,
data
:
getEncodedCalldata
(
batch
)
,
...
options
,
...
options
,
})
})
}
}
const
encodeBatchContext
=
(
context
:
BatchContext
):
string
=>
{
const
getEncodedCalldata
=
(
batch
:
AppendSequencerBatchParams
):
string
=>
{
return
(
const
methodId
=
APPEND_SEQUENCER_BATCH_METHOD_ID
encodeHex
(
context
.
numSequencedTransactions
,
6
)
+
const
calldata
=
encodeAppendSequencerBatch
(
batch
)
encodeHex
(
context
.
numSubsequentQueueTransactions
,
6
)
+
return
'
0x
'
+
remove0x
(
methodId
)
+
remove0x
(
calldata
)
encodeHex
(
context
.
timestamp
,
10
)
+
encodeHex
(
context
.
blockNumber
,
10
)
)
}
}
packages/batch-submitter/src/utils/index.ts
0 → 100644
View file @
a8c9cd67
export
*
from
'
./tx-submission
'
packages/batch-submitter/src/utils/tx-submission.ts
0 → 100644
View file @
a8c9cd67
import
{
Signer
,
utils
,
ethers
,
PopulatedTransaction
}
from
'
ethers
'
import
{
TransactionReceipt
,
TransactionResponse
,
}
from
'
@ethersproject/abstract-provider
'
import
*
as
ynatm
from
'
@eth-optimism/ynatm
'
export
interface
ResubmissionConfig
{
resubmissionTimeout
:
number
minGasPriceInGwei
:
number
maxGasPriceInGwei
:
number
gasRetryIncrement
:
number
}
export
type
SubmitTransactionFn
=
(
tx
:
PopulatedTransaction
)
=>
Promise
<
TransactionReceipt
>
export
interface
TxSubmissionHooks
{
beforeSendTransaction
:
(
tx
:
PopulatedTransaction
)
=>
void
onTransactionResponse
:
(
txResponse
:
TransactionResponse
)
=>
void
}
const
getGasPriceInGwei
=
async
(
signer
:
Signer
):
Promise
<
number
>
=>
{
return
parseInt
(
ethers
.
utils
.
formatUnits
(
await
signer
.
getGasPrice
(),
'
gwei
'
),
10
)
}
export
const
submitTransactionWithYNATM
=
async
(
tx
:
PopulatedTransaction
,
signer
:
Signer
,
config
:
ResubmissionConfig
,
numConfirmations
:
number
,
hooks
:
TxSubmissionHooks
):
Promise
<
TransactionReceipt
>
=>
{
const
sendTxAndWaitForReceipt
=
async
(
gasPrice
):
Promise
<
TransactionReceipt
>
=>
{
const
fullTx
=
{
...
tx
,
gasPrice
,
}
hooks
.
beforeSendTransaction
(
fullTx
)
const
txResponse
=
await
signer
.
sendTransaction
(
fullTx
)
hooks
.
onTransactionResponse
(
txResponse
)
return
signer
.
provider
.
waitForTransaction
(
txResponse
.
hash
,
numConfirmations
)
}
const
minGasPrice
=
await
getGasPriceInGwei
(
signer
)
const
receipt
=
await
ynatm
.
send
({
sendTransactionFunction
:
sendTxAndWaitForReceipt
,
minGasPrice
:
ynatm
.
toGwei
(
minGasPrice
),
maxGasPrice
:
ynatm
.
toGwei
(
config
.
maxGasPriceInGwei
),
gasPriceScalingFunction
:
ynatm
.
LINEAR
(
config
.
gasRetryIncrement
),
delay
:
config
.
resubmissionTimeout
,
})
return
receipt
}
export
interface
TransactionSubmitter
{
submitTransaction
(
tx
:
PopulatedTransaction
,
hooks
?:
TxSubmissionHooks
):
Promise
<
TransactionReceipt
>
}
export
class
YnatmTransactionSubmitter
implements
TransactionSubmitter
{
constructor
(
readonly
signer
:
Signer
,
readonly
ynatmConfig
:
ResubmissionConfig
,
readonly
numConfirmations
:
number
)
{}
public
async
submitTransaction
(
tx
:
PopulatedTransaction
,
hooks
?:
TxSubmissionHooks
):
Promise
<
TransactionReceipt
>
{
if
(
!
hooks
)
{
hooks
=
{
beforeSendTransaction
:
()
=>
undefined
,
onTransactionResponse
:
()
=>
undefined
,
}
}
return
submitTransactionWithYNATM
(
tx
,
this
.
signer
,
this
.
ynatmConfig
,
this
.
numConfirmations
,
hooks
)
}
}
packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts
View file @
a8c9cd67
...
@@ -27,6 +27,8 @@ import {
...
@@ -27,6 +27,8 @@ import {
TX_BATCH_SUBMITTER_LOG_TAG
,
TX_BATCH_SUBMITTER_LOG_TAG
,
STATE_BATCH_SUBMITTER_LOG_TAG
,
STATE_BATCH_SUBMITTER_LOG_TAG
,
BatchSubmitter
,
BatchSubmitter
,
YnatmTransactionSubmitter
,
ResubmissionConfig
,
}
from
'
../../src
'
}
from
'
../../src
'
import
{
import
{
...
@@ -200,8 +202,19 @@ describe('BatchSubmitter', () => {
...
@@ -200,8 +202,19 @@ describe('BatchSubmitter', () => {
sinon
.
restore
()
sinon
.
restore
()
})
})
const
createBatchSubmitter
=
(
timeout
:
number
):
TransactionBatchSubmitter
=>
const
createBatchSubmitter
=
(
timeout
:
number
):
TransactionBatchSubmitter
=>
{
new
TransactionBatchSubmitter
(
const
resubmissionConfig
:
ResubmissionConfig
=
{
resubmissionTimeout
:
100000
,
minGasPriceInGwei
:
MIN_GAS_PRICE_IN_GWEI
,
maxGasPriceInGwei
:
GAS_THRESHOLD_IN_GWEI
,
gasRetryIncrement
:
GAS_RETRY_INCREMENT
,
}
const
txBatchTxSubmitter
=
new
YnatmTransactionSubmitter
(
sequencer
,
resubmissionConfig
,
1
)
return
new
TransactionBatchSubmitter
(
sequencer
,
sequencer
,
l2Provider
as
any
,
l2Provider
as
any
,
MIN_TX_SIZE
,
MIN_TX_SIZE
,
...
@@ -212,15 +225,14 @@ describe('BatchSubmitter', () => {
...
@@ -212,15 +225,14 @@ describe('BatchSubmitter', () => {
100000
,
100000
,
AddressManager
.
address
,
AddressManager
.
address
,
1
,
1
,
MIN_GAS_PRICE_IN_GWEI
,
MAX_GAS_PRICE_IN_GWEI
,
GAS_RETRY_INCREMENT
,
GAS_THRESHOLD_IN_GWEI
,
GAS_THRESHOLD_IN_GWEI
,
txBatchTxSubmitter
,
1
,
1
,
new
Logger
({
name
:
TX_BATCH_SUBMITTER_LOG_TAG
}),
new
Logger
({
name
:
TX_BATCH_SUBMITTER_LOG_TAG
}),
testMetrics
,
testMetrics
,
false
false
)
)
}
describe
(
'
TransactionBatchSubmitter
'
,
()
=>
{
describe
(
'
TransactionBatchSubmitter
'
,
()
=>
{
describe
(
'
submitNextBatch
'
,
()
=>
{
describe
(
'
submitNextBatch
'
,
()
=>
{
...
@@ -375,7 +387,7 @@ describe('BatchSubmitter', () => {
...
@@ -375,7 +387,7 @@ describe('BatchSubmitter', () => {
.
callsFake
(
async
()
=>
lowGasPriceWei
)
.
callsFake
(
async
()
=>
lowGasPriceWei
)
const
receipt
=
await
batchSubmitter
.
submitNextBatch
()
const
receipt
=
await
batchSubmitter
.
submitNextBatch
()
expect
(
sequencer
.
getGasPrice
).
to
.
have
.
been
.
called
On
ce
expect
(
sequencer
.
getGasPrice
).
to
.
have
.
been
.
called
Twi
ce
expect
(
receipt
).
to
.
not
.
be
.
undefined
expect
(
receipt
).
to
.
not
.
be
.
undefined
})
})
})
})
...
@@ -417,6 +429,17 @@ describe('BatchSubmitter', () => {
...
@@ -417,6 +429,17 @@ describe('BatchSubmitter', () => {
// submit a batch of transactions to enable state batch submission
// submit a batch of transactions to enable state batch submission
await
txBatchSubmitter
.
submitNextBatch
()
await
txBatchSubmitter
.
submitNextBatch
()
const
resubmissionConfig
:
ResubmissionConfig
=
{
resubmissionTimeout
:
100000
,
minGasPriceInGwei
:
MIN_GAS_PRICE_IN_GWEI
,
maxGasPriceInGwei
:
GAS_THRESHOLD_IN_GWEI
,
gasRetryIncrement
:
GAS_RETRY_INCREMENT
,
}
const
stateBatchTxSubmitter
=
new
YnatmTransactionSubmitter
(
sequencer
,
resubmissionConfig
,
1
)
stateBatchSubmitter
=
new
StateBatchSubmitter
(
stateBatchSubmitter
=
new
StateBatchSubmitter
(
sequencer
,
sequencer
,
l2Provider
as
any
,
l2Provider
as
any
,
...
@@ -429,10 +452,7 @@ describe('BatchSubmitter', () => {
...
@@ -429,10 +452,7 @@ describe('BatchSubmitter', () => {
0
,
// finalityConfirmations
0
,
// finalityConfirmations
AddressManager
.
address
,
AddressManager
.
address
,
1
,
1
,
MIN_GAS_PRICE_IN_GWEI
,
stateBatchTxSubmitter
,
MAX_GAS_PRICE_IN_GWEI
,
GAS_RETRY_INCREMENT
,
GAS_THRESHOLD_IN_GWEI
,
1
,
1
,
new
Logger
({
name
:
STATE_BATCH_SUBMITTER_LOG_TAG
}),
new
Logger
({
name
:
STATE_BATCH_SUBMITTER_LOG_TAG
}),
testMetrics
,
testMetrics
,
...
@@ -473,54 +493,4 @@ describe('Batch Submitter with Ganache', () => {
...
@@ -473,54 +493,4 @@ describe('Batch Submitter with Ganache', () => {
after
(
async
()
=>
{
after
(
async
()
=>
{
await
server
.
close
()
await
server
.
close
()
})
})
// Unit test for getReceiptWithResubmission function,
// tests for increasing gas price on resubmission
it
(
'
should resubmit a transaction if it is not confirmed
'
,
async
()
=>
{
const
gasPrices
=
[]
const
numConfirmations
=
2
const
sendTxFunc
=
async
(
gasPrice
)
=>
{
// push the retried gasPrice
gasPrices
.
push
(
gasPrice
)
const
tx
=
signer
.
sendTransaction
({
to
:
predeploys
.
OVM_SequencerEntrypoint
,
value
:
88
,
nonce
:
0
,
gasPrice
,
})
const
response
=
await
tx
return
signer
.
provider
.
waitForTransaction
(
response
.
hash
,
numConfirmations
)
}
const
resubmissionConfig
=
{
numConfirmations
,
resubmissionTimeout
:
1
_000
,
// retry every second
minGasPriceInGwei
:
0
,
maxGasPriceInGwei
:
100
,
gasRetryIncrement
:
5
,
}
BatchSubmitter
.
getReceiptWithResubmission
(
sendTxFunc
,
resubmissionConfig
,
new
Logger
({
name
:
TX_BATCH_SUBMITTER_LOG_TAG
})
)
// Wait 1.5s for at least 1 retry
await
new
Promise
((
r
)
=>
setTimeout
(
r
,
1500
))
// Iterate through gasPrices to ensure each entry increases from
// the last
const
isIncreasing
=
gasPrices
.
reduce
(
(
isInc
,
gasPrice
,
i
,
gP
)
=>
(
isInc
&&
gasPrice
>
gP
[
i
-
1
])
||
Number
.
NEGATIVE_INFINITY
,
true
)
expect
(
gasPrices
).
to
.
have
.
lengthOf
.
above
(
1
)
// retried at least once
expect
(
isIncreasing
).
to
.
be
.
true
})
})
})
packages/batch-submitter/test/utils/tx-submission.spec.ts
0 → 100644
View file @
a8c9cd67
import
{
expect
}
from
'
../setup
'
import
{
ethers
,
BigNumber
,
Signer
}
from
'
ethers
'
import
{
submitTransactionWithYNATM
}
from
'
../../src/utils/tx-submission
'
import
{
ResubmissionConfig
}
from
'
../../src
'
import
{
TransactionReceipt
,
TransactionResponse
,
}
from
'
@ethersproject/abstract-provider
'
const
nullFunction
=
()
=>
undefined
const
nullHooks
=
{
beforeSendTransaction
:
nullFunction
,
onTransactionResponse
:
nullFunction
,
}
describe
(
'
submitTransactionWithYNATM
'
,
async
()
=>
{
it
(
'
calls sendTransaction, waitForTransaction, and hooks with correct inputs
'
,
async
()
=>
{
const
called
=
{
sendTransaction
:
false
,
waitForTransaction
:
false
,
beforeSendTransaction
:
false
,
onTransactionResponse
:
false
,
}
const
dummyHash
=
'
dummy hash
'
const
numConfirmations
=
3
const
tx
=
{
data
:
'
we here though
'
,
}
as
ethers
.
PopulatedTransaction
const
sendTransaction
=
async
(
_tx
:
ethers
.
PopulatedTransaction
):
Promise
<
TransactionResponse
>
=>
{
called
.
sendTransaction
=
true
expect
(
_tx
.
data
).
to
.
equal
(
tx
.
data
)
return
{
hash
:
dummyHash
,
}
as
TransactionResponse
}
const
waitForTransaction
=
async
(
hash
:
string
,
_numConfirmations
:
number
):
Promise
<
TransactionReceipt
>
=>
{
called
.
waitForTransaction
=
true
expect
(
hash
).
to
.
equal
(
dummyHash
)
expect
(
_numConfirmations
).
to
.
equal
(
numConfirmations
)
return
{
to
:
''
,
from
:
''
,
status
:
1
,
}
as
TransactionReceipt
}
const
signer
=
{
getGasPrice
:
async
()
=>
ethers
.
BigNumber
.
from
(
0
),
sendTransaction
,
provider
:
{
waitForTransaction
,
},
}
as
Signer
const
hooks
=
{
beforeSendTransaction
:
(
submittingTx
:
ethers
.
PopulatedTransaction
)
=>
{
called
.
beforeSendTransaction
=
true
expect
(
submittingTx
.
data
).
to
.
equal
(
tx
.
data
)
},
onTransactionResponse
:
(
txResponse
:
TransactionResponse
)
=>
{
called
.
onTransactionResponse
=
true
expect
(
txResponse
.
hash
).
to
.
equal
(
dummyHash
)
},
}
const
config
:
ResubmissionConfig
=
{
resubmissionTimeout
:
1000
,
minGasPriceInGwei
:
0
,
maxGasPriceInGwei
:
0
,
gasRetryIncrement
:
1
,
}
await
submitTransactionWithYNATM
(
tx
,
signer
,
config
,
numConfirmations
,
hooks
)
expect
(
called
.
sendTransaction
).
to
.
be
.
true
expect
(
called
.
waitForTransaction
).
to
.
be
.
true
expect
(
called
.
beforeSendTransaction
).
to
.
be
.
true
expect
(
called
.
onTransactionResponse
).
to
.
be
.
true
})
it
(
'
repeatedly increases the gas limit of the transaction when wait takes too long
'
,
async
()
=>
{
// Make transactions take longer to be included
// than our resubmission timeout
const
resubmissionTimeout
=
100
const
txReceiptDelay
=
resubmissionTimeout
*
3
const
numConfirmations
=
3
let
lastGasPrice
=
BigNumber
.
from
(
0
)
// Create a transaction which has a gas price that we will watch increment
const
tx
=
{
gasPrice
:
lastGasPrice
.
add
(
1
),
data
:
'
hello world!
'
,
}
as
ethers
.
PopulatedTransaction
const
sendTransaction
=
async
(
_tx
:
ethers
.
PopulatedTransaction
):
Promise
<
TransactionResponse
>
=>
{
// Ensure the gas price is always increasing
expect
(
_tx
.
gasPrice
>
lastGasPrice
).
to
.
be
.
true
lastGasPrice
=
_tx
.
gasPrice
return
{
hash
:
'
dummy hash
'
,
}
as
TransactionResponse
}
const
waitForTransaction
=
async
(
hash
:
string
,
_numConfirmations
:
number
):
Promise
<
TransactionReceipt
>
=>
{
await
new
Promise
((
r
)
=>
setTimeout
(
r
,
txReceiptDelay
))
return
{}
as
TransactionReceipt
}
const
signer
=
{
getGasPrice
:
async
()
=>
ethers
.
BigNumber
.
from
(
0
),
sendTransaction
,
provider
:
{
waitForTransaction
,
},
}
as
Signer
const
config
:
ResubmissionConfig
=
{
resubmissionTimeout
,
minGasPriceInGwei
:
0
,
maxGasPriceInGwei
:
1000
,
gasRetryIncrement
:
1
,
}
await
submitTransactionWithYNATM
(
tx
,
signer
,
config
,
0
,
nullHooks
)
})
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment