1+ import hre , { ethers } from 'hardhat' ;
2+ import { logger } from '../deployUtils' ;
3+
4+ type TxOverrides = {
5+ gasLimit ?: number ;
6+ maxFeePerGas ?: bigint ;
7+ maxPriorityFeePerGas ?: bigint ;
8+ gasPrice ?: bigint ;
9+ } ;
10+
11+ async function main ( ) {
12+ logger . step ( '🔧 Starting Batcher Contract Gas Limit Change 🔧' ) ;
13+
14+ const batcherContractAddress = process . env . BATCHER_CONTRACT_ADDRESS ;
15+ const newGasLimitStr = process . env . NEW_GAS_LIMIT ;
16+
17+ if ( ! batcherContractAddress ) {
18+ throw new Error ( 'BATCHER_CONTRACT_ADDRESS environment variable is required' ) ;
19+ }
20+
21+ if ( ! newGasLimitStr ) {
22+ throw new Error ( 'NEW_GAS_LIMIT environment variable is required' ) ;
23+ }
24+
25+ const newGasLimit = BigInt ( newGasLimitStr ) ;
26+
27+ logger . step ( '1. Setting up signer and network information...' ) ;
28+
29+ const signers = await ethers . getSigners ( ) ;
30+ if ( signers . length < 1 ) {
31+ throw new Error ( 'No signers available' ) ;
32+ }
33+
34+ const desiredIndex = process . env . BATCHER_DEPLOYER_INDEX
35+ ? Number ( process . env . BATCHER_DEPLOYER_INDEX )
36+ : 2 ;
37+ let batcherOwner = signers [ desiredIndex ] || signers [ signers . length - 1 ] ;
38+
39+ const signerInfos = await Promise . all (
40+ signers . map ( async ( s , i ) => {
41+ const addr = await s . getAddress ( ) ;
42+ const bal = await ethers . provider . getBalance ( addr ) ;
43+ return { index : i , addr, balance : bal } ;
44+ } )
45+ ) ;
46+
47+ if (
48+ ! batcherOwner ||
49+ ( await ethers . provider . getBalance ( await batcherOwner . getAddress ( ) ) ) === 0n
50+ ) {
51+ const funded = signerInfos
52+ . filter ( ( x ) => x . balance > 0n )
53+ . sort ( ( a , b ) => ( b . balance > a . balance ? 1 : - 1 ) ) [ 0 ] ;
54+ if ( ! funded ) {
55+ logger . error ( 'No funded signer available for transaction. Aborting.' ) ;
56+ throw new Error ( 'No funded signer' ) ;
57+ }
58+ batcherOwner = signers [ funded . index ] ;
59+ logger . warn (
60+ `Selected alternative funded signer index=${ funded . index } address=${
61+ funded . addr
62+ } (balance=${ ethers . formatEther ( funded . balance ) } )`
63+ ) ;
64+ }
65+
66+ const address = await batcherOwner . getAddress ( ) ;
67+ const { chainId } = await ethers . provider . getNetwork ( ) ;
68+
69+ logger . info ( `Network: ${ hre . network . name } (Chain ID: ${ chainId } )` ) ;
70+ logger . info ( `Owner Address: ${ address } ` ) ;
71+ logger . info ( `Batcher Contract Address: ${ batcherContractAddress } ` ) ;
72+ logger . info ( `New Gas Limit: ${ newGasLimit . toString ( ) } ` ) ;
73+
74+ logger . step ( '2. Connecting to Batcher contract...' ) ;
75+
76+ const batcherAbi = [
77+ 'function changeTransferGasLimit(uint256 newTransferGasLimit) external' ,
78+ 'function transferGasLimit() external view returns (uint256)' ,
79+ 'function owner() external view returns (address)'
80+ ] ;
81+
82+ const batcherContract = new ethers . Contract (
83+ batcherContractAddress ,
84+ batcherAbi ,
85+ batcherOwner
86+ ) ;
87+
88+ logger . step ( '3. Verifying contract ownership...' ) ;
89+
90+ try {
91+ const currentOwner = await batcherContract . owner ( ) ;
92+ logger . info ( `Contract Owner: ${ currentOwner } ` ) ;
93+
94+ if ( currentOwner . toLowerCase ( ) !== address . toLowerCase ( ) ) {
95+ throw new Error ( `Signer ${ address } is not the owner of the contract. Owner is ${ currentOwner } ` ) ;
96+ }
97+
98+ const currentGasLimit = await batcherContract . transferGasLimit ( ) ;
99+ logger . info ( `Current Gas Limit: ${ currentGasLimit . toString ( ) } ` ) ;
100+ } catch ( error ) {
101+ logger . error ( 'Failed to verify contract details:' , error ) ;
102+ throw error ;
103+ }
104+
105+ logger . step ( '4. Configuring gas parameters for the transaction...' ) ;
106+
107+ const eip1559Chains = [ 10143 , 480 , 4801 , 1946 , 1868 , 1114 , 1112 , 1111 , 50312 ] ;
108+ const feeData = await ethers . provider . getFeeData ( ) ;
109+ let gasOverrides : TxOverrides | undefined = undefined ;
110+
111+ if ( Number ( chainId ) === 50312 || Number ( chainId ) === 5031 ) {
112+ const latestBlock = await ethers . provider . getBlock ( 'latest' ) ;
113+ const has1559 =
114+ feeData . maxFeePerGas != null && feeData . maxPriorityFeePerGas != null ;
115+
116+ if ( has1559 ) {
117+ const minPriority = 1_000_000_000n ; // 1 gwei
118+ const priority =
119+ ( feeData . maxPriorityFeePerGas ?? 0n ) > 0n
120+ ? ( feeData . maxPriorityFeePerGas as bigint )
121+ : minPriority ;
122+ const base = feeData . maxFeePerGas ?? 0n ;
123+ const maxFee = base > priority * 2n ? base : priority * 2n ;
124+ gasOverrides = { maxFeePerGas : maxFee , maxPriorityFeePerGas : priority } ;
125+ logger . info (
126+ `EIP-1559 params (Somnia): maxFeePerGas=${ String (
127+ maxFee
128+ ) } , maxPriorityFeePerGas=${ String ( priority ) } `
129+ ) ;
130+ } else {
131+ const fallbackGasPrice = feeData . gasPrice ?? 6_000_000_000n ; // 6 gwei fallback
132+ gasOverrides = { gasPrice : fallbackGasPrice } ;
133+ logger . info (
134+ `Legacy gasPrice (Somnia): gasPrice=${ String ( fallbackGasPrice ) } `
135+ ) ;
136+ }
137+
138+ const est = await batcherContract . changeTransferGasLimit . estimateGas (
139+ newGasLimit ,
140+ gasOverrides || { }
141+ ) ;
142+
143+ const estWithBuffer = ( est * 120n ) / 100n ; // +20%
144+ let chosenGasLimit = Number ( estWithBuffer ) ;
145+ if ( latestBlock ?. gasLimit ) {
146+ const blockLimit = Number ( latestBlock . gasLimit ) ;
147+ chosenGasLimit = Math . min ( chosenGasLimit , Math . floor ( blockLimit * 0.95 ) ) ;
148+ }
149+ gasOverrides . gasLimit = chosenGasLimit ;
150+ logger . info (
151+ `Estimated gas: ${ est . toString ( ) } , using gasLimit=${ chosenGasLimit } `
152+ ) ;
153+ } else if ( eip1559Chains . includes ( Number ( chainId ) ) ) {
154+ gasOverrides = {
155+ maxFeePerGas : feeData . maxFeePerGas ?? feeData . gasPrice ?? undefined ,
156+ maxPriorityFeePerGas :
157+ feeData . maxPriorityFeePerGas ?? feeData . gasPrice ?? undefined
158+ } ;
159+ logger . info (
160+ `Gas params set: maxFeePerGas=${ String (
161+ gasOverrides . maxFeePerGas ?? ''
162+ ) } , maxPriorityFeePerGas=${ String (
163+ gasOverrides . maxPriorityFeePerGas ?? ''
164+ ) } , gasLimit=<auto>`
165+ ) ;
166+ } else {
167+ logger . info ( `Using default gas parameters for this network.` ) ;
168+ }
169+
170+ logger . step ( '5. Calling changeTransferGasLimit function...' ) ;
171+
172+ try {
173+ let tx ;
174+ if ( gasOverrides ) {
175+ tx = await batcherContract . changeTransferGasLimit ( newGasLimit , gasOverrides ) ;
176+ } else {
177+ tx = await batcherContract . changeTransferGasLimit ( newGasLimit ) ;
178+ }
179+
180+ logger . info ( `Transaction submitted: ${ tx . hash } ` ) ;
181+ logger . info ( 'Waiting for transaction confirmation...' ) ;
182+
183+ const receipt = await tx . wait ( ) ;
184+
185+ if ( receipt . status === 1 ) {
186+ logger . success ( '✅ Transaction confirmed successfully!' ) ;
187+ logger . info ( ` - Block Number: ${ receipt . blockNumber } ` ) ;
188+ logger . info ( ` - Gas Used: ${ receipt . gasUsed . toString ( ) } ` ) ;
189+ } else {
190+ throw new Error ( 'Transaction failed' ) ;
191+ }
192+
193+ logger . step ( '6. Verifying the gas limit change...' ) ;
194+
195+ const updatedGasLimit = await batcherContract . transferGasLimit ( ) ;
196+ logger . info ( `Updated Gas Limit: ${ updatedGasLimit . toString ( ) } ` ) ;
197+
198+ if ( updatedGasLimit . toString ( ) === newGasLimit . toString ( ) ) {
199+ logger . success ( '🎉 Gas limit successfully updated! 🎉' ) ;
200+ } else {
201+ logger . error ( `Gas limit verification failed. Expected: ${ newGasLimit . toString ( ) } , Actual: ${ updatedGasLimit . toString ( ) } ` ) ;
202+ }
203+
204+ } catch ( error ) {
205+ logger . error ( 'Failed to change gas limit:' , error ) ;
206+ throw error ;
207+ }
208+ }
209+
210+ main ( ) . catch ( ( error ) => {
211+ console . error ( error ) ;
212+ process . exitCode = 1 ;
213+ } ) ;
0 commit comments