11import {
2- getVeaOutboxArbToGnosisProvider ,
3- getVeaInboxArbToGnosisProvider ,
4- getWETHProvider ,
5- getWalletRPC ,
6- getVeaRouterArbToGnosisProvider ,
7- getAMBProvider ,
2+ getVeaOutboxArbToGnosis ,
3+ getVeaInboxArbToGnosis ,
4+ getWETH ,
5+ getWallet ,
6+ getVeaRouterArbToGnosis ,
7+ getAMB ,
88} from "../utils/ethers" ;
99import { JsonRpcProvider } from "@ethersproject/providers" ;
10+ import { Wallet } from "@ethersproject/wallet" ;
1011import { ChildToParentMessageStatus , ChildTransactionReceipt , getArbitrumNetwork } from "@arbitrum/sdk" ;
1112import { NODE_INTERFACE_ADDRESS } from "@arbitrum/sdk/dist/lib/dataEntities/constants" ;
1213import { NodeInterface__factory } from "@arbitrum/sdk/dist/lib/abi/factories/NodeInterface__factory" ;
1314import { SequencerInbox__factory } from "@arbitrum/sdk/dist/lib/abi/factories/SequencerInbox__factory" ;
14- import { BigNumber , ContractTransaction , Wallet , constants , ethers } from "ethers" ;
15+ import { ethers , ContractTransactionResponse } from "ethers" ;
1516import { Block , Log } from "@ethersproject/abstract-provider" ;
1617import { SequencerInbox } from "@arbitrum/sdk/dist/lib/abi/SequencerInbox" ;
1718import { NodeInterface } from "@arbitrum/sdk/dist/lib/abi/NodeInterface" ;
@@ -21,7 +22,6 @@ import {
2122 VeaInboxArbToGnosis ,
2223 VeaOutboxArbToGnosis ,
2324} from "@kleros/vea-contracts/typechain-types" ;
24- import { ClaimStruct } from "@kleros/vea-contracts/typechain-types/arbitrumToEth/VeaInboxArbToEth" ;
2525import { messageExecutor } from "../utils/arbMsgExecutor" ;
2626
2727require ( "dotenv" ) . config ( ) ;
@@ -96,52 +96,44 @@ const watch = async () => {
9696 const providerGnosis = new JsonRpcProvider ( process . env . RPC_GNOSIS ) ;
9797 const providerArb = new JsonRpcProvider ( process . env . RPC_ARB ) ;
9898
99- const watcherAddress = getWalletRPC ( process . env . PRIVATE_KEY , providerGnosis ) . address ;
99+ const watcherAddress = getWallet ( process . env . PRIVATE_KEY , process . env . RPC_GNOSIS ) . address ;
100100
101101 // use typechain generated contract factories for vea outbox and inbox
102- const veaOutbox = getVeaOutboxArbToGnosisProvider ( veaOutboxAddress , process . env . PRIVATE_KEY , providerGnosis ) ;
103- const veaInbox = getVeaInboxArbToGnosisProvider ( veaInboxAddress , process . env . PRIVATE_KEY , providerArb ) ;
104- const veaRouter = getVeaRouterArbToGnosisProvider ( veaRouterAddress , process . env . PRIVATE_KEY , providerEth ) ;
105- const amb = getAMBProvider ( gnosisAMBAddress , process . env . PRIVATE_KEY , providerGnosis ) ;
102+ const veaOutbox = getVeaOutboxArbToGnosis ( veaOutboxAddress , process . env . PRIVATE_KEY , process . env . RPC_GNOSIS ) ;
103+ const veaInbox = getVeaInboxArbToGnosis ( veaInboxAddress , process . env . PRIVATE_KEY , process . env . RPC_ARB ) ;
104+ const veaRouter = getVeaRouterArbToGnosis ( veaRouterAddress , process . env . PRIVATE_KEY , process . env . RPC_ETH ) ;
105+ const amb = getAMB ( gnosisAMBAddress , process . env . PRIVATE_KEY , process . env . RPC_GNOSIS ) ;
106106
107107 const wethAddress = ( await retryOperation ( ( ) => veaOutbox . weth ( ) , 1000 , 10 ) ) as string ;
108- const weth = getWETHProvider ( wethAddress , process . env . PRIVATE_KEY , providerGnosis ) ;
109- const balance = ( await retryOperation ( ( ) => weth . balanceOf ( watcherAddress ) , 1000 , 10 ) ) as BigNumber ;
110- const allowance = ( await retryOperation (
111- ( ) => weth . allowance ( watcherAddress , veaOutboxAddress ) ,
112- 1000 ,
113- 10
114- ) ) as BigNumber ;
108+ const weth = getWETH ( wethAddress , process . env . PRIVATE_KEY , process . env . RPC_GNOSIS ) ;
109+ const balance = ( await retryOperation ( ( ) => weth . balanceOf ( watcherAddress ) , 1000 , 10 ) ) as BigInt ;
110+ const allowance = ( await retryOperation ( ( ) => weth . allowance ( watcherAddress , veaOutboxAddress ) , 1000 , 10 ) ) as BigInt ;
115111
116112 // get Arb sequencer params
117113 const l2Network = await getArbitrumNetwork ( providerArb ) ;
118114 const sequencer = SequencerInbox__factory . connect ( l2Network . ethBridge . sequencerInbox , providerEth ) ;
119- const maxDelaySeconds = (
120- ( await retryOperation ( ( ) => sequencer . maxTimeVariation ( ) , 1000 , 10 ) ) [ 1 ] as BigNumber
121- ) . toNumber ( ) ;
115+ const maxDelaySeconds = Number ( ( await retryOperation ( ( ) => sequencer . maxTimeVariation ( ) , 1000 , 10 ) ) [ 1 ] as BigInt ) ;
122116
123117 // get vea outbox params
124- const deposit = ( await retryOperation ( ( ) => veaOutbox . deposit ( ) , 1000 , 10 ) ) as BigNumber ;
125- const epochPeriod = ( ( await retryOperation ( ( ) => veaOutbox . epochPeriod ( ) , 1000 , 10 ) ) as BigNumber ) . toNumber ( ) ;
126- const sequencerDelayLimit = (
127- ( await retryOperation ( ( ) => veaOutbox . sequencerDelayLimit ( ) , 1000 , 10 ) ) as BigNumber
128- ) . toNumber ( ) ;
118+ const deposit = await retryOperation ( ( ) => veaOutbox . deposit ( ) , 1000 , 10 ) ;
119+ const epochPeriod = Number ( await retryOperation ( ( ) => veaOutbox . epochPeriod ( ) , 1000 , 10 ) ) ;
120+ const sequencerDelayLimit = Number ( await retryOperation ( ( ) => veaOutbox . sequencerDelayLimit ( ) , 1000 , 10 ) ) ;
129121
130- const inactive = balance . lt ( deposit ) ;
122+ const inactive = balance < deposit ;
131123 if ( inactive ) {
132124 console . error (
133125 "insufficient weth balance to run an active watcher. Try bridging eth to gnosis with https://omni.gnosischain.com/bridge"
134126 ) ;
135127 console . log ( "running watcher in passive mode (no challenges)" ) ;
136128 }
137129
138- if ( allowance . lt ( constants . MaxUint256 . div ( 2 ) ) ) {
130+ if ( BigInt ( allowance . toString ( ) ) < ethers . MaxUint256 / BigInt ( 2 ) ) {
139131 console . log ( "setting infinite weth approval to vea outbox to prepare to challenge. . ." ) ;
140132 const approvalTxn = ( await retryOperation (
141- ( ) => weth . approve ( veaOutboxAddress , constants . MaxUint256 ) ,
133+ ( ) => weth . approve ( veaOutboxAddress , ethers . MaxUint256 ) ,
142134 1000 ,
143135 10
144- ) ) as ContractTransaction ;
136+ ) ) as ContractTransactionResponse ;
145137 await approvalTxn . wait ( ) ;
146138 console . log ( "weth approval txn hash: " + approvalTxn . hash ) ;
147139 }
@@ -241,7 +233,7 @@ const watch = async () => {
241233 ) ) as string ;
242234
243235 // no claim
244- if ( claimHash == constants . HashZero ) {
236+ if ( claimHash == ethers . ZeroHash ) {
245237 // if epoch is not claimable anymore, remove from array
246238 if ( veaEpochOutboxCheck <= veaEpochOutboxClaimableFinalized ) {
247239 console . log (
@@ -281,12 +273,11 @@ const watch = async () => {
281273 const logClaimed : Log = (
282274 await retryOperation (
283275 ( ) =>
284- providerGnosis . getLogs ( {
285- address : veaOutboxAddress ,
286- topics : veaOutbox . filters . Claimed ( null , [ veaEpochOutboxCheck ] , null ) . topics ,
287- fromBlock : blockNumberOutboxLowerBound ,
288- toBlock : blockTagGnosis ,
289- } ) ,
276+ veaOutbox . queryFilter (
277+ veaOutbox . filters . Claimed ( null , veaEpochOutboxCheck , null ) ,
278+ blockNumberOutboxLowerBound ,
279+ blockTagGnosis
280+ ) ,
290281 1000 ,
291282 10
292283 )
@@ -342,13 +333,13 @@ const watch = async () => {
342333 ) ;
343334 //TODO : check profitablity of the whole dispute resolution
344335 //const profitablity = await calculateDisputeResolutionProfitability(veaEpochOutboxCheck,claim,veaOutbox,veaInbox,providerGnosis,providerArb,providerEth);
345- if ( claim . challenger == constants . AddressZero ) {
336+ if ( claim . challenger == ethers . ZeroAddress ) {
346337 if ( challengeProgress ?. challenge . status == "pending" ) continue ;
347338 const txnChallenge = ( await retryOperation (
348339 ( ) => veaOutbox . challenge ( veaEpochOutboxCheck , claim ) ,
349340 1000 ,
350341 10
351- ) ) as ContractTransaction ;
342+ ) ) as ContractTransactionResponse ;
352343 console . log ( "Epoch " + veaEpochOutboxCheck + " challenged with txn " + txnChallenge . hash ) ;
353344 challengeProgress . challenge = {
354345 status : "pending" ,
@@ -368,7 +359,7 @@ const watch = async () => {
368359 ( ) => veaInbox . sendSnapshot ( veaEpochOutboxCheck , 200000 , claim ) , // execute transaction required around 142000 gas so we set gas limit to 200000
369360 1000 ,
370361 10
371- ) ) as ContractTransaction ;
362+ ) ) as ContractTransactionResponse ;
372363 console . log ( "Epoch " + veaEpochOutboxCheck + " sendSnapshot called with txn " + txnSendSnapshot . hash ) ;
373364 challengeProgress . snapshot = {
374365 status : "pending" ,
@@ -395,7 +386,7 @@ const watch = async () => {
395386 ( ) => veaOutbox . withdrawChallengeDeposit ( veaEpochOutboxCheck , claim ) ,
396387 1000 ,
397388 10
398- ) ) as ContractTransaction ;
389+ ) ) as ContractTransactionResponse ;
399390
400391 if ( txnWithdrawalDeposit . hash ) {
401392 console . log (
@@ -588,7 +579,7 @@ const ArbBlockToL1Block = async (
588579 . findBatchContainingBlock ( L2Block . number , { blockTag : "latest" } )
589580 . catch ( ( e ) => {
590581 console . error ( "Error finding batch containing block:" , JSON . parse ( JSON . stringify ( e ) ) . error . body ) ;
591- } ) ) as [ BigNumber ] & { batch : BigNumber } ;
582+ } ) ) as any ;
592583
593584 if ( ! result ) {
594585 if ( ! fallbackLatest ) {
@@ -657,7 +648,7 @@ async function getClaimForEpoch(
657648 const claimHash = ( await retryOperation ( ( ) => veaOutbox . claimHashes ( epoch ) , 1000 , 10 ) ) as any ;
658649
659650 // If there's no claim, return null
660- if ( claimHash === constants . HashZero ) {
651+ if ( claimHash === ethers . ZeroHash ) {
661652 return null ;
662653 }
663654
@@ -694,7 +685,7 @@ async function getClaimForEpoch(
694685 timestampVerification : 0 ,
695686 blocknumberVerification : 0 ,
696687 honest : 0 , // 0 for None, 1 for Claimer, 2 for Challenger
697- challenger : constants . AddressZero ,
688+ challenger : ethers . ZeroAddress ,
698689 } ;
699690 let other = { } as any ;
700691 let calculatedHash = hashClaim ( claim ) ;
@@ -755,58 +746,58 @@ async function getClaimForEpoch(
755746 return null ;
756747}
757748
758- async function calculateDisputeResolutionProfitability (
759- epoch : number ,
760- claim : ClaimStruct ,
761- veaOutbox : VeaOutboxArbToGnosis ,
762- veaInbox : VeaInboxArbToGnosis ,
763- providerGnosis : JsonRpcProvider ,
764- providerArb : JsonRpcProvider ,
765- providerEth : JsonRpcProvider
766- ) : Promise < { profitable : boolean ; estimatedProfit : BigNumber } > {
767- try {
768- const deposit = ( await retryOperation ( ( ) => veaOutbox . deposit ( ) , 1000 , 10 ) ) as BigNumber ;
769- const totalReward = deposit ;
770- const minimumProfit = totalReward . mul ( 40 ) . div ( 100 ) ; // 40% of total reward
771- let maximumAllowableCost = totalReward . sub ( minimumProfit ) ;
772- let totalCost = BigNumber . from ( 0 ) ;
773-
774- // 1. Costs on Gnosis Chain
775- const gnosisGasEstimate = await veaOutbox . estimateGas . challenge ( epoch , claim ) ;
776-
777- const gnosisGasPrice = await providerGnosis . getGasPrice ( ) ;
778- const gnosisCost = gnosisGasEstimate . mul ( gnosisGasPrice ) ;
779-
780- if ( gnosisCost . gt ( maximumAllowableCost ) ) {
781- return { profitable : false , estimatedProfit : constants . Zero } ;
782- }
783- totalCost = totalCost . add ( gnosisCost ) ;
784- maximumAllowableCost = maximumAllowableCost . sub ( gnosisCost ) ;
785-
786- const l2Network = await getArbitrumNetwork ( providerArb ) ;
787-
788- const arbGasEstimate = ( await retryOperation (
789- ( ) => veaInbox . estimateGas . sendSnapshot ( epoch , 200000 , claim ) ,
790- 1000 ,
791- 10
792- ) ) as BigNumber ;
793-
794- const arbGasPrice = ( await retryOperation ( ( ) => providerArb . getGasPrice ( ) , 1000 , 10 ) ) as BigNumber ;
795- const arbCost = arbGasEstimate . mul ( arbGasPrice ) ;
796-
797- if ( arbCost . gt ( maximumAllowableCost ) ) {
798- return { profitable : false , estimatedProfit : constants . Zero } ;
799- }
800- totalCost = totalCost . add ( arbCost ) ;
801- maximumAllowableCost = maximumAllowableCost . sub ( arbCost ) ;
802-
803- // 3. Costs on Ethereum (for Arbitrum -> Ethereum message)
804- //TODO : L2 to L1 message execution gas cost
805- } catch ( error ) {
806- console . error ( "Error calculating profitability:" , error ) ;
807- return { profitable : false , estimatedProfit : constants . Zero } ;
808- }
809- }
749+ // async function calculateDisputeResolutionProfitability(
750+ // epoch: number,
751+ // claim: ClaimStruct,
752+ // veaOutbox: VeaOutboxArbToGnosis,
753+ // veaInbox: VeaInboxArbToGnosis,
754+ // providerGnosis: JsonRpcProvider,
755+ // providerArb: JsonRpcProvider,
756+ // providerEth: JsonRpcProvider
757+ // ): Promise<{ profitable: boolean; estimatedProfit: BigInt }> {
758+ // try {
759+ // const deposit = await retryOperation(() => veaOutbox.deposit(), 1000, 10) as bigint ;
760+ // const totalReward = deposit;
761+ // const minimumProfit = totalReward * BigInt (40) / BigInt (100); // 40% of total reward
762+ // let maximumAllowableCost = totalReward - minimumProfit;
763+ // let totalCost = BigInt (0);
764+
765+ // // 1. Costs on Gnosis Chain
766+ // const gnosisGasEstimate = await veaOutbox.challenge.estimateGas (epoch, claim);
767+
768+ // const gnosisGasPrice = await providerGnosis.getGasPrice();
769+ // const gnosisCost = gnosisGasEstimate * gnosisGasPrice;
770+
771+ // if (gnosisCost > maximumAllowableCost) {
772+ // return { profitable: false, estimatedProfit: BigInt(0) };
773+ // }
774+ // totalCost = totalCost + gnosisCost;
775+ // maximumAllowableCost = maximumAllowableCost - gnosisCost;
776+
777+ // const l2Network = await getArbitrumNetwork(providerArb);
778+
779+ // const arbGasEstimate = (await retryOperation(
780+ // () => veaInbox.sendSnapshot.estimateGas (epoch, 200000, claim),
781+ // 1000,
782+ // 10
783+ // )) as BigInt ;
784+
785+ // const arbGasPrice = (await retryOperation(() => providerArb.getGasPrice(), 1000, 10)) as BigInt ;
786+ // const arbCost = arbGasEstimate * arbGasPrice;
787+
788+ // if (arbCost > maximumAllowableCost) {
789+ // return { profitable: false, estimatedProfit: BigInt(0) };
790+ // }
791+ // totalCost = totalCost + arbCost;
792+ // maximumAllowableCost = maximumAllowableCost - arbCost;
793+
794+ // // 3. Costs on Ethereum (for Arbitrum -> Ethereum message)
795+ // //TODO : L2 to L1 message execution gas cost
796+ // } catch (error) {
797+ // console.error("Error calculating profitability:", error);
798+ // return { profitable: false, estimatedProfit: BigInt(0) };
799+ // }
800+ // }
810801
811802function needsRetry ( current : ChallengeProgress , previous : ChallengeProgress | undefined ) : boolean {
812803 if ( ! previous ) return false ;
@@ -1112,7 +1103,7 @@ async function reconstructChallengeProgress(
11121103}
11131104
11141105const hashClaim = ( claim ) => {
1115- return ethers . utils . solidityKeccak256 (
1106+ return ethers . solidityPackedKeccak256 (
11161107 [ "bytes32" , "address" , "uint32" , "uint32" , "uint32" , "uint8" , "address" ] ,
11171108 [
11181109 claim . stateRoot ,
0 commit comments