1
1
import { JsonRpcProvider } from "@ethersproject/providers" ;
2
2
import { ethers } from "ethers" ;
3
- import { ITransactionHandler } from "../utils/transactionHandlers" ;
3
+ import { ITransactionHandler , getTransactionHandler } from "../utils/transactionHandlers" ;
4
4
import { getClaim , getClaimResolveState } from "../utils/claim" ;
5
5
import { defaultEmitter } from "../utils/emitter" ;
6
6
import { BotEvents } from "../utils/botEvents" ;
7
7
import { getBlocksAndCheckFinality } from "../utils/arbToEthState" ;
8
8
import { Network } from "../consts/bridgeRoutes" ;
9
9
import { ClaimStruct } from "@kleros/vea-contracts/typechain-types/arbitrumToEth/VeaInboxArbToEth" ;
10
- import { getTransactionHandler } from "../utils/ethers" ;
11
-
12
- // https://github.com/prysmaticlabs/prysm/blob/493905ee9e33a64293b66823e69704f012b39627/config/params/mainnet_config.go#L103
13
- const secondsPerSlotEth = 12 ;
10
+ import { getBlockFromEpoch } from "../utils/epochHandler" ;
14
11
15
12
export interface ChallengeAndResolveClaimParams {
16
13
chainId : number ;
@@ -28,6 +25,7 @@ export interface ChallengeAndResolveClaimParams {
28
25
fetchClaimResolveState ?: typeof getClaimResolveState ;
29
26
fetchBlocksAndCheckFinality ?: typeof getBlocksAndCheckFinality ;
30
27
fetchTransactionHandler ?: typeof getTransactionHandler ;
28
+ fetchBlockFromEpoch ?: typeof getBlockFromEpoch ;
31
29
}
32
30
33
31
export async function challengeAndResolveClaim ( {
@@ -45,27 +43,19 @@ export async function challengeAndResolveClaim({
45
43
fetchClaimResolveState = getClaimResolveState ,
46
44
fetchBlocksAndCheckFinality = getBlocksAndCheckFinality ,
47
45
fetchTransactionHandler = getTransactionHandler ,
46
+ fetchBlockFromEpoch = getBlockFromEpoch ,
48
47
} : ChallengeAndResolveClaimParams ) : Promise < ITransactionHandler | null > {
49
48
if ( ! claim ) {
50
49
emitter . emit ( BotEvents . NO_CLAIM , epoch ) ;
51
50
return null ;
52
51
}
53
- const queryRpc = veaRouterProvider ? veaRouterProvider : veaOutboxProvider ;
54
- const [ arbitrumBlock , ethFinalizedBlock , finalityIssueFlagEth ] = await fetchBlocksAndCheckFinality (
52
+ const queryRpc = veaRouterProvider ?? veaOutboxProvider ;
53
+ const [ arbitrumBlock , , finalityIssueFlagEth ] = await fetchBlocksAndCheckFinality (
55
54
queryRpc ,
56
55
veaInboxProvider ,
57
56
epoch ,
58
57
epochPeriod
59
58
) ;
60
- let blockNumberOutboxLowerBound : number ;
61
- const epochClaimableFinalized = Math . floor ( ethFinalizedBlock . timestamp / epochPeriod ) - 2 ;
62
- // to query event performantly, we limit the block range with the heuristic that. delta blocknumber <= delta timestamp / secondsPerSlot
63
- if ( epoch <= epochClaimableFinalized ) {
64
- blockNumberOutboxLowerBound =
65
- ethFinalizedBlock . number - Math . ceil ( ( ( epochClaimableFinalized - epoch + 2 ) * epochPeriod ) / secondsPerSlotEth ) ;
66
- } else {
67
- blockNumberOutboxLowerBound = ethFinalizedBlock . number - Math . ceil ( epochPeriod / secondsPerSlotEth ) ;
68
- }
69
59
const ethBlockTag = finalityIssueFlagEth ? "finalized" : "latest" ;
70
60
if ( ! transactionHandler ) {
71
61
const TransactionHandler = fetchTransactionHandler ( chainId , Network . TESTNET ) ;
@@ -78,41 +68,118 @@ export async function challengeAndResolveClaim({
78
68
veaInboxProvider,
79
69
veaOutboxProvider,
80
70
veaRouterProvider,
81
- emitter : defaultEmitter ,
71
+ emitter,
82
72
claim,
83
73
} ) ;
84
74
} else {
85
75
transactionHandler . claim = claim ;
86
76
}
87
77
88
- const claimSnapshot = await veaInbox . snapshots ( epoch , { blockTag : arbitrumBlock . number } ) ;
89
- if ( claimSnapshot != claim . stateRoot && claim . challenger == ethers . ZeroAddress ) {
90
- await transactionHandler . challengeClaim ( ) ;
91
- } else {
92
- if ( claimSnapshot == claim . stateRoot && claim . challenger == ethers . ZeroAddress ) {
93
- emitter . emit ( BotEvents . VALID_CLAIM , epoch ) ;
94
- return null ;
95
- } else {
96
- const claimResolveState = await fetchClaimResolveState (
97
- chainId ,
98
- veaInbox ,
99
- veaInboxProvider ,
100
- queryRpc ,
101
- epoch ,
102
- blockNumberOutboxLowerBound ,
103
- ethBlockTag
104
- ) ;
105
- if ( ! claimResolveState . sendSnapshot . status ) {
106
- await transactionHandler . sendSnapshot ( ) ;
107
- } else if ( claimResolveState . execution . status == 1 ) {
108
- await transactionHandler . resolveChallengedClaim ( claimResolveState . sendSnapshot . txHash ) ;
109
- } else if ( claimResolveState . execution . status == 2 && claim . honest == 2 ) {
110
- await transactionHandler . withdrawChallengeDeposit ( ) ;
111
- } else {
112
- emitter . emit ( BotEvents . WAITING_ARB_TIMEOUT , epoch ) ;
113
- }
114
- }
78
+ const { challenged, toRelay } = await challengeAndCheckRelay ( {
79
+ veaInbox,
80
+ epoch,
81
+ claim,
82
+ transactionHandler,
83
+ arbitrumBlockNumber : arbitrumBlock . number ,
84
+ } ) ;
85
+ if ( ! toRelay && ! challenged ) {
86
+ return null ;
87
+ } else if ( challenged && ! toRelay ) {
88
+ return transactionHandler ;
115
89
}
90
+ await handleResolveFlow ( {
91
+ chainId,
92
+ epoch,
93
+ epochPeriod,
94
+ claim,
95
+ veaInbox,
96
+ veaInboxProvider,
97
+ queryRpc,
98
+ ethBlockTag,
99
+ transactionHandler,
100
+ fetchClaimResolveState,
101
+ fetchBlockFromEpoch,
102
+ } ) ;
116
103
117
104
return transactionHandler ;
118
105
}
106
+
107
+ interface ChallengeAndCheckRelayParams {
108
+ veaInbox : any ;
109
+ epoch : number ;
110
+ claim : ClaimStruct ;
111
+ transactionHandler : ITransactionHandler ;
112
+ arbitrumBlockNumber : number ;
113
+ }
114
+ async function challengeAndCheckRelay ( {
115
+ veaInbox,
116
+ epoch,
117
+ claim,
118
+ transactionHandler,
119
+ arbitrumBlockNumber,
120
+ } : ChallengeAndCheckRelayParams ) : Promise < { challenged : boolean ; toRelay : boolean } > {
121
+ const onChainSnapshot = await veaInbox . snapshots ( epoch , { blockTag : arbitrumBlockNumber } ) ;
122
+ const isNotChallenged = claim . challenger === ethers . ZeroAddress ;
123
+ const challengeAndRelayState = {
124
+ challenged : false ,
125
+ toRelay : false ,
126
+ } ;
127
+ if ( onChainSnapshot !== claim . stateRoot && isNotChallenged ) {
128
+ await transactionHandler . challengeClaim ( ) ;
129
+ challengeAndRelayState . challenged = true ;
130
+ }
131
+ if ( ! isNotChallenged ) {
132
+ return { challenged : true , toRelay : true } ;
133
+ }
134
+ return challengeAndRelayState ;
135
+ }
136
+
137
+ interface ResolveFlowParams {
138
+ chainId : number ;
139
+ epoch : number ;
140
+ epochPeriod : number ;
141
+ claim : ClaimStruct ;
142
+ veaInbox : any ;
143
+ veaInboxProvider : JsonRpcProvider ;
144
+ queryRpc : JsonRpcProvider ;
145
+ ethBlockTag : "latest" | "finalized" ;
146
+ transactionHandler : ITransactionHandler ;
147
+ fetchClaimResolveState : typeof getClaimResolveState ;
148
+ fetchBlockFromEpoch : typeof getBlockFromEpoch ;
149
+ }
150
+ async function handleResolveFlow ( {
151
+ chainId,
152
+ epoch,
153
+ epochPeriod,
154
+ claim,
155
+ veaInbox,
156
+ veaInboxProvider,
157
+ queryRpc,
158
+ ethBlockTag,
159
+ transactionHandler,
160
+ fetchClaimResolveState,
161
+ fetchBlockFromEpoch,
162
+ } : ResolveFlowParams ) : Promise < void > {
163
+ const blockNumberOutboxLowerBound = await fetchBlockFromEpoch ( epoch , epochPeriod , queryRpc ) ;
164
+ const claimResolveState = await fetchClaimResolveState ( {
165
+ chainId,
166
+ veaInbox,
167
+ veaInboxProvider,
168
+ veaOutboxProvider : queryRpc ,
169
+ epoch,
170
+ fromBlock : blockNumberOutboxLowerBound ,
171
+ toBlock : ethBlockTag ,
172
+ } ) ;
173
+
174
+ if ( ! claimResolveState . sendSnapshot . status ) {
175
+ await transactionHandler . sendSnapshot ( ) ;
176
+ return ;
177
+ }
178
+
179
+ const execStatus = claimResolveState . execution . status ;
180
+ if ( execStatus === 1 ) {
181
+ await transactionHandler . resolveChallengedClaim ( claimResolveState . sendSnapshot . txHash ) ;
182
+ } else if ( execStatus === 2 && claim . honest === 2 ) {
183
+ await transactionHandler . withdrawChallengeDeposit ( ) ;
184
+ }
185
+ }
0 commit comments