Skip to content

Commit 2e6a5b5

Browse files
Fix force inclusion (#632)
* fix bugs for forceInclusion * fix findFirstBlockBelow * fix maxTimeVariation decoder type assertion for TS compilation * extract L1/Arb block mapping utilities from inbox.ts (#633) Pull repeated ArbitrumProvider and NodeInterface block-mapping logic into getL1BlockNumberOfArbBlock and getFirstArbBlockForL1Block in lib.ts, replacing inline implementations in findFirstBlockBelow, getForceIncludableBlockRange, and forceInclude. * renmae --------- Co-authored-by: doug <4741454+douglance@users.noreply.github.com>
1 parent 848e4a9 commit 2e6a5b5

2 files changed

Lines changed: 68 additions & 40 deletions

File tree

packages/sdk/src/lib/inbox/inbox.ts

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import { Signer } from '@ethersproject/abstract-signer'
2020
import { Block, Provider } from '@ethersproject/abstract-provider'
2121
import { BigNumber, ContractTransaction, ethers, Overrides } from 'ethers'
22-
import { TransactionRequest, JsonRpcProvider } from '@ethersproject/providers'
22+
import { TransactionRequest } from '@ethersproject/providers'
2323

2424
import { Bridge } from '../abi/Bridge'
2525
import { Bridge__factory } from '../abi/factories/Bridge__factory'
@@ -37,11 +37,11 @@ import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory'
3737
import { NODE_INTERFACE_ADDRESS } from '../dataEntities/constants'
3838
import { InboxMessageKind } from '../dataEntities/message'
3939
import {
40-
getBlockRangesForL1Block,
40+
getFirstArbBlockForL1Block,
41+
getL1BlockNumberOfArbBlock,
4142
isArbitrumChain,
4243
isDefined,
4344
} from '../utils/lib'
44-
import { ArbitrumProvider } from '../utils/arbProvider'
4545

4646
type ForceInclusionParams = FetchedEvent<MessageDeliveredEvent> & {
4747
delayedAcc: string
@@ -90,37 +90,11 @@ export class InboxTools {
9090
): Promise<Block> {
9191
const isParentChainArbitrum = await isArbitrumChain(this.parentProvider)
9292

93-
if (isParentChainArbitrum) {
94-
const nodeInterface = NodeInterface__factory.connect(
95-
NODE_INTERFACE_ADDRESS,
96-
this.parentProvider
97-
)
98-
99-
try {
100-
blockNumber = (
101-
await nodeInterface.l2BlockRangeForL1(blockNumber - 1)
102-
).firstBlock.toNumber()
103-
} catch (e) {
104-
// l2BlockRangeForL1 reverts if no L2 block exist with the given L1 block number,
105-
// since l1 block is updated in batch sometimes block can be skipped even when there are activities
106-
// alternatively we use binary search to get the nearest block
107-
const _blockNum = (
108-
await getBlockRangesForL1Block({
109-
arbitrumProvider: this.parentProvider as JsonRpcProvider,
110-
forL1Block: blockNumber - 1,
111-
allowGreater: true,
112-
})
113-
)[0]
114-
115-
if (!_blockNum) {
116-
throw e
117-
}
118-
119-
blockNumber = _blockNum
120-
}
121-
}
93+
const parentChainBlockNumber = isParentChainArbitrum
94+
? await getFirstArbBlockForL1Block(this.parentProvider, blockNumber - 1)
95+
: blockNumber
12296

123-
const block = await this.parentProvider.getBlock(blockNumber)
97+
const block = await this.parentProvider.getBlock(parentChainBlockNumber)
12498
const diff = block.timestamp - blockTimestamp
12599
if (diff < 0) return block
126100

@@ -194,11 +168,10 @@ export class InboxTools {
194168
const isParentChainArbitrum = await isArbitrumChain(this.parentProvider)
195169

196170
if (isParentChainArbitrum) {
197-
const arbProvider = new ArbitrumProvider(
198-
this.parentProvider as JsonRpcProvider
171+
currentL1BlockNumber = await getL1BlockNumberOfArbBlock(
172+
this.parentProvider,
173+
'latest'
199174
)
200-
const currentArbBlock = await arbProvider.getBlock('latest')
201-
currentL1BlockNumber = currentArbBlock.l1BlockNumber
202175
}
203176

204177
const multicall = await MultiCaller.fromProvider(this.parentProvider)
@@ -215,7 +188,9 @@ export class InboxTools {
215188
sequencerInbox.interface.decodeFunctionResult(
216189
'maxTimeVariation',
217190
returnData
218-
)[0],
191+
) as unknown as Awaited<
192+
ReturnType<SequencerInbox['maxTimeVariation']>
193+
>,
219194
},
220195
multicall.getBlockNumberInput(),
221196
multicall.getCurrentBlockTimestampInput(),
@@ -378,10 +353,18 @@ export class InboxTools {
378353
if (!eventInfo) return null
379354
const block = await this.parentProvider.getBlock(eventInfo.blockHash)
380355

356+
let l1BlockNumber: number = eventInfo.blockNumber
357+
if (await isArbitrumChain(this.parentProvider)) {
358+
l1BlockNumber = await getL1BlockNumberOfArbBlock(
359+
this.parentProvider,
360+
eventInfo.blockNumber
361+
)
362+
}
363+
381364
return await sequencerInbox.functions.forceInclusion(
382365
eventInfo.event.messageIndex.add(1),
383366
eventInfo.event.kind,
384-
[eventInfo.blockNumber, block.timestamp],
367+
[l1BlockNumber, block.timestamp],
385368
eventInfo.event.baseFeeL1,
386369
eventInfo.event.sender,
387370
eventInfo.event.messageDataHash,

packages/sdk/src/lib/utils/lib.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { TransactionReceipt, JsonRpcProvider } from '@ethersproject/providers'
44
import { ArbSdkError } from '../dataEntities/errors'
55
import { ArbitrumProvider } from './arbProvider'
66
import { ArbSys__factory } from '../abi/factories/ArbSys__factory'
7-
import { ARB_SYS_ADDRESS } from '../dataEntities/constants'
7+
import {
8+
ARB_SYS_ADDRESS,
9+
NODE_INTERFACE_ADDRESS,
10+
} from '../dataEntities/constants'
11+
import { NodeInterface__factory } from '../abi/factories/NodeInterface__factory'
812
import { ArbitrumNetwork, getNitroGenesisBlock } from '../dataEntities/networks'
913
import { ERC20__factory } from '../abi/factories/ERC20__factory'
1014

@@ -68,6 +72,47 @@ export const isArbitrumChain = async (provider: Provider): Promise<boolean> => {
6872
return true
6973
}
7074

75+
/**
76+
* Get the L1 block number for a given block on an Arbitrum chain.
77+
*/
78+
export async function getL1BlockNumberOfArbBlock(
79+
provider: Provider,
80+
blockNumber: number | 'latest'
81+
): Promise<number> {
82+
const arbProvider = new ArbitrumProvider(provider as JsonRpcProvider)
83+
const arbBlock = await arbProvider.getBlock(blockNumber)
84+
return arbBlock.l1BlockNumber
85+
}
86+
87+
/**
88+
* Get the first Arbitrum block number that corresponds to a given L1 block.
89+
* Falls back to binary search if l2BlockRangeForL1 reverts.
90+
*/
91+
export async function getFirstArbBlockForL1Block(
92+
provider: Provider,
93+
l1BlockNumber: number
94+
): Promise<number> {
95+
const nodeInterface = NodeInterface__factory.connect(
96+
NODE_INTERFACE_ADDRESS,
97+
provider
98+
)
99+
try {
100+
return (
101+
await nodeInterface.l2BlockRangeForL1(l1BlockNumber)
102+
).firstBlock.toNumber()
103+
} catch (e) {
104+
const blockNum = (
105+
await getBlockRangesForL1Block({
106+
arbitrumProvider: provider as JsonRpcProvider,
107+
forL1Block: l1BlockNumber,
108+
allowGreater: true,
109+
})
110+
)[0]
111+
if (!blockNum) throw e
112+
return blockNum
113+
}
114+
}
115+
71116
type GetFirstBlockForL1BlockProps = {
72117
arbitrumProvider: JsonRpcProvider
73118
forL1Block: number

0 commit comments

Comments
 (0)