├── .env.example ├── .gitignore ├── 01_wallet.py ├── 02_batch_bridge.py ├── 03_batch_okex_withdraw.py ├── 04_bridge_deposit.py ├── 05_zksync2_transfer.py ├── 06_zksync2_deploy_contract.py ├── 07_bridge_withdraw.py ├── README.md ├── README.zh.md ├── images ├── 00.png └── 01.png ├── requirements.txt ├── solidity ├── demo │ ├── Demo.sol │ ├── Foo.sol │ └── build │ │ └── combined.json ├── incrementer │ ├── Incrementer.sol │ └── build │ │ └── combined.json └── storage │ ├── Storage.sol │ └── build │ └── combined.json └── utils ├── __init__.py ├── private_utils.py └── read_wallets.py /.env.example: -------------------------------------------------------------------------------- 1 | # wallet private key 2 | PRIVATE_KEY=xxx 3 | 4 | # eth node url 5 | # ETH_URL=https://rpc.ankr.com/eth_goerli 6 | ETH_URL= 7 | 8 | # zksync node url 9 | # ZKSYNC_URL=https://zksync2-testnet.zksync.dev 10 | ZKSYNC_URL= 11 | 12 | # OKX api 13 | OKX_API_KEY=ZKSYNC_URL 14 | OKX_SECRET_KEY=xxx 15 | OKX_PASS_PHRASE=xxx 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.csv 3 | .idea 4 | accounts/* 5 | __pycache__ -------------------------------------------------------------------------------- /01_wallet.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | from eth_account import Account 5 | 6 | root_dir = os.path.dirname(os.path.abspath(__file__)) 7 | 8 | 9 | def saveETHWallet(jsonData): 10 | file_path = root_dir + '/accounts/wallets.json' 11 | if os.path.exists(file_path): 12 | raise RuntimeError("Wallets existed") 13 | with open(file_path, 'w') as f: 14 | json.dump(jsonData, f, indent=4) 15 | 16 | 17 | def createNewETHWallet(number): 18 | wallets = [] 19 | for id in range(number): 20 | # 添加一些随机性 21 | account = Account.create('zksync Random Seed' + str(id)) 22 | # 私钥 23 | privateKey = account._key_obj 24 | # 公钥 25 | publicKey = privateKey.public_key 26 | # 地址 27 | address = publicKey.to_checksum_address() 28 | wallet = { 29 | "index": id, 30 | "address": address, 31 | "privateKey": str(privateKey) 32 | } 33 | wallets.append(wallet) 34 | 35 | return wallets 36 | 37 | 38 | # https://eth.antcave.club/1000 39 | if __name__ == '__main__': 40 | wallets = createNewETHWallet(10) 41 | saveETHWallet(wallets) 42 | -------------------------------------------------------------------------------- /02_batch_bridge.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dotenv import load_dotenv 4 | from eth_account import Account 5 | from eth_account.signers.local import LocalAccount 6 | from eth_typing import HexStr 7 | from web3 import Web3 8 | from zksync2.core.types import Token 9 | from zksync2.manage_contracts.zksync_contract import ZkSyncContract 10 | from zksync2.module.module_builder import ZkSyncBuilder 11 | from zksync2.provider.eth_provider import EthereumProvider 12 | 13 | from utils.private_utils import EnvPrivateKey 14 | from utils.read_wallets import ReadWallets 15 | 16 | 17 | def deposit(zksync_provider: Web3, 18 | eth_web3: Web3, 19 | eth_provider: EthereumProvider, 20 | account: LocalAccount, 21 | amount: float, 22 | to: HexStr = None) -> tuple[HexStr, HexStr]: 23 | """ 24 | Deposit ETH from L1 to L2 network 25 | :param zksync_provider: 26 | Instance of ZkSync provider 27 | :param eth_web3: 28 | Instance of Ethereum Web3 provider 29 | :param eth_provider: 30 | Instance of Ethereum provider 31 | :param account: 32 | From which ETH account the withdrawal will be made 33 | :param amount: 34 | How much would the withdrawal will contain 35 | :return: 36 | Deposit transaction hashes on L1 and L2 networks 37 | """ 38 | # execute deposit on L1 network 39 | print("Executing deposit transaction on L1 network") 40 | l1_tx_receipt = eth_provider.deposit(token=Token.create_eth(), 41 | to=to, 42 | amount=Web3.to_wei(amount, 'ether'), 43 | l2_gas_limit=1123680, 44 | gas_limit=200000, 45 | gas_price=int(eth_web3.eth.gas_price * 1.2)) 46 | 47 | # Check if deposit transaction was successful 48 | if not l1_tx_receipt["status"]: 49 | raise RuntimeError("Deposit transaction on L1 network failed") 50 | 51 | # Get ZkSync contract on L1 network 52 | zksync_contract = ZkSyncContract(zksync_provider.zksync.main_contract_address, eth_web3, account) 53 | 54 | # Get hash of deposit transaction on L2 network 55 | l2_hash = zksync_provider.zksync.get_l2_hash_from_priority_op(l1_tx_receipt, zksync_contract) 56 | 57 | # Wait for deposit transaction on L2 network to be finalized (5-7 minutes) 58 | print("Waiting for deposit transaction on L2 network to be finalized (5-7 minutes)") 59 | l2_tx_receipt = zksync_provider.zksync.wait_for_transaction_receipt(transaction_hash=l2_hash, 60 | timeout=360, 61 | poll_latency=10) 62 | 63 | # return deposit transaction hashes from L1 and L2 networks 64 | return l1_tx_receipt['transactionHash'].hex(), l2_tx_receipt['transactionHash'].hex() 65 | 66 | 67 | if __name__ == "__main__": 68 | """ 69 | Batch cross-chain bridge 70 | """ 71 | load_dotenv() 72 | zksync_url = os.getenv('ZKSYNC_URL') 73 | eth_url = os.getenv('ETH_URL') 74 | if zksync_url is None: 75 | print("Err: ZKSYNC_URL not set") 76 | if eth_url is None: 77 | print("Err: ETH_URL not set") 78 | 79 | key_env = EnvPrivateKey("PRIVATE_KEY") 80 | account: LocalAccount = Account.from_key(key_env.key) 81 | 82 | zk_web3 = ZkSyncBuilder.build(zksync_url) 83 | 84 | eth_web3 = Web3(Web3.HTTPProvider(eth_url)) 85 | 86 | eth_provider = EthereumProvider(zk_web3, eth_web3, account) 87 | 88 | amount = 0.02 89 | 90 | wallets = ReadWallets() 91 | accounts = wallets.get_accounts() 92 | 93 | for wallet in accounts: 94 | l1_tx_hash, l2_tx_hash = deposit(zk_web3, eth_web3, eth_provider, account, amount, wallet['address']) 95 | 96 | print(f"L1 transaction: {l1_tx_hash}") 97 | print(f"L2 transaction: {l2_tx_hash}") 98 | -------------------------------------------------------------------------------- /03_batch_okex_withdraw.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import datetime 3 | import hmac 4 | import json 5 | import os 6 | import time 7 | 8 | import requests 9 | from dotenv import load_dotenv 10 | 11 | from utils.read_wallets import ReadWallets 12 | 13 | load_dotenv() 14 | 15 | # https://www.okx.com/docs-v5/en/#overview-api-resources-and-support 16 | BASE_URL = 'https://aws.okx.com' 17 | 18 | apiKey = os.getenv("OKX_API_KEY", None) 19 | secretKey = os.getenv("OKX_SECRET_KEY", None) 20 | passPhrase = os.getenv("OKX_PASS_PHRASE", None) 21 | 22 | 23 | def get_time(): 24 | now = datetime.datetime.utcnow() 25 | t = now.isoformat("T", "milliseconds") 26 | return t + "Z" 27 | 28 | 29 | def signature(timestamp, method, request_path, body, secret_key): 30 | if str(body) == '{}' or str(body) == 'None': 31 | body = '' 32 | message = str(timestamp) + str.upper(method) + request_path + str(body) 33 | mac = hmac.new(bytes(secret_key, encoding='utf8'), bytes(message, encoding='utf-8'), digestmod='sha256') 34 | d = mac.digest() 35 | return base64.b64encode(d) 36 | 37 | 38 | class OkexClient: 39 | def __init__(self, apikey: str, apisecret: str, password: str): 40 | self.apikey = apikey 41 | self.apisecret = apisecret 42 | self.password = password 43 | self.baseURL = 'https://www.okex.com' 44 | 45 | def get_header(self, sign, timestamp): 46 | header = { 47 | "OK-ACCESS-KEY": self.apikey, 48 | "OK-ACCESS-SIGN": sign, 49 | "OK-ACCESS-TIMESTAMP": timestamp, 50 | "OK-ACCESS-PASSPHRASE": self.password, 51 | "Content-Type": "application/json", 52 | } 53 | return header 54 | 55 | def getCurrencies(self, ccy): 56 | """ 57 | Get current ETH withdraw fee 58 | :param ccy: 59 | :return: 60 | """ 61 | path = "/api/v5/asset/currencies?ccy=" + ccy 62 | timestamp = get_time() 63 | sign = signature(timestamp, "get", path, None, secretKey) 64 | result = requests.get(BASE_URL + path, headers=self.get_header(sign, timestamp)) 65 | 66 | res = result.json() 67 | if res['code'] == '0': 68 | chain = filter(lambda coin: coin['chain'] == "ETH-ERC20", res['data']) 69 | return list(chain)[0]['minFee'] 70 | else: 71 | print("getCurrencies failed: ", result.text) 72 | 73 | def withdraw(self, ccy, amt, fee, toAddress): 74 | """ 75 | Batch withdraw ETH into Accounts 76 | :param ccy: 77 | :param amt: 78 | :param fee: 79 | :param toAddress: 80 | :return: 81 | """ 82 | 83 | path = "/api/v5/asset/withdrawal" 84 | for i in range(len(toAddress)): 85 | time.sleep(5) 86 | body = { 87 | "ccy": ccy, 88 | "dest": 4, 89 | "amt": str(amt), 90 | "toAddr": toAddress[i]['address'], 91 | "fee": str(fee), 92 | "chain": "ETH-ERC20"} 93 | 94 | timestamp = get_time() 95 | body = json.dumps(body) 96 | sign = signature(timestamp, "POST", path, body, secretKey) 97 | result = requests.post(BASE_URL + path, headers=self.get_header(sign, timestamp), data=body) 98 | res = result.json() 99 | 100 | print(result.text) 101 | if res['code'] == '0': 102 | print("Withdraw success wallet: ", i) 103 | else: 104 | print("Withdraw failed: ", result.text) 105 | 106 | 107 | if __name__ == '__main__': 108 | wallets = ReadWallets() 109 | accounts = wallets.get_accounts() 110 | 111 | client = OkexClient(apiKey, secretKey, passPhrase) 112 | fee = client.getCurrencies("ETH") 113 | print("Fee: ", fee) 114 | # client.withdraw("ETH", 0.01, fee, accounts) 115 | -------------------------------------------------------------------------------- /04_bridge_deposit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dotenv import load_dotenv 4 | from eth_account import Account 5 | from eth_account.signers.local import LocalAccount 6 | from eth_typing import HexStr 7 | from eth_utils import remove_0x_prefix 8 | from web3 import Web3 9 | from zksync2.core.types import Token 10 | from zksync2.manage_contracts.zksync_contract import ZkSyncContract 11 | from zksync2.module.module_builder import ZkSyncBuilder 12 | from zksync2.provider.eth_provider import EthereumProvider 13 | 14 | from utils.private_utils import EnvPrivateKey 15 | from utils.read_wallets import ReadWallets 16 | 17 | 18 | def deposit(zksync_provider: Web3, 19 | eth_web3: Web3, 20 | eth_provider: EthereumProvider, 21 | account: LocalAccount, 22 | amount: float, 23 | to: HexStr = None) -> tuple[HexStr, HexStr]: 24 | """ 25 | Deposit ETH from L1 to L2 network 26 | :param zksync_provider: 27 | Instance of ZkSync provider 28 | :param eth_web3: 29 | Instance of Ethereum Web3 provider 30 | :param eth_provider: 31 | Instance of Ethereum provider 32 | :param account: 33 | From which ETH account the withdrawal will be made 34 | :param amount: 35 | How much would the withdrawal will contain 36 | :return: 37 | Deposit transaction hashes on L1 and L2 networks 38 | """ 39 | # execute deposit on L1 network 40 | print("Executing deposit transaction on L1 network") 41 | l1_tx_receipt = eth_provider.deposit(token=Token.create_eth(), 42 | to=to, 43 | amount=Web3.to_wei(amount, 'ether'), 44 | l2_gas_limit=1123680, 45 | gas_limit=200000, 46 | gas_price=int(eth_web3.eth.gas_price * 1.2)) 47 | 48 | # Check if deposit transaction was successful 49 | if not l1_tx_receipt["status"]: 50 | raise RuntimeError("Deposit transaction on L1 network failed") 51 | 52 | # Get ZkSync contract on L1 network 53 | zksync_contract = ZkSyncContract(zksync_provider.zksync.main_contract_address, eth_web3, account) 54 | 55 | # Get hash of deposit transaction on L2 network 56 | l2_hash = zksync_provider.zksync.get_l2_hash_from_priority_op(l1_tx_receipt, zksync_contract) 57 | 58 | # Wait for deposit transaction on L2 network to be finalized (5-7 minutes) 59 | print("Waiting for deposit transaction on L2 network to be finalized (5-7 minutes)") 60 | l2_tx_receipt = zksync_provider.zksync.wait_for_transaction_receipt(transaction_hash=l2_hash, 61 | timeout=360, 62 | poll_latency=10) 63 | 64 | # return deposit transaction hashes from L1 and L2 networks 65 | return l1_tx_receipt['transactionHash'].hex(), l2_tx_receipt['transactionHash'].hex() 66 | 67 | 68 | if __name__ == "__main__": 69 | # Get the private key from OS environment variables 70 | # PRIVATE_KEY = bytes.fromhex(os.environ.get("PRIVATE_KEY")) 71 | 72 | load_dotenv() 73 | zksync_url = os.getenv('ZKSYNC_URL') 74 | eth_url = os.getenv('ETH_URL') 75 | if zksync_url is None: 76 | print("Err: ZKSYNC_URL not set") 77 | if eth_url is None: 78 | print("Err: ETH_URL not set") 79 | 80 | wallets = ReadWallets() 81 | accounts = wallets.get_accounts() 82 | 83 | for wallet in accounts: 84 | # Get account object by providing private key of the sender 85 | 86 | account: LocalAccount = Account.from_key(bytes.fromhex(remove_0x_prefix(HexStr(wallet['privateKey'])))) 87 | 88 | # Connect to zkSync network 89 | zk_web3 = ZkSyncBuilder.build(zksync_url) 90 | 91 | # connect to Ethereum network 92 | eth_web3 = Web3(Web3.HTTPProvider(eth_url)) 93 | 94 | # Create Ethereum provider 95 | eth_provider = EthereumProvider(zk_web3, eth_web3, account) 96 | 97 | # Perform the deposit 98 | amount = 0.001 99 | 100 | l1_tx_hash, l2_tx_hash = deposit(zk_web3, eth_web3, eth_provider, account, amount, None) 101 | 102 | print(f"L1 transaction: {l1_tx_hash}") 103 | print(f"L2 transaction: {l2_tx_hash}") 104 | -------------------------------------------------------------------------------- /05_zksync2_transfer.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dotenv import load_dotenv 4 | from eth_account import Account 5 | from eth_account.signers.local import LocalAccount 6 | from eth_typing import HexStr, HexAddress 7 | from eth_utils import to_checksum_address, remove_0x_prefix 8 | from web3 import Web3 9 | from zksync2.core.types import ZkBlockParams, EthBlockParams 10 | from zksync2.module.module_builder import ZkSyncBuilder 11 | from zksync2.signer.eth_signer import PrivateKeyEthSigner 12 | from zksync2.transaction.transaction_builders import TxFunctionCall 13 | 14 | from utils.read_wallets import ReadWallets 15 | 16 | 17 | def get_eth_balance(zk_web3: Web3, address: HexAddress) -> float: 18 | """ 19 | Get ETH balance of ETH address on zkSync network 20 | 21 | :param zk_web3: 22 | Instance of ZkSyncBuilder that interacts with zkSync network 23 | 24 | :param address: 25 | ETH address that you want to get balance of. 26 | 27 | :return: 28 | Balance of ETH address. 29 | 30 | """ 31 | 32 | # Get WEI balance of ETH address 33 | balance_wei = zk_web3.zksync.get_balance( 34 | address, 35 | EthBlockParams.LATEST.value 36 | ) 37 | 38 | # Convert WEI balance to ETH 39 | balance_eth = Web3.from_wei(balance_wei, "ether") 40 | 41 | # Return the ETH balance of the ETH address 42 | return balance_eth 43 | 44 | 45 | def transfer_eth( 46 | zk_web3: Web3, 47 | account: LocalAccount, 48 | address: HexAddress, 49 | amount: float 50 | ) -> bytes: 51 | """ 52 | Transfer ETH to a desired address on zkSync network 53 | 54 | :param zk_web3: 55 | Instance of ZkSyncBuilder that interacts with zkSync network 56 | 57 | :param account: 58 | From which account the transfer will be made 59 | 60 | :param address: 61 | Desired ETH address that you want to transfer to. 62 | 63 | :param amount: 64 | Desired ETH amount that you want to transfer. 65 | 66 | :return: 67 | The transaction hash of the deposit transaction. 68 | 69 | """ 70 | 71 | # Get chain id of zkSync network 72 | chain_id = zk_web3.zksync.chain_id 73 | 74 | # Signer is used to generate signature of provided transaction 75 | signer = PrivateKeyEthSigner(account, chain_id) 76 | 77 | # Get nonce of ETH address on zkSync network 78 | nonce = zk_web3.zksync.get_transaction_count( 79 | account.address, ZkBlockParams.COMMITTED.value 80 | ) 81 | 82 | # Get current gas price in Wei 83 | gas_price = zk_web3.zksync.gas_price 84 | 85 | # Create transaction 86 | tx_func_call = TxFunctionCall( 87 | chain_id=chain_id, 88 | nonce=nonce, 89 | from_=account.address, 90 | to=to_checksum_address(address), 91 | value=zk_web3.to_wei(amount, "ether"), 92 | data=HexStr("0x"), 93 | gas_limit=0, # UNKNOWN AT THIS STATE 94 | gas_price=gas_price, 95 | max_priority_fee_per_gas=100_000_000, 96 | ) 97 | 98 | # ZkSync transaction gas estimation 99 | estimate_gas = zk_web3.zksync.eth_estimate_gas(tx_func_call.tx) 100 | print(f"Fee for transaction is: {estimate_gas * gas_price}") 101 | 102 | # Convert transaction to EIP-712 format 103 | tx_712 = tx_func_call.tx712(estimate_gas) 104 | 105 | # Sign message & encode it 106 | signed_message = signer.sign_typed_data(tx_712.to_eip712_struct()) 107 | 108 | # Encode signed message 109 | msg = tx_712.encode(signed_message) 110 | 111 | # Transfer ETH 112 | tx_hash = zk_web3.zksync.send_raw_transaction(msg) 113 | print(f"Transaction hash is : {tx_hash.hex()}") 114 | 115 | # Wait for transaction to be included in a block 116 | tx_receipt = zk_web3.zksync.wait_for_transaction_receipt( 117 | tx_hash, timeout=240, poll_latency=0.5 118 | ) 119 | print(f"Tx status: {tx_receipt['status']}") 120 | 121 | # Return the transaction hash of the transfer 122 | return tx_hash 123 | 124 | 125 | # Set a provider 126 | 127 | if __name__ == "__main__": 128 | load_dotenv() 129 | zksync_url = os.getenv('ZKSYNC_URL') 130 | if zksync_url is None: 131 | print("Err: ZKSYNC_URL not set") 132 | 133 | # Connect to zkSync network 134 | zk_web3 = ZkSyncBuilder.build(zksync_url) 135 | 136 | wallets = ReadWallets() 137 | accounts = wallets.get_accounts() 138 | for wallet in accounts: 139 | # Get account object by providing from private key 140 | account: LocalAccount = Account.from_key(bytes.fromhex(remove_0x_prefix(HexStr(wallet['privateKey'])))) 141 | # Show balance before ETH transfer 142 | print(f"Balance before transfer : {get_eth_balance(zk_web3, account.address)} ETH") 143 | 144 | # Perform the ETH transfer 145 | transfer_eth( 146 | zk_web3, 147 | account, 148 | account.address, 149 | 0.0001 150 | ) 151 | 152 | # Show balance after ETH transfer 153 | print(f"Balance after transfer : {get_eth_balance(zk_web3, account.address)} ETH") 154 | -------------------------------------------------------------------------------- /06_zksync2_deploy_contract.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | from dotenv import load_dotenv 5 | from eth_account import Account 6 | from eth_account.signers.local import LocalAccount 7 | from eth_typing import HexAddress, HexStr 8 | from eth_utils import remove_0x_prefix 9 | from web3 import Web3 10 | from zksync2.core.types import EthBlockParams 11 | from zksync2.manage_contracts.contract_encoder_base import ContractEncoder 12 | from zksync2.module.module_builder import ZkSyncBuilder 13 | from zksync2.signer.eth_signer import PrivateKeyEthSigner 14 | from zksync2.transaction.transaction_builders import TxCreateContract 15 | 16 | from utils.read_wallets import ReadWallets 17 | 18 | 19 | def deploy_contract( 20 | zk_web3: Web3, account: LocalAccount, compiled_contract: Path 21 | ) -> HexAddress: 22 | """Deploy compiled contract on zkSync network using create() opcode 23 | 24 | :param zk_web3: 25 | Instance of ZkSyncBuilder that interacts with zkSync network 26 | 27 | :param account: 28 | From which account the deployment contract tx will be made 29 | 30 | :param compiled_contract: 31 | Compiled contract source. 32 | 33 | :return: 34 | Address of deployed contract. 35 | """ 36 | # Get chain id of zkSync network 37 | chain_id = zk_web3.zksync.chain_id 38 | 39 | # Signer is used to generate signature of provided transaction 40 | signer = PrivateKeyEthSigner(account, chain_id) 41 | 42 | # Get nonce of ETH address on zkSync network 43 | nonce = zk_web3.zksync.get_transaction_count( 44 | account.address, EthBlockParams.PENDING.value 45 | ) 46 | 47 | # Get contract ABI and bytecode information 48 | storage_contract = ContractEncoder.from_json(zk_web3, compiled_contract)[0] 49 | 50 | # Get current gas price in Wei 51 | gas_price = zk_web3.zksync.gas_price 52 | 53 | # Create deployment contract transaction 54 | create_contract = TxCreateContract( 55 | web3=zk_web3, 56 | chain_id=chain_id, 57 | nonce=nonce, 58 | from_=account.address, 59 | gas_limit=0, # UNKNOWN AT THIS STATE 60 | gas_price=gas_price, 61 | bytecode=storage_contract.bytecode, 62 | ) 63 | 64 | # ZkSync transaction gas estimation 65 | estimate_gas = zk_web3.zksync.eth_estimate_gas(create_contract.tx) 66 | print(f"Fee for transaction is: {Web3.from_wei(estimate_gas * gas_price, 'ether')} ETH") 67 | 68 | # Convert transaction to EIP-712 format 69 | tx_712 = create_contract.tx712(estimate_gas) 70 | 71 | # Sign message 72 | signed_message = signer.sign_typed_data(tx_712.to_eip712_struct()) 73 | 74 | # Encode signed message 75 | msg = tx_712.encode(signed_message) 76 | 77 | # Deploy contract 78 | tx_hash = zk_web3.zksync.send_raw_transaction(msg) 79 | 80 | # Wait for deployment contract transaction to be included in a block 81 | tx_receipt = zk_web3.zksync.wait_for_transaction_receipt( 82 | tx_hash, timeout=240, poll_latency=0.5 83 | ) 84 | 85 | print(f"Tx status: {tx_receipt['status']}") 86 | contract_address = tx_receipt["contractAddress"] 87 | 88 | print(f"Deployed contract address: {contract_address}") 89 | 90 | # Return the contract deployed address 91 | return contract_address 92 | 93 | 94 | if __name__ == "__main__": 95 | load_dotenv() 96 | zksync_url = os.getenv('ZKSYNC_URL') 97 | if zksync_url is None: 98 | print("Err: ZKSYNC_URL not set") 99 | 100 | # Connect to zkSync network 101 | zk_web3 = ZkSyncBuilder.build(zksync_url) 102 | 103 | wallets = ReadWallets() 104 | accounts = wallets.get_accounts() 105 | for wallet in accounts: 106 | # Get account object by providing from private key 107 | account: LocalAccount = Account.from_key(bytes.fromhex(remove_0x_prefix(HexStr(wallet['privateKey'])))) 108 | 109 | # Provide a compiled JSON source contract 110 | contract_path = Path("solidity/storage/build/combined.json") 111 | 112 | # Perform contract deployment 113 | deploy_contract(zk_web3, account, contract_path) 114 | -------------------------------------------------------------------------------- /07_bridge_withdraw.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dotenv import load_dotenv 4 | from eth_account import Account 5 | from eth_account.signers.local import LocalAccount 6 | from eth_typing import HexStr 7 | from eth_utils import remove_0x_prefix 8 | from hexbytes import HexBytes 9 | from web3 import Web3 10 | from web3.middleware import geth_poa_middleware 11 | from web3.types import TxReceipt 12 | from zksync2.core.types import Token 13 | from zksync2.module.module_builder import ZkSyncBuilder 14 | from zksync2.provider.eth_provider import EthereumProvider 15 | from zksync2.transaction.transaction_builders import TxWithdraw 16 | 17 | from utils.read_wallets import ReadWallets 18 | 19 | 20 | def withdraw( 21 | zksync_provider: Web3, account: LocalAccount, amount: float 22 | ) -> HexBytes: 23 | """Withdraw from Layer 2 to Layer 1 on zkSync network 24 | :param zksync_provider: 25 | Instance of ZkSync provider 26 | :param account: 27 | From which ETH account the withdrawal will be made 28 | :param amount: 29 | How much would the withdrawal will contain 30 | :return: 31 | Hash of withdraw transaction on L2 network 32 | """ 33 | 34 | # Create withdrawal transaction 35 | withdrawal = TxWithdraw( 36 | web3=zksync_provider, 37 | token=Token.create_eth(), 38 | amount=Web3.to_wei(amount, "ether"), 39 | gas_limit=0, # unknown 40 | account=account, 41 | ) 42 | 43 | # ZkSync transaction gas estimation 44 | estimated_gas = zksync_provider.zksync.eth_estimate_gas(withdrawal.tx) 45 | 46 | # Estimate gas transaction 47 | tx = withdrawal.estimated_gas(estimated_gas) 48 | 49 | # Sign the transaction 50 | signed = account.sign_transaction(tx) 51 | 52 | # Broadcast the transaction to the network 53 | return zksync_provider.zksync.send_raw_transaction(signed.rawTransaction) 54 | 55 | 56 | def finalize_withdraw( 57 | zksync_provider: Web3, ethereum_provider: EthereumProvider, withdraw_tx_hash: HexBytes 58 | ) -> TxReceipt: 59 | """ 60 | Execute finalize withdraw transaction on L1 network 61 | :type zksync_provider: 62 | Instance of ZkSync provider 63 | :param ethereum_provider 64 | Instance of EthereumProvider 65 | :param withdraw_tx_hash 66 | Hash of withdraw transaction on L2 network 67 | :return: 68 | TxReceipt of finalize withdraw transaction on L1 network 69 | """ 70 | zks_receipt = zksync_provider.zksync.wait_finalized(withdraw_tx_hash) 71 | 72 | # Check if withdraw transaction was successful 73 | if not zks_receipt["status"]: 74 | raise RuntimeError("Withdraw transaction on L2 network failed") 75 | 76 | # Execute finalize withdraw 77 | tx_receipt = ethereum_provider.finalize_withdrawal(zks_receipt["transactionHash"]) 78 | 79 | # Check if finalize withdraw transaction was successful 80 | if not tx_receipt["status"]: 81 | raise RuntimeError("Finalize withdraw transaction L1 network failed") 82 | return tx_receipt 83 | 84 | 85 | if __name__ == "__main__": 86 | # Get the private key from OS environment variables 87 | load_dotenv() 88 | zksync_url = os.getenv('ZKSYNC_URL') 89 | eth_url = os.getenv('ETH_URL') 90 | if zksync_url is None: 91 | print("Err: ZKSYNC_URL not set") 92 | if eth_url is None: 93 | print("Err: ETH_URL not set") 94 | 95 | wallets = ReadWallets() 96 | accounts = wallets.get_accounts() 97 | 98 | # Connect to zkSync network 99 | zk_web3 = ZkSyncBuilder.build(zksync_url) 100 | 101 | # Connect to Ethereum network 102 | eth_web3 = Web3(Web3.HTTPProvider(eth_url)) 103 | eth_web3.middleware_onion.inject(geth_poa_middleware, layer=0) 104 | 105 | for wallet in accounts: 106 | # Get account object by providing from private key 107 | account: LocalAccount = Account.from_key(bytes.fromhex(remove_0x_prefix(HexStr(wallet['privateKey'])))) 108 | 109 | # Create Ethereum provider 110 | eth_provider = EthereumProvider(zk_web3, eth_web3, account) 111 | 112 | amount = 0.01 113 | 114 | # Perform the withdrawal 115 | withdraw_tx_hash = withdraw(zk_web3, account, amount) 116 | 117 | print(f"Withdraw transaction hash: {withdraw_tx_hash.hex()}") 118 | print("Wait for withdraw transaction to be finalized on L2 network (11-24 hours)") 119 | print("Read more about withdrawal delay: https://era.zksync.io/docs/dev/troubleshooting/withdrawal-delay.html") 120 | print("When withdraw transaction is finalized, execute 10_finalize_withdrawal.py script " 121 | "with WITHDRAW_TX_HASH environment variable set") 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ZkSync Era Network Batch Airdrop Script 2 | 3 | 4 | ## Feature 5 | - [√] Batch of production wallets 6 | - [√] Turn into ETH in batches through cross -chain 7 | - [√] Transfer to ETH through OKX batch (recommended method) 8 | - [√] Batch wallet operation -cross -chain (ETH-> ZKSYNC2) 9 | - [√] Batch wallet operation-transfer 10 | - [√] Batch wallet operation-deployment contract 11 | - [√] Batch wallet operation -cross -chain (ZKSYNC2-> ETH) 12 | - [] Batch wallet operation -SWAP 13 | - [] Batch wallet operation -Mint NFT 14 | 15 | 16 | ## config 17 | > `cp .env.example .env` 18 | 19 | 20 | - ETH_URL: eth node url 21 | - ZKSYNC_URL : zksync node url 22 | - OKX_XX: (optional) 23 | - 24 | ``` 25 | # wallet private key 26 | PRIVATE_KEY=xxx 27 | 28 | # eth node url 29 | # ETH_URL=https://rpc.ankr.com/eth_goerli 30 | ETH_URL= 31 | 32 | # zksync node url 33 | # ZKSYNC_URL=https://zksync2-testnet.zksync.dev 34 | ZKSYNC_URL= 35 | 36 | # OKX api (optional) 37 | OKX_API_KEY=ZKSYNC_URL 38 | OKX_SECRET_KEY=xxx 39 | OKX_PASS_PHRASE=xxx 40 | 41 | ``` 42 | 43 | ## notice 44 | 45 | If similar problems occur `Fail with error 'mv'` during runing, you can modify the package and run again. 46 | 47 | ![](./images/00.png) 48 | ![](./images/01.png) 49 | 50 | 51 | ## Risk 52 | - This project script is hosted on the world's largest github, open, transparent, and secure, and refuses any private chat scripts. 53 | - The distribution of handling fees from the exchange in the script involves the exchange's apiKey, which must not be exposed to others. 54 | - Private key accounts are very important! The script only runs on your own computer, and refuses any proxy interaction. -------------------------------------------------------------------------------- /README.zh.md: -------------------------------------------------------------------------------- 1 | ## ZkSync Era Network 批量交互脚本 2 | 3 | 4 | ## 基本功能 5 | - [√] 批量生成钱包 6 | - [√] 通过跨链(bridge.zksync.io)的方式批量转入ETH 7 | - [√] 通过OKX批量转入ETH (推荐方式) 8 | - [√] 批量钱包操作-跨链(ETH -> zksync2) 9 | - [√] 批量钱包操作-转账 10 | - [√] 批量钱包操作-部署合约 11 | - [√] 批量钱包操作-跨链(zksync2 -> ETH) 12 | - [ ] 批量钱包操作-swap 13 | - [ ] 批量钱包操作-mint NFT 14 | 15 | ## 配置 16 | > `cp .env.example .env` 17 | 18 | 19 | - ETH_URL: eth 节点 url 20 | - ZKSYNC_URL : zksync 节点 url 21 | - OKX_XX: 并不是必须得,用到再配置 22 | ``` 23 | # wallet private key 24 | PRIVATE_KEY=xxx 25 | 26 | # eth node url 27 | # ETH_URL=https://rpc.ankr.com/eth_goerli 28 | ETH_URL= 29 | 30 | # zksync node url 31 | # ZKSYNC_URL=https://zksync2-testnet.zksync.dev 32 | ZKSYNC_URL= 33 | 34 | # OKX api (optional) 35 | OKX_API_KEY=ZKSYNC_URL 36 | OKX_SECRET_KEY=xxx 37 | OKX_PASS_PHRASE=xxx 38 | 39 | ``` 40 | 41 | ## 运行问题 42 | 43 | 如果在运行过程中出现类似的问题' Fail with error 'mv' ',您可以修改包并重新运行。当时提了一个[PR](https://github.com/zksync-sdk/zksync2-python/pull/37#event-9583137191) , 作者也做了合并,目前还没有发布新的版本。 44 | ![](./images/00.png) 45 | ![](./images/01.png) 46 | 47 | 48 | ## 风险 49 | - 代码仅供交流使用,使用中任何资金风险概不负责; 50 | - 请保管好自己的私钥,做好备份,防止丢失; -------------------------------------------------------------------------------- /images/00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixbe/zksync2_script/eb03912c4db872f6f33dbf832d5eb5830efb4c15/images/00.png -------------------------------------------------------------------------------- /images/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixbe/zksync2_script/eb03912c4db872f6f33dbf832d5eb5830efb4c15/images/01.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | python-dotenv==1.0.0 2 | zksync2==0.5.0 3 | eth-account==0.9.0 -------------------------------------------------------------------------------- /solidity/demo/Demo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | // demo Foo.sol from current directory 5 | import "./Foo.sol"; 6 | 7 | // demo {symbol1 as alias, symbol2} from "filename"; 8 | import {Unauthorized, add as func, Point} from "./Foo.sol"; 9 | 10 | contract Demo { 11 | // Initialize Foo.sol 12 | Foo public foo = new Foo(); 13 | 14 | // Test Foo.sol by getting it's name. 15 | function getFooName() public view returns (string memory) { 16 | return foo.name(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /solidity/demo/Foo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | struct Point { 5 | uint x; 6 | uint y; 7 | } 8 | 9 | error Unauthorized(address caller); 10 | 11 | function add(uint x, uint y) pure returns (uint) { 12 | return x + y; 13 | } 14 | 15 | contract Foo { 16 | string public name = "Foo"; 17 | } 18 | -------------------------------------------------------------------------------- /solidity/demo/build/combined.json: -------------------------------------------------------------------------------- 1 | { 2 | "contracts": { 3 | "solidity/demo/Demo.sol:Demo": { 4 | "abi": [ 5 | { 6 | "inputs": [], 7 | "name": "foo", 8 | "outputs": [ 9 | { 10 | "internalType": "contract Foo", 11 | "name": "", 12 | "type": "address" 13 | } 14 | ], 15 | "stateMutability": "view", 16 | "type": "function" 17 | }, 18 | { 19 | "inputs": [], 20 | "name": "getFooName", 21 | "outputs": [ 22 | { 23 | "internalType": "string", 24 | "name": "", 25 | "type": "string" 26 | } 27 | ], 28 | "stateMutability": "view", 29 | "type": "function" 30 | } 31 | ], 32 | "bin": "00040000000000020003000000000002000000000301001900000060033002700000005b04300197000300000041035500020000000103550000005b0030019d000100000000001f0000008001000039000000400010043f00000001012001900000002d0000c13d0000000001000031000000040110008c000000840000413d0000000201000367000000000101043b000000e001100270000000620210009c000000730000613d000000630110009c000000840000c13d0000000001000416000000000110004c000000840000c13d000000040100008a00000000011000310000006402000041000000000310004c000000000300001900000000030240190000006401100197000000000410004c000000000200a019000000640110009c00000000010300190000000001026019000000000110004c000000840000c13d000000000100041a0000005f01100197000000800010043f0000006a01000041000001690001042e0000000001000416000000000110004c000000840000c13d0000005c01000041000000a40010043f00000000010004140000005d02000041000000800020043f000000840000043f0000006002000039000000c40020043f0000005b020000410000005b0310009c0000000001028019000000c0011002100000005e011001c7000000e40000043f00008006020000390168015e0000040f0000000102200190000000480000613d000000000101043b000000000210004c000000860000c13d000000030100036700000001040000310000004d0000013d0003000000010355000000000201001900000060022002700001005b0020019d0000005b04200197000000400200043d0000001f0340018f00000005044002720000005a0000613d000000000500001900000005065002100000000007620019000000000661034f000000000606043b00000000006704350000000105500039000000000645004b000000520000413d000000000530004c000000690000613d0000000504400210000000000141034f00000000044200190000000303300210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000005b0100004100000001030000310000005b0430009c00000000030180190000005b0420009c000000000102401900000040011002100000006002300210000000000112019f0000016a000104300000000001000416000000000110004c000000840000c13d000000040100008a00000000011000310000006402000041000000000310004c000000000300001900000000030240190000006401100197000000000410004c000000000200a019000000640110009c00000000010300190000000001026019000000000110004c000000900000613d00000000010000190000016a000104300000005f01100197000000000200041a0000006002200197000000000112019f000000000010041b0000002001000039000001000010044300000120000004430000006101000041000001690001042e000000000200041a000000400800043d0000006501000041000000000018043500000000010004140000005f02200197000000040320008c0000009b0000c13d00000003010003670000000103000031000000ae0000013d0000005b030000410000005b0410009c00000000010380190000005b0480009c00000000030840190000004003300210000000c001100210000000000131019f00000066011001c7000300000008001d016801630000040f0000000308000029000000000301001900000060033002700001005b0030019d0000005b0330019700030000000103550000000102200190000001020000613d0000001f0230018f0000000504300272000000ba0000613d000000000500001900000005065002100000000007680019000000000661034f000000000606043b00000000006704350000000105500039000000000645004b000000b20000413d000000000520004c000000c90000613d0000000504400210000000000141034f00000000044800190000000302200210000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000001f01300039000000200900008a000000000191016f0000000002810019000000000112004b00000000010000190000000101004039000000670420009c000000fc0000213d0000000101100190000000fc0000c13d0000006401000041000000200430008c000000000400001900000000040140190000006405300197000000000650004c000000000100a019000000640550009c000000000104c019000000400020043f000000000110004c000000840000c13d0000000001080433000000670410009c000000840000213d000000000583001900000000018100190000001f031000390000006404000041000000000653004b0000000006000019000000000604801900000064033001970000006407500197000000000873004b0000000004008019000000000373013f000000640330009c00000000030600190000000003046019000000000330004c000000840000c13d0000000043010434000000670130009c000000fc0000213d0000003f01300039000000000191016f0000000001210019000000670610009c000001280000a13d000000680100004100000000001004350000004101000039000000040010043f00000069010000410000016a00010430000000400200043d0000001f0430018f00000005033002720000010f0000613d000000000500001900000005065002100000000007620019000000000661034f000000000606043b00000000006704350000000105500039000000000635004b000001070000413d000000000540004c0000011e0000613d0000000503300210000000000131034f00000000033200190000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000005b0100004100000001030000310000005b0430009c00000000030180190000005b0420009c000000000102401900000040011002100000006002300210000000000112019f0000016a00010430000000400010043f00000000013204360000000006430019000000000556004b000000840000213d000300000009001d000000000530004c000001380000613d000000000500001900000000061500190000000007450019000000000707043300000000007604350000002005500039000000000635004b000001310000413d000000000313001900000000000304350000002003000039000000400400043d000200000004001d00000000053404360000000003020433000100000003001d00000000003504350000004002400039016801510000040f00000001010000290000005f011000390000000302000029000000000121016f0000005b020000410000005b0310009c000000000102801900000002040000290000005b0340009c000000000204401900000040022002100000006001100210000000000121019f000001690001042e000000000430004c0000015b0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000001540000413d00000000012300190000000000010435000000000001042d00000161002104210000000102000039000000000001042d0000000002000019000000000001042d00000166002104230000000102000039000000000001042d0000000002000019000000000001042d0000016800000432000001690001042e0000016a00010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff01000039f11f3d0f6f21fa0d138e5347957e112f0fe63aa12e3b7c6d6022945a9c4d535bdea7cd8a978f128b93471df48c7dbab89d703809115bdc118c235bfd0200000000000000000000000000000000000084000000800000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000c626126100000000000000000000000000000000000000000000000000000000c2985578800000000000000000000000000000000000000000000000000000000000000006fdde03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000000000000e847e4f0071639f5d73bf1d1c818ea74666111d633a0f502e3587723d11b691a", 33 | "factory-deps": { 34 | "01000039f11f3d0f6f21fa0d138e5347957e112f0fe63aa12e3b7c6d6022945a": "/solidity/demo/Foo.sol:Foo" 35 | } 36 | }, 37 | "solidity/demo/Foo.sol:Foo": { 38 | "abi": [ 39 | { 40 | "inputs": [], 41 | "name": "name", 42 | "outputs": [ 43 | { 44 | "internalType": "string", 45 | "name": "", 46 | "type": "string" 47 | } 48 | ], 49 | "stateMutability": "view", 50 | "type": "function" 51 | } 52 | ], 53 | "bin": "00010000000000020001000000000002000000000301001900000060033002700000002c0030019d0000002c033001970000000102200190000000340000c13d000000040230008c0000006a0000413d000000000101043b0000003001100197000000310110009c0000006a0000c13d0000000001000416000000000110004c0000006a0000c13d000000040100008a00000000011000310000003202000041000000000310004c000000000300001900000000030240190000003201100197000000000410004c000000000200a019000000320110009c00000000010300190000000001026019000000000110004c0000006a0000c13d000000000100041a000000010310019000000001021002700000007f0420018f00000000020460190000001f0420008c00000000040000190000000104002039000000000441013f0000000104400190000000440000c13d000000800020043f000000000330004c0000006c0000c13d000001000300008a000000000131016f000000a00010043f000000000120004c000000c001000039000000a0010060390000007b0000013d0000008001000039000000400010043f0000000001000416000000000110004c0000006a0000c13d000000000100041a000000010210019000000001011002700000007f0310018f000000000301c0190000001f0130008c00000000010000190000000101002039000000010110018f000000000112004b0000004a0000613d000000360100004100000000001004350000002201000039000000040010043f0000003701000041000000ac00010430000000200130008c000000630000413d000100000003001d00000000000004350000002c0100004100000000020004140000002c0320009c0000000001024019000000c0011002100000002d011001c7000080100200003900aa00a50000040f00000001022001900000006a0000613d000000000101043b00000001020000290000001f0220003900000005022002700000000002210019000000000321004b000000630000813d000000000001041b0000000101100039000000000321004b0000005f0000413d0000002e01000041000000000010041b0000002001000039000001000010044300000120000004430000002f01000041000000ab0001042e0000000001000019000000ac00010430000000a0010000390000000000000435000000000320004c000000870000613d000000330100004100000000040000190000000003040019000000000401041a000000a005300039000000000045043500000001011000390000002004300039000000000524004b000000720000413d000000c0013000390000001f01100039000000200200008a000000000121016f0000003402100041000000350220009c000000870000813d000000360100004100000000001004350000004101000039000000040010043f0000003701000041000000ac00010430000000400010043f00000020020000390000000003210436000000800200043d00000000002304350000004003100039000000000420004c000000970000613d00000000040000190000000005340019000000a006400039000000000606043300000000006504350000002004400039000000000524004b000000900000413d000000000332001900000000000304350000005f02200039000000200300008a000000000232016f0000002c030000410000002c0420009c00000000020380190000002c0410009c000000000103801900000040011002100000006002200210000000000112019f000000ab0001042e000000a8002104230000000102000039000000000001042d0000000002000019000000000001042d000000aa00000432000000ab0001042e000000ac0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0200000000000000000000000000000000000020000000000000000000000000466f6f00000000000000000000000000000000000000000000000000000000060000000200000000000000000000000000000040000001000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000006fdde03000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff00000000000000804e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000bdea15b201354fbcb883f804afa93fac6616815f3b001aba37b2c0d0f50a18f9", 54 | "factory-deps": {} 55 | } 56 | }, 57 | "version": "0.8.19+commit.7dd6d404.Linux.g++", 58 | "zk_version": "1.3.9" 59 | } -------------------------------------------------------------------------------- /solidity/incrementer/Incrementer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.0; 3 | 4 | contract Incrementer { 5 | uint256 incrementer; 6 | uint256 value; 7 | 8 | constructor(uint _incrementer){ 9 | incrementer = _incrementer; 10 | value = 0; 11 | } 12 | 13 | function increment() public { 14 | value += incrementer; 15 | } 16 | 17 | function get() public view returns (uint256) { 18 | return value; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /solidity/incrementer/build/combined.json: -------------------------------------------------------------------------------- 1 | { 2 | "contracts": { 3 | "solidity/incrementer/Incrementer.sol:Incrementer": { 4 | "abi": [ 5 | { 6 | "inputs": [ 7 | { 8 | "internalType": "uint256", 9 | "name": "_incrementer", 10 | "type": "uint256" 11 | } 12 | ], 13 | "stateMutability": "nonpayable", 14 | "type": "constructor" 15 | }, 16 | { 17 | "inputs": [], 18 | "name": "get", 19 | "outputs": [ 20 | { 21 | "internalType": "uint256", 22 | "name": "", 23 | "type": "uint256" 24 | } 25 | ], 26 | "stateMutability": "view", 27 | "type": "function" 28 | }, 29 | { 30 | "inputs": [], 31 | "name": "increment", 32 | "outputs": [], 33 | "stateMutability": "nonpayable", 34 | "type": "function" 35 | } 36 | ], 37 | "bin": "000200000000000200010000000103550000006001100270000000250010019d0000000101200190000000280000c13d0000008001000039000000400010043f0000000001000031000000040110008c0000007a0000413d0000000101000367000000000101043b000000e0011002700000002a0210009c000000690000613d0000002b0110009c0000007a0000c13d0000000001000416000000000110004c0000007a0000c13d000000040100008a00000000011000310000002602000041000000000310004c000000000300001900000000030240190000002601100197000000000410004c000000000200a019000000260110009c00000000010300190000000001026019000000000110004c0000007a0000c13d0000000101000039000000000101041a000000800010043f0000002c010000410000008f0001042e0000000001000416000000000110004c0000007a0000c13d00000000010000310000009f02100039000000200300008a000000000232016f0000007f0320008c000000370000213d000000280100004100000000001004350000004101000039000000040010043f00000029010000410000009000010430000000400020043f0000001f0210018f00000001030003670000000504100272000000450000613d00000000050000190000000506500210000000000763034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b0000003d0000413d000000000520004c000000540000613d0000000504400210000000000343034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f00000000002404350000002602000041000000200310008c000000000300001900000000030240190000002601100197000000000410004c000000000200a019000000260110009c00000000010300190000000001026019000000000110004c0000007a0000c13d000000800100043d000000000010041b0000000101000039000000000001041b00000020010000390000010000100443000001200000044300000027010000410000008f0001042e0000000001000416000000000110004c0000007a0000c13d000000040100008a00000000011000310000002602000041000000000310004c000000000300001900000000030240190000002601100197000000000410004c000000000200a019000000260110009c00000000010300190000000001026019000000000110004c0000007c0000613d000000000100001900000090000104300000000101000039000000000301041a000000000200041a0000000002230019000000000332004b0000000003000019000000010300403900000001033001900000008b0000613d000000280100004100000000001004350000001101000039000000040010043f00000029010000410000009000010430000000000021041b00000000010000190000008f0001042e0000008e000004320000008f0001042e000000900001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff800000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000400000010000000000000000004e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000d09de08a000000000000000000000000000000000000000000000000000000006d4ce63c000000000000000000000000000000000000002000000080000000000000000000000000000000000000000000000000000000000000000000000000000000009c101c102c8f8e6a911eba880cec4d8a4f42d4b1aa7da24fe11fe295320eebdd", 38 | "factory-deps": {} 39 | } 40 | }, 41 | "version": "0.8.19+commit.7dd6d404.Linux.g++", 42 | "zk_version": "1.3.9" 43 | } -------------------------------------------------------------------------------- /solidity/storage/Storage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.0; 3 | 4 | contract Storage { 5 | uint256 counter; 6 | 7 | function set(uint256 _value) public { 8 | counter = _value; 9 | } 10 | 11 | function get() public view returns (uint256) { 12 | return counter; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /solidity/storage/build/combined.json: -------------------------------------------------------------------------------- 1 | { 2 | "contracts": { 3 | "solidity/storage/Storage.sol:Storage": { 4 | "abi": [ 5 | { 6 | "inputs": [], 7 | "name": "get", 8 | "outputs": [ 9 | { 10 | "internalType": "uint256", 11 | "name": "", 12 | "type": "uint256" 13 | } 14 | ], 15 | "stateMutability": "view", 16 | "type": "function" 17 | }, 18 | { 19 | "inputs": [ 20 | { 21 | "internalType": "uint256", 22 | "name": "_value", 23 | "type": "uint256" 24 | } 25 | ], 26 | "name": "set", 27 | "outputs": [], 28 | "stateMutability": "nonpayable", 29 | "type": "function" 30 | } 31 | ], 32 | "bin": "000200000000000200010000000103550000006001100270000000130010019d0000008001000039000000400010043f0000000101200190000000290000c13d0000000001000031000000040110008c000000420000413d0000000101000367000000000101043b000000e001100270000000150210009c000000310000613d000000160110009c000000420000c13d0000000001000416000000000110004c000000420000c13d000000040100008a00000000011000310000001702000041000000200310008c000000000300001900000000030240190000001701100197000000000410004c000000000200a019000000170110009c00000000010300190000000001026019000000000110004c000000420000c13d00000004010000390000000101100367000000000101043b000000000010041b0000000001000019000000490001042e0000000001000416000000000110004c000000420000c13d0000002001000039000001000010044300000120000004430000001401000041000000490001042e0000000001000416000000000110004c000000420000c13d000000040100008a00000000011000310000001702000041000000000310004c000000000300001900000000030240190000001701100197000000000410004c000000000200a019000000170110009c00000000010300190000000001026019000000000110004c000000440000613d00000000010000190000004a00010430000000000100041a000000800010043f0000001801000041000000490001042e0000004800000432000000490001042e0000004a00010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000000000000000000000000000006d4ce63c0000000000000000000000000000000000000000000000000000000060fe47b1800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000000000000d5c7d2782d356f4a1a2e458d242d21e07a04810c9f771eed6501083e07288c87", 33 | "factory-deps": {} 34 | } 35 | }, 36 | "version": "0.8.19+commit.7dd6d404.Linux.g++", 37 | "zk_version": "1.3.9" 38 | } -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixbe/zksync2_script/eb03912c4db872f6f33dbf832d5eb5830efb4c15/utils/__init__.py -------------------------------------------------------------------------------- /utils/private_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | from eth_typing import HexStr 3 | from eth_utils import remove_0x_prefix 4 | 5 | 6 | class EnvPrivateKey: 7 | def __init__(self, env: str): 8 | env = os.getenv(env, None) 9 | if env is None: 10 | raise LookupError(f"Can't build key from {env}") 11 | self._key = bytes.fromhex(remove_0x_prefix(HexStr(env))) 12 | 13 | @property 14 | def key(self) -> bytes: 15 | return self._key -------------------------------------------------------------------------------- /utils/read_wallets.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | root_dir = os.path.dirname(os.path.abspath(__file__)) 5 | 6 | 7 | class ReadWallets: 8 | def get_accounts(self): 9 | with open(root_dir + '/../accounts/wallets.json', 'r') as fcc_file: 10 | return json.load(fcc_file) 11 | --------------------------------------------------------------------------------