|
| 1 | +#!/usr/bin/env python3.9 |
| 2 | + |
| 3 | +import os |
| 4 | +import argparse |
| 5 | +from web3 import Web3, Account, HTTPProvider, eth |
| 6 | +from web3.middleware import ( |
| 7 | + buffered_gas_estimate_middleware, |
| 8 | + construct_sign_and_send_raw_middleware, |
| 9 | +) |
| 10 | + |
| 11 | +node_uri_pat = "https://{chain}.infura.io/v3/{infura_key}" |
| 12 | +batcher_abi = [ |
| 13 | + { |
| 14 | + "inputs": [], |
| 15 | + "name": "tick", |
| 16 | + "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], |
| 17 | + "stateMutability": "nonpayable", |
| 18 | + "type": "function", |
| 19 | + } |
| 20 | +] |
| 21 | + |
| 22 | +default_batcher_address = "0x613d088F2e5a2ED91635016483dAFa3cd47a8964" |
| 23 | + |
| 24 | + |
| 25 | +def new_wallet_account(w3: Web3, eth_private_key): |
| 26 | + return new_wallet_account_list(w3, [eth_private_key])[0] |
| 27 | + |
| 28 | + |
| 29 | +def new_wallet_account_list(w3: Web3, eth_private_keys, name=None): |
| 30 | + """ |
| 31 | + Creates new eth accounts and registers them (including the private keys). |
| 32 | + The new accounts may have no funds. |
| 33 | + This function is more efficient than calling new_wallet_account() many times |
| 34 | + as it creates only one middleware layer. |
| 35 | + """ |
| 36 | + accounts = [Account.from_key(eth_private_key) for eth_private_key in eth_private_keys] |
| 37 | + |
| 38 | + w3.middleware_onion.add(construct_sign_and_send_raw_middleware(accounts), name=name) |
| 39 | + w3.middleware_onion.remove("gas_estimate") |
| 40 | + w3.middleware_onion.add(buffered_gas_estimate_middleware, name="gas_estimate") |
| 41 | + return [account.address for account in accounts] |
| 42 | + |
| 43 | + |
| 44 | +def parse_args(): |
| 45 | + parser = argparse.ArgumentParser( |
| 46 | + description="Collect pending withdrawals waiting for l1_recipient" |
| 47 | + ) |
| 48 | + parser.add_argument( |
| 49 | + "--chain", |
| 50 | + type=str, |
| 51 | + choices=["mainnet", "sepolia"], |
| 52 | + default="mainnet", |
| 53 | + help="Select Ethereum chain (default: mainnet)", |
| 54 | + ) |
| 55 | + parser.add_argument( |
| 56 | + "--batcher_contract", |
| 57 | + type=str, |
| 58 | + default=default_batcher_address, |
| 59 | + help="L1 withdrawal batching contract", |
| 60 | + ) |
| 61 | + args = parser.parse_args() |
| 62 | + args.batcher_contract = Web3.toChecksumAddress(args.batcher_contract) |
| 63 | + return args |
| 64 | + |
| 65 | + |
| 66 | +def main(): |
| 67 | + args = parse_args() |
| 68 | + account = Account.from_key(os.environ["PK"]) |
| 69 | + node_uri = node_uri_pat.format(chain=args.chain, infura_key=os.environ["INFURA_KEY"]) |
| 70 | + w3 = Web3(HTTPProvider(node_uri)) |
| 71 | + |
| 72 | + assert w3.isConnected() |
| 73 | + w3.eth.default_account = new_wallet_account(w3, account.key) |
| 74 | + batcher = w3.eth.contract(address=args.batcher_contract, abi=batcher_abi) |
| 75 | + print(w3.eth.default_account, batcher.address) |
| 76 | + |
| 77 | + pending_funds = batcher.functions.tick().call() |
| 78 | + if pending_funds: |
| 79 | + print(f"Awaiting {pending_funds//10**6} withdrawal waiting.") |
| 80 | + th = batcher.functions.tick().transact() |
| 81 | + print(f"Pending withdrawal collected, tx hash: {th.hex()}") |
| 82 | + else: |
| 83 | + print("nothing to tick") |
| 84 | + |
| 85 | + |
| 86 | +if __name__ == "__main__": |
| 87 | + main() |
0 commit comments