From 4e4fd56d6f2a053103242564ac402218f0aaf052 Mon Sep 17 00:00:00 2001 From: petarTxFusion Date: Fri, 19 Jan 2024 15:58:14 +0100 Subject: [PATCH] chore: lint code --- scripts/setup.py | 34 +- scripts/wait.py | 4 +- tests/integration/test_config.py | 4 +- tests/integration/test_paymaster.py | 123 ++- tests/integration/test_wallet.py | 270 ++++-- tests/integration/test_zksync_contract.py | 126 +-- tests/integration/test_zksync_web3.py | 607 ++++++++----- tests/unit/test_config.py | 4 +- tests/unit/test_contract_deploy.py | 28 +- tests/unit/test_eip712.py | 120 ++- tests/unit/test_eth_signer.py | 50 +- tests/unit/test_transaction712.py | 77 +- tests/unit/test_utils.py | 12 +- zksync2/account/utils.py | 47 +- zksync2/account/wallet.py | 6 +- zksync2/account/wallet_l1.py | 802 ++++++++++++------ zksync2/account/wallet_l2.py | 120 ++- zksync2/core/types.py | 11 +- zksync2/core/utils.py | 18 +- zksync2/eip712/domain_separator.py | 17 +- zksync2/eip712/struct.py | 137 +-- zksync2/eip712/types.py | 75 +- .../manage_contracts/contract_encoder_base.py | 25 +- zksync2/manage_contracts/contract_factory.py | 2 +- zksync2/manage_contracts/paymaster_utils.py | 2 - .../precompute_contract_deployer.py | 1 + zksync2/manage_contracts/utils.py | 10 +- zksync2/module/request_types.py | 1 + zksync2/module/response_types.py | 33 +- zksync2/module/zksync_module.py | 477 ++++++----- zksync2/transaction/transaction_builders.py | 457 +++++----- 31 files changed, 2283 insertions(+), 1417 deletions(-) diff --git a/scripts/setup.py b/scripts/setup.py index 7056e9e..d4f8ce8 100644 --- a/scripts/setup.py +++ b/scripts/setup.py @@ -1,4 +1,4 @@ -#Deposits token to l2 so that tests can run +# Deposits token to l2 so that tests can run import json from pathlib import Path @@ -15,40 +15,48 @@ def main(): zksync = ZkSyncBuilder.build("http://127.0.0.1:3050") eth_web3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545")) - account: LocalAccount = Account.from_key("0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110") + account: LocalAccount = Account.from_key( + "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" + ) wallet = Wallet(zksync, eth_web3, account) zksync_contract = eth_web3.eth.contract( Web3.to_checksum_address(zksync.zksync.main_contract_address), - abi=zksync_abi_default()) + abi=zksync_abi_default(), + ) deposit_token(wallet, eth_web3, zksync, zksync_contract) + def deposit_token(wallet: Wallet, eth_web3: Web3, zksync: Web3, zksync_contract): amount = 50 l1_address = load_token() - tx_hash = wallet.deposit(DepositTransaction(Web3.to_checksum_address(l1_address), - amount, - wallet.address, - approve_erc20=True, - refund_recipient=wallet.address)) + tx_hash = wallet.deposit( + DepositTransaction( + Web3.to_checksum_address(l1_address), + amount, + wallet.address, + approve_erc20=True, + refund_recipient=wallet.address, + ) + ) l1_tx_receipt = eth_web3.eth.wait_for_transaction_receipt(tx_hash) l2_hash = zksync.zksync.get_l2_hash_from_priority_op(l1_tx_receipt, zksync_contract) - zksync.zksync.wait_for_transaction_receipt(transaction_hash=l2_hash, - timeout=360, - poll_latency=10) + zksync.zksync.wait_for_transaction_receipt( + transaction_hash=l2_hash, timeout=360, poll_latency=10 + ) def load_token(): directory = Path(__file__).parent.parent path = directory / "tests/integration/token.json" - with open(path, 'r') as file: + with open(path, "r") as file: data = json.load(file) return data[0]["address"] if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/scripts/wait.py b/scripts/wait.py index ac2faa2..b37ce30 100644 --- a/scripts/wait.py +++ b/scripts/wait.py @@ -30,9 +30,9 @@ def wait_for_node(): raise Exception("Maximum retries exceeded.") -if __name__ == '__main__': +if __name__ == "__main__": current_directory = os.path.dirname(os.path.abspath(__file__)) - parent_directory = os.path.join(current_directory, '..') + parent_directory = os.path.join(current_directory, "..") sys.path.append(parent_directory) try: wait_for_node() diff --git a/tests/integration/test_config.py b/tests/integration/test_config.py index a8eb2c1..d328b13 100644 --- a/tests/integration/test_config.py +++ b/tests/integration/test_config.py @@ -30,4 +30,6 @@ class TestEnvironment: eth_server: str -LOCAL_ENV = TestEnvironment(EnvType.LOCAL_HOST, "http://127.0.0.1:3050", "http://127.0.0.1:8545") +LOCAL_ENV = TestEnvironment( + EnvType.LOCAL_HOST, "http://127.0.0.1:3050", "http://127.0.0.1:8545" +) diff --git a/tests/integration/test_paymaster.py b/tests/integration/test_paymaster.py index f8fb1b0..5b56865 100644 --- a/tests/integration/test_paymaster.py +++ b/tests/integration/test_paymaster.py @@ -7,10 +7,15 @@ from tests.integration.test_config import LOCAL_ENV from tests.integration.test_zksync_contract import generate_random_salt -from zksync2.manage_contracts.contract_encoder_base import ContractEncoder, JsonConfiguration +from zksync2.manage_contracts.contract_encoder_base import ( + ContractEncoder, + JsonConfiguration, +) from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses from zksync2.manage_contracts.paymaster_utils import PaymasterFlowEncoder -from zksync2.manage_contracts.precompute_contract_deployer import PrecomputeContractDeployer +from zksync2.manage_contracts.precompute_contract_deployer import ( + PrecomputeContractDeployer, +) from zksync2.manage_contracts.utils import nonce_holder_abi_default from zksync2.module.module_builder import ZkSyncBuilder from zksync2.core.types import Token, EthBlockParams, ZkBlockParams, PaymasterParams @@ -18,16 +23,22 @@ from eth_account.signers.local import LocalAccount from zksync2.signer.eth_signer import PrivateKeyEthSigner from tests.contracts.utils import contract_path -from zksync2.transaction.transaction_builders import TxFunctionCall, TxCreate2Contract, TxCreateAccount +from zksync2.transaction.transaction_builders import ( + TxFunctionCall, + TxCreate2Contract, + TxCreateAccount, +) # mint tx hash of Test coins: # https://goerli.explorer.zksync.io/address/0xFC174650BDEbE4D94736442307D4D7fdBe799EeC#contract -class PaymasterTests(TestCase): +class PaymasterTests(TestCase): ETH_TOKEN = Token.create_eth() - PRIVATE_KEY = bytes.fromhex("1f0245d47b3a84299aeb121ac33c2dbd1cdb3d3c2079b3240e63796e75ee8b70") + PRIVATE_KEY = bytes.fromhex( + "1f0245d47b3a84299aeb121ac33c2dbd1cdb3d3c2079b3240e63796e75ee8b70" + ) ETH_AMOUNT_BALANCE = 1 ETH_TEST_NET_AMOUNT_BALANCE = Decimal(1) @@ -35,17 +46,20 @@ class PaymasterTests(TestCase): Web3.to_checksum_address("0x" + "0" * 40), Web3.to_checksum_address("0xFC174650BDEbE4D94736442307D4D7fdBe799EeC"), "SERC20", - 18) + 18, + ) SALT = keccak(text="TestPaymaster") def setUp(self) -> None: self.env = LOCAL_ENV self.web3 = ZkSyncBuilder.build(self.env.zksync_server) - self.account: LocalAccount = Account.from_key("0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110") + self.account: LocalAccount = Account.from_key( + "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" + ) self.chain_id = self.web3.zksync.chain_id self.signer = PrivateKeyEthSigner(self.account, self.chain_id) - #self.custom_paymaster = ContractEncoder.from_json(self.web3, contract_path("CustomPaymaster.json")) + # self.custom_paymaster = ContractEncoder.from_json(self.web3, contract_path("CustomPaymaster.json")) def _is_deployed(self): return len(self.web3.zksync.get_code(self.paymaster_address)) > 0 @@ -64,15 +78,20 @@ def deploy_paymaster(self, token_address): nonce = self.web3.zksync.get_transaction_count( self.account.address, EthBlockParams.PENDING.value ) - nonce_holder = self.web3.zksync.contract(address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, - abi=nonce_holder_abi_default()) - deployment_nonce = nonce_holder.functions.getDeploymentNonce(self.account.address).call( - { - "from": self.account.address - }) + nonce_holder = self.web3.zksync.contract( + address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, + abi=nonce_holder_abi_default(), + ) + deployment_nonce = nonce_holder.functions.getDeploymentNonce( + self.account.address + ).call({"from": self.account.address}) deployer = PrecomputeContractDeployer(self.web3) - precomputed_address = deployer.compute_l2_create_address(self.account.address, deployment_nonce) - token_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + precomputed_address = deployer.compute_l2_create_address( + self.account.address, deployment_nonce + ) + token_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) encoded_constructor = token_contract.encode_constructor(**constructor_arguments) gas_price = self.web3.zksync.gas_price create_account = TxCreateAccount( @@ -104,20 +123,24 @@ def test_paymaster(self): self.account.address, EthBlockParams.PENDING.value ) random_salt = generate_random_salt() - token_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + token_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) abi = token_contract.abi encoded_constructor = token_contract.encode_constructor(**constructor_arguments) gas_price = self.web3.zksync.gas_price - create2_contract = TxCreate2Contract(web3=self.web3, - chain_id=chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, - gas_price=gas_price, - bytecode=token_contract.bytecode, - salt=random_salt, - call_data=encoded_constructor) + create2_contract = TxCreate2Contract( + web3=self.web3, + chain_id=chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, + gas_price=gas_price, + bytecode=token_contract.bytecode, + salt=random_salt, + call_data=encoded_constructor, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create2_contract.tx) tx_712 = create2_contract.tx712(estimate_gas) signed_message = signer.sign_typed_data(tx_712.to_eip712_struct()) @@ -129,12 +152,18 @@ def test_paymaster(self): token_contract_address = tx_receipt["contractAddress"] token_contract = self.web3.zksync.contract(token_contract_address, abi=abi) - mint_tx = token_contract.functions.mint(self.account.address, 15).build_transaction({ - "nonce": self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value), - "from": self.account.address, - "maxPriorityFeePerGas": 1_000_000, - "maxFeePerGas": self.web3.zksync.gas_price, - }) + mint_tx = token_contract.functions.mint( + self.account.address, 15 + ).build_transaction( + { + "nonce": self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ), + "from": self.account.address, + "maxPriorityFeePerGas": 1_000_000, + "maxFeePerGas": self.web3.zksync.gas_price, + } + ) signed = self.account.sign_transaction(mint_tx) tx_hash = self.web3.zksync.send_raw_transaction(signed.rawTransaction) @@ -146,7 +175,9 @@ def test_paymaster(self): tx_func_call = TxFunctionCall( chain_id=self.web3.zksync.chain_id, - nonce=self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value), + nonce=self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ), from_=self.account.address, to=paymaster_address, value=self.web3.to_wei(1, "ether"), @@ -164,24 +195,33 @@ def test_paymaster(self): tx_hash, timeout=240, poll_latency=0.5 ) - calladata = token_contract.encodeABI(fn_name="mint", args=[self.account.address, 7]) + calladata = token_contract.encodeABI( + fn_name="mint", args=[self.account.address, 7] + ) - paymaster_params = PaymasterParams(**{ - "paymaster": paymaster_address, - "paymaster_input": self.web3.to_bytes( - hexstr=PaymasterFlowEncoder(self.web3).encode_approval_based(token_contract_address, 1, b'')) - }) + paymaster_params = PaymasterParams( + **{ + "paymaster": paymaster_address, + "paymaster_input": self.web3.to_bytes( + hexstr=PaymasterFlowEncoder(self.web3).encode_approval_based( + token_contract_address, 1, b"" + ) + ), + } + ) tx_func_call = TxFunctionCall( chain_id=self.web3.zksync.chain_id, - nonce=self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value), + nonce=self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ), from_=self.account.address, to=token_contract_address, data=calladata, gas_limit=0, # Unknown at this state, estimation is done in next step gas_price=gas_price, max_priority_fee_per_gas=100_000_000, - paymaster_params=paymaster_params + paymaster_params=paymaster_params, ) estimate_gas = self.web3.zksync.eth_estimate_gas(tx_func_call.tx) tx_712 = tx_func_call.tx712(estimate_gas) @@ -192,4 +232,3 @@ def test_paymaster(self): self.web3.zksync.wait_for_transaction_receipt( tx_hash, timeout=240, poll_latency=0.5 ) - diff --git a/tests/integration/test_wallet.py b/tests/integration/test_wallet.py index 785aa52..435b2e6 100644 --- a/tests/integration/test_wallet.py +++ b/tests/integration/test_wallet.py @@ -12,10 +12,24 @@ from tests.integration.test_config import LOCAL_ENV, EnvPrivateKey from tests.integration.test_zksync_contract import generate_random_salt from zksync2.account.wallet import Wallet -from zksync2.core.types import Token, DepositTransaction, ADDRESS_DEFAULT, FullDepositFee, \ - RequestExecuteCallMsg, TransactionOptions, TransferTransaction, WithdrawTransaction, EthBlockParams -from zksync2.manage_contracts.contract_encoder_base import ContractEncoder, JsonConfiguration -from zksync2.manage_contracts.precompute_contract_deployer import PrecomputeContractDeployer +from zksync2.core.types import ( + Token, + DepositTransaction, + ADDRESS_DEFAULT, + FullDepositFee, + RequestExecuteCallMsg, + TransactionOptions, + TransferTransaction, + WithdrawTransaction, + EthBlockParams, +) +from zksync2.manage_contracts.contract_encoder_base import ( + ContractEncoder, + JsonConfiguration, +) +from zksync2.manage_contracts.precompute_contract_deployer import ( + PrecomputeContractDeployer, +) from zksync2.manage_contracts.utils import zksync_abi_default, get_erc20_abi from zksync2.module.module_builder import ZkSyncBuilder from zksync2.signer.eth_signer import PrivateKeyEthSigner @@ -31,16 +45,17 @@ def setUp(self) -> None: self.eth_web3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545")) self.account: LocalAccount = Account.from_key(env_key.key) self.wallet = Wallet(self.zksync, self.eth_web3, self.account) - self.zksync_contract = self.eth_web3.eth.contract(Web3.to_checksum_address(self.zksync.zksync.main_contract_address), - abi=zksync_abi_default()) - + self.zksync_contract = self.eth_web3.eth.contract( + Web3.to_checksum_address(self.zksync.zksync.main_contract_address), + abi=zksync_abi_default(), + ) def load_token(self): directory = Path(__file__).parent path = directory / Path("token.json") - with open(path, 'r') as file: - data = json.load(file) + with open(path, "r") as file: + data = json.load(file) l1_address = data[0]["address"] l2_address = self.zksync.zksync.l2_token_address(l1_address) return l1_address, l2_address @@ -67,12 +82,12 @@ def test_get_l2_token_address(self): self.assertEqual(address, ADDRESS_DEFAULT, "Should return l2 token address") def test_approve_erc20(self): - usdc_token = \ - Token( - Web3.to_checksum_address("0xd35cceead182dcee0f148ebac9447da2c4d449c4"), - Web3.to_checksum_address("0x852a4599217e76aa725f0ada8bf832a1f57a8a91"), - "USDC", - 6) + usdc_token = Token( + Web3.to_checksum_address("0xd35cceead182dcee0f148ebac9447da2c4d449c4"), + Web3.to_checksum_address("0x852a4599217e76aa725f0ada8bf832a1f57a8a91"), + "USDC", + 6, + ) amount_usdc = 5 is_approved = self.wallet.approve_erc20(usdc_token.l1_address, amount_usdc) @@ -88,7 +103,7 @@ def test_get_balance(self): def test_get_all_balances(self): balances = self.wallet.get_all_balances() - self.assertGreaterEqual(len(balances), 1,"Should return all balances") + self.assertGreaterEqual(len(balances), 1, "Should return all balances") def test_l2_bridge_contracts(self): contracts = self.wallet.get_l2_bridge_contracts() @@ -96,17 +111,23 @@ def test_l2_bridge_contracts(self): def test_get_address(self): address = self.wallet.address - self.assertEqual(address, "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", "Should return wallet address") + self.assertEqual( + address, + "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", + "Should return wallet address", + ) def test_get_deployment_nonce(self): nonce = self.wallet.get_deployment_nonce() self.assertIsNotNone(nonce, "Should return deployment nonce") def test_prepare_deposit_transaction(self): - options = TransactionOptions(gas_price=1_000_000_007, - max_fee_per_gas=1_000_000_010, - value=288_992_007_000_000, - max_priority_fee_per_gas=1_000_000_000) + options = TransactionOptions( + gas_price=1_000_000_007, + max_fee_per_gas=1_000_000_010, + value=288_992_007_000_000, + max_priority_fee_per_gas=1_000_000_000, + ) tx = DepositTransaction( token=ADDRESS_DEFAULT, amount=7_000_000, @@ -116,7 +137,7 @@ def test_prepare_deposit_transaction(self): gas_per_pubdata_byte=800, refund_recipient=self.wallet.address, l2_value=7_000_000, - options=options + options=options, ) transaction = self.wallet.prepare_deposit_tx(tx) @@ -129,86 +150,117 @@ def test_prepare_deposit_transaction_token(self): amount=5, refund_recipient=self.wallet.address, to=self.wallet.get_l2_bridge_contracts().erc20.address, - custom_bridge_data=HexBytes("0xe8b99b1b00000000000000000000000036615cf349d7f6344891b1e7ca7c72883f5dc049000000000000000000000000881567b68502e6d7a7a3556ff4313b637ba47f4e0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000008e0f6000000000000000000000000000000000000000000000000000000000000032000000000000000000000000036615cf349d7f6344891b1e7ca7c72883f5dc049") + custom_bridge_data=HexBytes( + "0xe8b99b1b00000000000000000000000036615cf349d7f6344891b1e7ca7c72883f5dc049000000000000000000000000881567b68502e6d7a7a3556ff4313b637ba47f4e0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000008e0f6000000000000000000000000000000000000000000000000000000000000032000000000000000000000000036615cf349d7f6344891b1e7ca7c72883f5dc049" + ), ) transaction = self.wallet.prepare_deposit_tx(tx) self.assertEqual(tx, transaction) def test_estimate_gas_deposit(self): - estimated_gas = self.wallet.estimate_gas_deposit(DepositTransaction( - token=ADDRESS_DEFAULT, - to=self.wallet.address, - amount=5, - refund_recipient=self.wallet.address - )) + estimated_gas = self.wallet.estimate_gas_deposit( + DepositTransaction( + token=ADDRESS_DEFAULT, + to=self.wallet.address, + amount=5, + refund_recipient=self.wallet.address, + ) + ) self.assertGreaterEqual(estimated_gas, 110_581) def test_deposit_eth(self): amount = 7_000_000_000 l2_balance_before = self.wallet.get_balance() - tx_hash = self.wallet.deposit(DepositTransaction(token=Token.create_eth().l1_address, - amount=amount)) + tx_hash = self.wallet.deposit( + DepositTransaction(token=Token.create_eth().l1_address, amount=amount) + ) tx_receipt = self.eth_web3.eth.wait_for_transaction_receipt(tx_hash) - l2_hash = self.zksync.zksync.get_l2_hash_from_priority_op(tx_receipt, self.zksync_contract) - self.zksync.zksync.wait_for_transaction_receipt(transaction_hash=l2_hash, - timeout=360, - poll_latency=10) + l2_hash = self.zksync.zksync.get_l2_hash_from_priority_op( + tx_receipt, self.zksync_contract + ) + self.zksync.zksync.wait_for_transaction_receipt( + transaction_hash=l2_hash, timeout=360, poll_latency=10 + ) l2_balance_after = self.wallet.get_balance() self.assertEqual(1, tx_receipt["status"], "L1 transaction should be successful") - self.assertGreaterEqual(l2_balance_after - l2_balance_before, amount, "Balance on L2 should be increased") + self.assertGreaterEqual( + l2_balance_after - l2_balance_before, + amount, + "Balance on L2 should be increased", + ) # @skip("Integration test, used for develop purposes only") def test_deposit_token(self): amount = 5 l1_address, l2_address = self.load_token() - is_approved = self.wallet.approve_erc20(Web3.to_checksum_address(l1_address), amount) + is_approved = self.wallet.approve_erc20( + Web3.to_checksum_address(l1_address), amount + ) self.assertTrue(is_approved) - balance_l2_beore = self.wallet.get_balance(token_address=Web3.to_checksum_address(l2_address)) + balance_l2_beore = self.wallet.get_balance( + token_address=Web3.to_checksum_address(l2_address) + ) - tx_hash = self.wallet.deposit(DepositTransaction(Web3.to_checksum_address(l1_address), - amount, - self.account.address, - approve_erc20=True, - refund_recipient=self.wallet.address)) + tx_hash = self.wallet.deposit( + DepositTransaction( + Web3.to_checksum_address(l1_address), + amount, + self.account.address, + approve_erc20=True, + refund_recipient=self.wallet.address, + ) + ) l1_tx_receipt = self.eth_web3.eth.wait_for_transaction_receipt(tx_hash) - l2_hash = self.zksync.zksync.get_l2_hash_from_priority_op(l1_tx_receipt, self.zksync_contract) - self.zksync.zksync.wait_for_transaction_receipt(transaction_hash=l2_hash, - timeout=360, - poll_latency=10) + l2_hash = self.zksync.zksync.get_l2_hash_from_priority_op( + l1_tx_receipt, self.zksync_contract + ) + self.zksync.zksync.wait_for_transaction_receipt( + transaction_hash=l2_hash, timeout=360, poll_latency=10 + ) - balance_l2_after = self.wallet.get_balance(token_address=Web3.to_checksum_address(l2_address)) + balance_l2_after = self.wallet.get_balance( + token_address=Web3.to_checksum_address(l2_address) + ) self.assertGreater(balance_l2_after, balance_l2_beore) def test_full_required_deposit_fee(self): - fee_data=FullDepositFee( + fee_data = FullDepositFee( base_cost=285096500000000, l1_gas_limit=110581, l2_gas_limit=570193, max_fee_per_gas=1500000010, - max_priority_fee_per_gas=1500000000) - fee = self.wallet.get_full_required_deposit_fee(DepositTransaction( - token=ADDRESS_DEFAULT, - to=self.wallet.address - )) + max_priority_fee_per_gas=1500000000, + ) + fee = self.wallet.get_full_required_deposit_fee( + DepositTransaction(token=ADDRESS_DEFAULT, to=self.wallet.address) + ) self.assertEqual(fee, fee_data) def test_transfer_eth(self): amount = 7_000_000_000 - balance_before_transfer = self.zksync.zksync.get_balance(Web3.to_checksum_address(self.address2)) - tx_hash = self.wallet.transfer(TransferTransaction(to=Web3.to_checksum_address(self.address2), - token_address=ADDRESS_DEFAULT, - amount=amount)) + balance_before_transfer = self.zksync.zksync.get_balance( + Web3.to_checksum_address(self.address2) + ) + tx_hash = self.wallet.transfer( + TransferTransaction( + to=Web3.to_checksum_address(self.address2), + token_address=ADDRESS_DEFAULT, + amount=amount, + ) + ) self.zksync.zksync.wait_for_transaction_receipt( tx_hash, timeout=240, poll_latency=0.5 ) - balance_after_transfer = self.zksync.zksync.get_balance(Web3.to_checksum_address(self.address2)) + balance_after_transfer = self.zksync.zksync.get_balance( + Web3.to_checksum_address(self.address2) + ) self.assertEqual(balance_after_transfer - balance_before_transfer, amount) @@ -216,15 +268,23 @@ def test_transfer_token(self): amount = 5 l1_address, l2_address = self.load_token() - balance_before = self.zksync.zksync.zks_get_balance(self.address2, token_address=l2_address) - tx_hash = self.wallet.transfer(TransferTransaction(to=Web3.to_checksum_address(self.address2), - token_address=Web3.to_checksum_address(l2_address), - amount=amount)) + balance_before = self.zksync.zksync.zks_get_balance( + self.address2, token_address=l2_address + ) + tx_hash = self.wallet.transfer( + TransferTransaction( + to=Web3.to_checksum_address(self.address2), + token_address=Web3.to_checksum_address(l2_address), + amount=amount, + ) + ) self.zksync.zksync.wait_for_transaction_receipt( tx_hash, timeout=240, poll_latency=0.5 ) - balance_after = self.zksync.zksync.zks_get_balance(self.address2, token_address=l2_address) + balance_after = self.zksync.zksync.zks_get_balance( + self.address2, token_address=l2_address + ) self.assertEqual(balance_after - balance_before, amount) @@ -232,7 +292,11 @@ def test_withdraw_eth(self): l2_balance_before = self.wallet.get_balance() amount = 0.005 - withdraw_tx_hash = self.wallet.withdraw(WithdrawTransaction(token=Token.create_eth().l1_address, amount=Web3.to_wei(amount, "ether"))) + withdraw_tx_hash = self.wallet.withdraw( + WithdrawTransaction( + token=Token.create_eth().l1_address, amount=Web3.to_wei(amount, "ether") + ) + ) self.zksync.zksync.wait_for_transaction_receipt( withdraw_tx_hash, timeout=240, poll_latency=0.5 @@ -240,37 +304,55 @@ def test_withdraw_eth(self): l2_balance_after = self.wallet.get_balance() - self.assertGreater(l2_balance_before, l2_balance_after, "L2 balance should be lower after withdrawal") + self.assertGreater( + l2_balance_before, + l2_balance_after, + "L2 balance should be lower after withdrawal", + ) def test_withdraw_token(self): l1_address, l2_address = self.load_token() - l2_balance_before = self.wallet.get_balance(token_address=Web3.to_checksum_address(l2_address)) + l2_balance_before = self.wallet.get_balance( + token_address=Web3.to_checksum_address(l2_address) + ) - withdraw_tx_hash = self.wallet.withdraw(WithdrawTransaction(Web3.to_checksum_address(l2_address), 5)) + withdraw_tx_hash = self.wallet.withdraw( + WithdrawTransaction(Web3.to_checksum_address(l2_address), 5) + ) self.zksync.zksync.wait_for_transaction_receipt( withdraw_tx_hash, timeout=240, poll_latency=0.5 ) - l2_balance_after = self.wallet.get_balance(token_address=Web3.to_checksum_address(l2_address)) + l2_balance_after = self.wallet.get_balance( + token_address=Web3.to_checksum_address(l2_address) + ) - self.assertGreater(l2_balance_before, l2_balance_after, "L2 balance should be lower after withdrawal") + self.assertGreater( + l2_balance_before, + l2_balance_after, + "L2 balance should be lower after withdrawal", + ) def test_get_request_execute_transaction(self): - result = self.wallet.get_request_execute_transaction(RequestExecuteCallMsg( - contract_address=self.zksync_contract.address, - call_data=HexStr("0x"), - l2_value=7_000_000_000 - )) + result = self.wallet.get_request_execute_transaction( + RequestExecuteCallMsg( + contract_address=self.zksync_contract.address, + call_data=HexStr("0x"), + l2_value=7_000_000_000, + ) + ) self.assertIsNotNone(result) def test_estimate_request_execute(self): - result = self.wallet.estimate_gas_request_execute(RequestExecuteCallMsg( - contract_address=self.zksync_contract.address, - call_data=HexStr("0x"), - l2_value=7_000_000_000 - )) + result = self.wallet.estimate_gas_request_execute( + RequestExecuteCallMsg( + contract_address=self.zksync_contract.address, + call_data=HexStr("0x"), + l2_value=7_000_000_000, + ) + ) self.assertGreater(result, 0) @@ -278,13 +360,27 @@ def test_request_execute(self): amount = 7_000_000_000 l2_balance_before = self.wallet.get_balance() - tx_hash = self.wallet.request_execute(RequestExecuteCallMsg(contract_address=Web3.to_checksum_address(self.zksync.zksync.main_contract_address), - call_data=HexStr("0x"), - l2_value=amount, - l2_gas_limit=900_000)) + tx_hash = self.wallet.request_execute( + RequestExecuteCallMsg( + contract_address=Web3.to_checksum_address( + self.zksync.zksync.main_contract_address + ), + call_data=HexStr("0x"), + l2_value=amount, + l2_gas_limit=900_000, + ) + ) l1_tx_receipt = self.eth_web3.eth.wait_for_transaction_receipt(tx_hash) - l2_hash = self.zksync.zksync.get_l2_hash_from_priority_op(l1_tx_receipt, self.zksync_contract) + l2_hash = self.zksync.zksync.get_l2_hash_from_priority_op( + l1_tx_receipt, self.zksync_contract + ) self.zksync.zksync.wait_for_transaction_receipt(l2_hash) l2_balance_after = self.wallet.get_balance() - self.assertEqual(1, l1_tx_receipt["status"], "L1 transaction should be successful") - self.assertGreaterEqual(l2_balance_after - l2_balance_before, amount, "Balance on L2 should be increased") + self.assertEqual( + 1, l1_tx_receipt["status"], "L1 transaction should be successful" + ) + self.assertGreaterEqual( + l2_balance_after - l2_balance_before, + amount, + "Balance on L2 should be increased", + ) diff --git a/tests/integration/test_zksync_contract.py b/tests/integration/test_zksync_contract.py index 9a99de5..843ab14 100644 --- a/tests/integration/test_zksync_contract.py +++ b/tests/integration/test_zksync_contract.py @@ -17,7 +17,6 @@ def generate_random_salt() -> bytes: class ZkSyncWeb3Tests(TestCase): - def setUp(self) -> None: env = LOCAL_ENV env_key = "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" @@ -26,14 +25,17 @@ def setUp(self) -> None: self.account: LocalAccount = Account.from_key(env_key) self.chain_id = self.zksync.zksync.chain_id self.signer = PrivateKeyEthSigner(self.account, self.chain_id) - self.zksync_contract = self.eth_web3.eth.contract(Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), abi=zksync_abi_default()) + self.zksync_contract = self.eth_web3.eth.contract( + Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), + abi=zksync_abi_default(), + ) def test_facet_addresses_call(self): facets = self.zksync_contract.functions.facets().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), } ) @@ -42,104 +44,125 @@ def test_get_first_unprocessed_priority_tx(self): { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_governor(self): governor = self.zksync_contract.functions.getGovernor().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_l2_bootloader_bytecode_hash(self): - bytecode_hash = self.zksync_contract.functions.getL2BootloaderBytecodeHash().call( - { - "chainId": self.eth_web3.eth.chain_id, - "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + bytecode_hash = ( + self.zksync_contract.functions.getL2BootloaderBytecodeHash().call( + { + "chainId": self.eth_web3.eth.chain_id, + "from": self.account.address, + "nonce": self.eth_web3.eth.get_transaction_count( + self.account.address + ), + } + ) + ) def test_get_l2_default_account_bytecode_hash(self): - bytecode_hash = self.zksync_contract.functions.getL2DefaultAccountBytecodeHash().call( - { - "chainId": self.eth_web3.eth.chain_id, - "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + bytecode_hash = ( + self.zksync_contract.functions.getL2DefaultAccountBytecodeHash().call( + { + "chainId": self.eth_web3.eth.chain_id, + "from": self.account.address, + "nonce": self.eth_web3.eth.get_transaction_count( + self.account.address + ), + } + ) + ) def test_get_proposed_upgrade_hash(self): upgrade_hash = self.zksync_contract.functions.getPendingGovernor().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_proposed_upgrade_timestamp(self): upgrade_timestamp = self.zksync_contract.functions.getPriorityQueueSize().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_total_blocks_committed(self): total = self.zksync_contract.functions.getProtocolVersion().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_total_blocks_executed(self): total = self.zksync_contract.functions.getTotalBatchesCommitted().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_total_blocks_verified(self): total = self.zksync_contract.functions.getTotalBatchesExecuted().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_total_priority_txs(self): priority = self.zksync_contract.functions.getTotalBatchesVerified().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_is_diamond_storage_frozen(self): v = self.zksync_contract.functions.isDiamondStorageFrozen().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_verifier(self): verifier = self.zksync_contract.functions.getVerifier().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_get_verifier_params(self): verifier_params = ret = self.zksync_contract.functions.getVerifierParams().call( { "chainId": self.eth_web3.eth.chain_id, "from": self.account.address, - 'nonce': self.eth_web3.eth.get_transaction_count(self.account.address), - }) + "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), + } + ) def test_request_l2_transaction(self): RECOMMENDED_DEPOSIT_L2_GAS_LIMIT = 10000000 @@ -147,22 +170,27 @@ def test_request_l2_transaction(self): gas_price = self.eth_web3.eth.gas_price gas_limit = RecommendedGasLimit.EXECUTE.value l2_value = 0 - contract = self.eth_web3.eth.contract(Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), abi=zksync_abi_default()) - tx = contract.functions.requestL2Transaction(Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), - l2_value, - b'', - RECOMMENDED_DEPOSIT_L2_GAS_LIMIT, - DEPOSIT_GAS_PER_PUBDATA_LIMIT, - [], - Web3.to_checksum_address(self.zksync.zksync.zks_main_contract())).build_transaction( + contract = self.eth_web3.eth.contract( + Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), + abi=zksync_abi_default(), + ) + tx = contract.functions.requestL2Transaction( + Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), + l2_value, + b"", + RECOMMENDED_DEPOSIT_L2_GAS_LIMIT, + DEPOSIT_GAS_PER_PUBDATA_LIMIT, + [], + Web3.to_checksum_address(self.zksync.zksync.zks_main_contract()), + ).build_transaction( { "nonce": self.eth_web3.eth.get_transaction_count(self.account.address), - 'from': self.account.address, + "from": self.account.address, "gasPrice": gas_price, "gas": gas_limit, - "value": 0 - }) + "value": 0, + } + ) signed_tx = self.account.sign_transaction(tx) tx_hash = self.eth_web3.eth.send_raw_transaction(signed_tx.rawTransaction) tx_receipt = self.eth_web3.eth.wait_for_transaction_receipt(tx_hash) - diff --git a/tests/integration/test_zksync_web3.py b/tests/integration/test_zksync_web3.py index 62a77a8..da2d1fd 100644 --- a/tests/integration/test_zksync_web3.py +++ b/tests/integration/test_zksync_web3.py @@ -12,14 +12,23 @@ from tests.contracts.utils import contract_path from zksync2.core.types import Token, ZkBlockParams, EthBlockParams, ADDRESS_DEFAULT -from zksync2.manage_contracts.contract_encoder_base import ContractEncoder, JsonConfiguration +from zksync2.manage_contracts.contract_encoder_base import ( + ContractEncoder, + JsonConfiguration, +) from zksync2.manage_contracts.contract_factory import LegacyContractFactory from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses -from zksync2.manage_contracts.precompute_contract_deployer import PrecomputeContractDeployer +from zksync2.manage_contracts.precompute_contract_deployer import ( + PrecomputeContractDeployer, +) from zksync2.manage_contracts.utils import nonce_holder_abi_default from zksync2.module.module_builder import ZkSyncBuilder from zksync2.signer.eth_signer import PrivateKeyEthSigner -from zksync2.transaction.transaction_builders import TxFunctionCall, TxCreateContract, TxCreate2Contract +from zksync2.transaction.transaction_builders import ( + TxFunctionCall, + TxCreateContract, + TxCreate2Contract, +) from .test_config import LOCAL_ENV, EnvType @@ -34,21 +43,29 @@ class ZkSyncWeb3Tests(TestCase): def setUp(self) -> None: self.env = LOCAL_ENV self.web3 = ZkSyncBuilder.build(self.env.zksync_server) - self.account: LocalAccount = Account.from_key("7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110") + self.account: LocalAccount = Account.from_key( + "7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" + ) self.chain_id = self.web3.zksync.chain_id self.signer = PrivateKeyEthSigner(self.account, self.chain_id) self.counter_address = None self.test_tx_hash = None # INFO: use deploy_erc20_token_builder to get new address if self.env.type == EnvType.LOCAL_HOST: - self.some_erc20_address = Web3.to_checksum_address("0x37b96512962FC7773E06237116BE693Eb2b3cD51") + self.some_erc20_address = Web3.to_checksum_address( + "0x37b96512962FC7773E06237116BE693Eb2b3cD51" + ) if self.env.type == EnvType.TESTNET: # https://goerli.explorer.zksync.io/address/0xd782e03F4818A7eDb0bc5f70748F67B4e59CdB33#contract - self.some_erc20_address = Web3.to_checksum_address("0xd782e03F4818A7eDb0bc5f70748F67B4e59CdB33") - self.ERC20_Token = Token(l1_address=ADDRESS_DEFAULT, - l2_address=self.some_erc20_address, - symbol="SERC20", - decimals=18) + self.some_erc20_address = Web3.to_checksum_address( + "0xd782e03F4818A7eDb0bc5f70748F67B4e59CdB33" + ) + self.ERC20_Token = Token( + l1_address=ADDRESS_DEFAULT, + l2_address=self.some_erc20_address, + symbol="SERC20", + decimals=18, + ) @skip("Integration test, used for develop purposes only") def test_send_money(self): @@ -61,11 +78,11 @@ def test_send_money(self): "gasPrice": Web3.to_wei(1, "gwei"), "gas": gas_limit, "to": self.account.address, - "value": web3.to_wei(1000000, 'ether') + "value": web3.to_wei(1000000, "ether"), } tx_hash = web3.eth.send_transaction(transaction) txn_receipt = web3.eth.wait_for_transaction_receipt(tx_hash) - self.assertEqual(txn_receipt['status'], 1) + self.assertEqual(txn_receipt["status"], 1) # @skip("Integration test, used for develop purposes only") def test_get_l1_balance(self): @@ -75,26 +92,34 @@ def test_get_l1_balance(self): # @skip("Integration test, used for develop purposes only") def test_get_l2_balance(self): - zk_balance = self.web3.zksync.get_balance(self.account.address, EthBlockParams.LATEST.value) + zk_balance = self.web3.zksync.get_balance( + self.account.address, EthBlockParams.LATEST.value + ) # @skip("Integration test, used for develop purposes only") def test_get_nonce(self): - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ) # @skip("Integration test, used for develop purposes only") def test_get_transaction_receipt(self): if self.test_tx_hash is None: - nonce = self.web3.zksync.get_transaction_count(self.account.address, ZkBlockParams.COMMITTED.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, ZkBlockParams.COMMITTED.value + ) gas_price = self.web3.zksync.gas_price - tx_func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.account.address, - value=Web3.to_wei(0.01, 'ether'), - data=HexStr("0x"), - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=gas_price, - max_priority_fee_per_gas=100000000) + tx_func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.account.address, + value=Web3.to_wei(0.01, "ether"), + data=HexStr("0x"), + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=gas_price, + max_priority_fee_per_gas=100000000, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(tx_func_call.tx) tx_712 = tx_func_call.tx712(estimate_gas) @@ -107,17 +132,21 @@ def test_get_transaction_receipt(self): # @skip("Integration test, used for develop purposes only") def test_get_transaction(self): if self.test_tx_hash is None: - nonce = self.web3.zksync.get_transaction_count(self.account.address, ZkBlockParams.COMMITTED.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, ZkBlockParams.COMMITTED.value + ) gas_price = self.web3.zksync.gas_price - tx_func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.account.address, - value=Web3.to_wei(0.01, 'ether'), - data=HexStr("0x"), - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=gas_price, - max_priority_fee_per_gas=100000000) + tx_func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.account.address, + value=Web3.to_wei(0.01, "ether"), + data=HexStr("0x"), + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=gas_price, + max_priority_fee_per_gas=100000000, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(tx_func_call.tx) tx_712 = tx_func_call.tx712(estimate_gas) @@ -126,95 +155,127 @@ def test_get_transaction(self): self.test_tx_hash = self.web3.zksync.send_raw_transaction(msg) self.web3.zksync.wait_for_transaction_receipt(self.test_tx_hash) tx = self.web3.zksync.get_transaction(self.test_tx_hash) - self.assertEqual(tx['from'], self.account.address) + self.assertEqual(tx["from"], self.account.address) # @skip("Integration test, used for develop purposes only") def test_estimate_gas_transfer_native(self): - nonce = self.web3.zksync.get_transaction_count(self.account.address, ZkBlockParams.COMMITTED.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, ZkBlockParams.COMMITTED.value + ) gas_price = self.web3.zksync.gas_price - func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.account.address, - gas_limit=0, - gas_price=gas_price) + func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.account.address, + gas_limit=0, + gas_price=gas_price, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(func_call.tx) - self.assertGreater(estimate_gas, 0, "test_estimate_gas_transfer_native, estimate_gas must be greater 0") + self.assertGreater( + estimate_gas, + 0, + "test_estimate_gas_transfer_native, estimate_gas must be greater 0", + ) # @skip("Integration test, used for develop purposes only") def test_estimate_fee_transfer_native(self): - nonce = self.web3.zksync.get_transaction_count(self.account.address, ZkBlockParams.COMMITTED.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, ZkBlockParams.COMMITTED.value + ) gas_price = self.web3.zksync.gas_price - func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.account.address, - gas_limit=0, - gas_price=gas_price) + func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.account.address, + gas_limit=0, + gas_price=gas_price, + ) estimated_fee = self.web3.zksync.zks_estimate_fee(func_call.tx) # @skip("Integration test, used for develop purposes only") def test_transfer_native_to_self(self): - nonce = self.web3.zksync.get_transaction_count(self.account.address, ZkBlockParams.COMMITTED.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, ZkBlockParams.COMMITTED.value + ) gas_price = self.web3.zksync.gas_price - tx_func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.account.address, - value=Web3.to_wei(0.01, 'ether'), - data=HexStr("0x"), - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=gas_price, - max_priority_fee_per_gas=100000000) + tx_func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.account.address, + value=Web3.to_wei(0.01, "ether"), + data=HexStr("0x"), + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=gas_price, + max_priority_fee_per_gas=100000000, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(tx_func_call.tx) tx_712 = tx_func_call.tx712(estimate_gas) singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) def deploy_erc20_token_builder(self): - nonce = self.web3.zksync.get_transaction_count(self.account.address, ZkBlockParams.COMMITTED.value) - counter_contract = ContractEncoder.from_json(self.web3, contract_path("SomeERC20.json")) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, ZkBlockParams.COMMITTED.value + ) + counter_contract = ContractEncoder.from_json( + self.web3, contract_path("SomeERC20.json") + ) random_salt = generate_random_salt() gas_price = self.web3.zksync.gas_price - create_contract = TxCreateContract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=gas_price, - bytecode=counter_contract.bytecode, - salt=random_salt) + create_contract = TxCreateContract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=gas_price, + bytecode=counter_contract.bytecode, + salt=random_salt, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create_contract.tx) tx_712 = create_contract.tx712(estimate_gas) singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) - self.assertEqual(1, tx_receipt['status']) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) + self.assertEqual(1, tx_receipt["status"]) contract_address = tx_receipt["contractAddress"] if self.some_erc20_address is None: self.some_erc20_address = contract_address def mint_some_erc20(self, amount: int): - some_erc20_encoder = ContractEncoder.from_json(self.web3, contract_path("SomeERC20.json")) - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value) + some_erc20_encoder = ContractEncoder.from_json( + self.web3, contract_path("SomeERC20.json") + ) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ) gas_price = self.web3.zksync.gas_price args = (self.account.address, self.ERC20_Token.to_int(amount)) - call_data = some_erc20_encoder.encode_method(fn_name='mint', args=args) - func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.some_erc20_address, - data=call_data, - gas_limit=0, # UNKNOWN AT THIS STATE, - gas_price=gas_price) + call_data = some_erc20_encoder.encode_method(fn_name="mint", args=args) + func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.some_erc20_address, + data=call_data, + gas_limit=0, # UNKNOWN AT THIS STATE, + gas_price=gas_price, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(func_call.tx) tx_712 = func_call.tx712(estimate_gas) @@ -222,57 +283,79 @@ def mint_some_erc20(self, amount: int): singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) - self.assertEqual(1, tx_receipt['status']) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) + self.assertEqual(1, tx_receipt["status"]) # @skip("Integration test, used for develop purposes only") def test_estimate_gas_deploy_contract(self): directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - counter_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + counter_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) gas_price = self.web3.zksync.gas_price - create2_contract = TxCreate2Contract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, - gas_price=gas_price, - bytecode=counter_contract.bytecode) + create2_contract = TxCreate2Contract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, + gas_price=gas_price, + bytecode=counter_contract.bytecode, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create2_contract.tx) - self.assertGreater(estimate_gas, 0, "test_estimate_gas_deploy_contract, estimate_gas must be greater 0") + self.assertGreater( + estimate_gas, + 0, + "test_estimate_gas_deploy_contract, estimate_gas must be greater 0", + ) # @skip("Integration test, used for develop purposes only") def test_deploy_contract_create(self): random_salt = generate_random_salt() - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) nonce_holder = self.web3.zksync.contract( address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, - abi=nonce_holder_abi_default() - ) - deployment_nonce = nonce_holder.functions.getDeploymentNonce(self.account.address).call( - {"from": self.account.address} + abi=nonce_holder_abi_default(), ) + deployment_nonce = nonce_holder.functions.getDeploymentNonce( + self.account.address + ).call({"from": self.account.address}) deployer = PrecomputeContractDeployer(self.web3) - precomputed_address = deployer.compute_l2_create_address(self.account.address, deployment_nonce) + precomputed_address = deployer.compute_l2_create_address( + self.account.address, deployment_nonce + ) directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - counter_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + counter_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) gas_price = self.web3.zksync.gas_price - create_contract = TxCreateContract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=gas_price, - bytecode=counter_contract.bytecode) + create_contract = TxCreateContract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=gas_price, + bytecode=counter_contract.bytecode, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create_contract.tx) tx_712 = create_contract.tx712(estimate_gas) singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) contract_address = tx_receipt["contractAddress"] self.counter_address = contract_address @@ -280,10 +363,8 @@ def test_deploy_contract_create(self): self.assertEqual(precomputed_address.lower(), contract_address.lower()) value = counter_contract.contract.functions.get().call( - { - "from": self.account.address, - "to": contract_address - }) + {"from": self.account.address, "to": contract_address} + ) self.assertEqual(0, value) @skip("web3py 6.0.0 does not provide protocol version") @@ -294,34 +375,44 @@ def test_protocol_version(self): # @skip("Integration test, used for develop purposes only") def test_deploy_contract_with_constructor_create(self): random_salt = generate_random_salt() - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) gas_price = self.web3.zksync.gas_price nonce_holder = self.web3.zksync.contract( address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, - abi=nonce_holder_abi_default() - ) - deployment_nonce = nonce_holder.functions.getDeploymentNonce(self.account.address).call( - {"from": self.account.address} + abi=nonce_holder_abi_default(), ) + deployment_nonce = nonce_holder.functions.getDeploymentNonce( + self.account.address + ).call({"from": self.account.address}) deployer = PrecomputeContractDeployer(self.web3) - precomputed_address = deployer.compute_l2_create_address(self.account.address, deployment_nonce) + precomputed_address = deployer.compute_l2_create_address( + self.account.address, deployment_nonce + ) directory = Path(__file__).parent path = directory / Path("../contracts/SimpleConstructor.json") - constructor_encoder = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + constructor_encoder = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) a = 2 b = 3 - encoded_ctor = constructor_encoder.encode_constructor(a=a, b=b, shouldRevert=False) + encoded_ctor = constructor_encoder.encode_constructor( + a=a, b=b, shouldRevert=False + ) - create_contract = TxCreateContract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, # UNKNOWN AT THIS STATE, - gas_price=gas_price, - bytecode=constructor_encoder.bytecode, - call_data=encoded_ctor) + create_contract = TxCreateContract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, # UNKNOWN AT THIS STATE, + gas_price=gas_price, + bytecode=constructor_encoder.bytecode, + call_data=encoded_ctor, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create_contract.tx) @@ -330,49 +421,63 @@ def test_deploy_contract_with_constructor_create(self): singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) contract_address = tx_receipt["contractAddress"] # INFO: does not work, contract_address is None self.assertEqual(precomputed_address.lower(), contract_address.lower()) - contract = self.web3.eth.contract(address=Web3.to_checksum_address(contract_address), abi=constructor_encoder.abi) + contract = self.web3.eth.contract( + address=Web3.to_checksum_address(contract_address), + abi=constructor_encoder.abi, + ) - value = contract.functions.get().call({ - "from":self.account.address, - "to":contract_address - }) + value = contract.functions.get().call( + {"from": self.account.address, "to": contract_address} + ) self.assertEqual(a * b, value) # @skip("Integration test, used for develop purposes only") def test_deploy_contract_create2(self): random_salt = generate_random_salt() - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) gas_price = self.web3.zksync.gas_price deployer = PrecomputeContractDeployer(self.web3) directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - counter_contract_encoder = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) - precomputed_address = deployer.compute_l2_create2_address(sender=self.account.address, - bytecode=counter_contract_encoder.bytecode, - constructor=b'', - salt=random_salt) - create2_contract = TxCreate2Contract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, - gas_price=gas_price, - bytecode=counter_contract_encoder.bytecode, - salt=random_salt) + counter_contract_encoder = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) + precomputed_address = deployer.compute_l2_create2_address( + sender=self.account.address, + bytecode=counter_contract_encoder.bytecode, + constructor=b"", + salt=random_salt, + ) + create2_contract = TxCreate2Contract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, + gas_price=gas_price, + bytecode=counter_contract_encoder.bytecode, + salt=random_salt, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create2_contract.tx) tx_712 = create2_contract.tx712(estimate_gas) singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=1.0) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=1.0 + ) self.assertEqual(1, tx_receipt["status"]) @@ -382,10 +487,8 @@ def test_deploy_contract_create2(self): self.assertEqual(precomputed_address.lower(), contract_address.lower()) value = counter_contract_encoder.contract.functions.get().call( - { - "from": self.account.address, - "to": contract_address - }) + {"from": self.account.address, "to": contract_address} + ) self.assertEqual(0, value) # @skip("Integration test, used for develop purposes only") @@ -393,31 +496,40 @@ def test_deploy_contract_with_deps_create(self): random_salt = generate_random_salt() directory = Path(__file__).parent path = directory / Path("../contracts/Import.json") - import_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + import_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) directory = Path(__file__).parent foo_path = directory / Path("../contracts/Foo.json") - import_dependency_contract = ContractEncoder.from_json(self.web3, foo_path.resolve(), JsonConfiguration.STANDARD) - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + import_dependency_contract = ContractEncoder.from_json( + self.web3, foo_path.resolve(), JsonConfiguration.STANDARD + ) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) gas_price = self.web3.zksync.gas_price nonce_holder = self.web3.zksync.contract( address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, - abi=nonce_holder_abi_default() - ) - deployment_nonce = nonce_holder.functions.getDeploymentNonce(self.account.address).call( - {"from": self.account.address} + abi=nonce_holder_abi_default(), ) + deployment_nonce = nonce_holder.functions.getDeploymentNonce( + self.account.address + ).call({"from": self.account.address}) contract_deployer = PrecomputeContractDeployer(self.web3) - precomputed_address = contract_deployer.compute_l2_create_address(self.account.address, - deployment_nonce) - - create_contract = TxCreateContract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, - gas_price=gas_price, - bytecode=import_contract.bytecode, - deps=[import_dependency_contract.bytecode]) + precomputed_address = contract_deployer.compute_l2_create_address( + self.account.address, deployment_nonce + ) + + create_contract = TxCreateContract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, + gas_price=gas_price, + bytecode=import_contract.bytecode, + deps=[import_dependency_contract.bytecode], + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create_contract.tx) @@ -426,7 +538,9 @@ def test_deploy_contract_with_deps_create(self): singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) contract_address = contract_deployer.extract_contract_address(tx_receipt) @@ -437,27 +551,37 @@ def test_deploy_contract_with_deps_create2(self): random_salt = generate_random_salt() directory = Path(__file__).parent path = directory / Path("../contracts/Import.json") - import_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + import_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) directory = Path(__file__).parent foo_path = directory / Path("../contracts/Foo.json") - import_dependency_contract = ContractEncoder.from_json(self.web3, foo_path.resolve(), JsonConfiguration.STANDARD) - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + import_dependency_contract = ContractEncoder.from_json( + self.web3, foo_path.resolve(), JsonConfiguration.STANDARD + ) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) gas_price = self.web3.zksync.gas_price contract_deployer = PrecomputeContractDeployer(self.web3) - precomputed_address = contract_deployer.compute_l2_create2_address(self.account.address, - bytecode=import_contract.bytecode, - constructor=b'', - salt=random_salt) - create2_contract = TxCreate2Contract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, - gas_price=gas_price, - bytecode=import_contract.bytecode, - deps=[import_dependency_contract.bytecode], - salt=random_salt) + precomputed_address = contract_deployer.compute_l2_create2_address( + self.account.address, + bytecode=import_contract.bytecode, + constructor=b"", + salt=random_salt, + ) + create2_contract = TxCreate2Contract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, + gas_price=gas_price, + bytecode=import_contract.bytecode, + deps=[import_dependency_contract.bytecode], + salt=random_salt, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create2_contract.tx) tx_712 = create2_contract.tx712(estimate_gas) @@ -465,7 +589,9 @@ def test_deploy_contract_with_deps_create2(self): singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) contract_address = contract_deployer.extract_contract_address(tx_receipt) self.assertEqual(precomputed_address.lower(), contract_address.lower()) @@ -474,29 +600,39 @@ def test_deploy_contract_with_deps_create2(self): def test_execute_contract(self): directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - counter_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + counter_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) if self.counter_address is None: random_salt = generate_random_salt() - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.PENDING.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.PENDING.value + ) gas_price = self.web3.zksync.gas_price - create_contract = TxCreateContract(web3=self.web3, - chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=gas_price, - bytecode=counter_contract.bytecode) + create_contract = TxCreateContract( + web3=self.web3, + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=gas_price, + bytecode=counter_contract.bytecode, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(create_contract.tx) tx_712 = create_contract.tx712(estimate_gas) singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) contract_address = tx_receipt["contractAddress"] self.counter_address = contract_address - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ) encoded_get = counter_contract.encode_method(fn_name="get", args=[]) eth_tx: TxParams = { "from": self.account.address, @@ -508,13 +644,15 @@ def test_execute_contract(self): gas_price = self.web3.zksync.gas_price call_data = counter_contract.encode_method(fn_name="increment", args=[1]) - func_call = TxFunctionCall(chain_id=self.chain_id, - nonce=nonce, - from_=self.account.address, - to=self.counter_address, - data=call_data, - gas_limit=0, # UNKNOWN AT THIS STATE, - gas_price=gas_price) + func_call = TxFunctionCall( + chain_id=self.chain_id, + nonce=nonce, + from_=self.account.address, + to=self.counter_address, + data=call_data, + gas_limit=0, # UNKNOWN AT THIS STATE, + gas_price=gas_price, + ) estimate_gas = self.web3.zksync.eth_estimate_gas(func_call.tx) tx_712 = func_call.tx712(estimate_gas) @@ -522,47 +660,54 @@ def test_execute_contract(self): singed_message = self.signer.sign_typed_data(tx_712.to_eip712_struct()) msg = tx_712.encode(singed_message) tx_hash = self.web3.zksync.send_raw_transaction(msg) - tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash, timeout=240, poll_latency=0.5) + tx_receipt = self.web3.zksync.wait_for_transaction_receipt( + tx_hash, timeout=240, poll_latency=0.5 + ) self.assertEqual(1, tx_receipt["status"]) eth_ret2 = self.web3.zksync.call(eth_tx, EthBlockParams.LATEST.value) updated_result = int.from_bytes(eth_ret2, "big", signed=True) self.assertEqual(result + 1, updated_result) - #@skip + # @skip def test_contract_factory(self): increment_value = 10 salt = generate_random_salt() directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - deployer = LegacyContractFactory.from_json(zksync=self.web3, - compiled_contract=path.resolve(), - account=self.account, - signer=self.signer) + deployer = LegacyContractFactory.from_json( + zksync=self.web3, + compiled_contract=path.resolve(), + account=self.account, + signer=self.signer, + ) contract = deployer.deploy() - value = contract.functions.get().call({ - "from": self.account.address - }) + value = contract.functions.get().call({"from": self.account.address}) gas_price = self.web3.zksync.gas_price - nonce = self.web3.zksync.get_transaction_count(self.account.address, EthBlockParams.LATEST.value) - tx = contract.functions.increment(increment_value).build_transaction({ - "nonce": nonce, - "from": self.account.address, - # INFO: this fields can't be got automatically because internally - # web3 py uses web3.eth provider with specific lambdas for getting them - "maxPriorityFeePerGas": 1000000, - "maxFeePerGas": gas_price - }) + nonce = self.web3.zksync.get_transaction_count( + self.account.address, EthBlockParams.LATEST.value + ) + tx = contract.functions.increment(increment_value).build_transaction( + { + "nonce": nonce, + "from": self.account.address, + # INFO: this fields can't be got automatically because internally + # web3 py uses web3.eth provider with specific lambdas for getting them + "maxPriorityFeePerGas": 1000000, + "maxFeePerGas": gas_price, + } + ) signed = self.account.sign_transaction(tx) tx_hash = self.web3.zksync.send_raw_transaction(signed.rawTransaction) tx_receipt = self.web3.zksync.wait_for_transaction_receipt(tx_hash) - self.assertEqual(1, tx_receipt['status']) + self.assertEqual(1, tx_receipt["status"]) value = contract.functions.get().call( { "from": self.account.address, - }) + } + ) self.assertEqual(increment_value, value) # @skip("Integration test, used for develop purposes only") @@ -588,9 +733,9 @@ def test_get_account_info(self): self.assertIsNotNone(result) def test_get_l1_token_address(self): - result = self.web3.zksync.l1_token_address(ADDRESS_DEFAULT); + result = self.web3.zksync.l1_token_address(ADDRESS_DEFAULT) self.assertEqual(result, ADDRESS_DEFAULT) def test_get_l2_token_address(self): - result = self.web3.zksync.l2_token_address(ADDRESS_DEFAULT); + result = self.web3.zksync.l2_token_address(ADDRESS_DEFAULT) self.assertEqual(result, ADDRESS_DEFAULT) diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index f70da75..e18ae05 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -30,4 +30,6 @@ class TestEnvironment: eth_server: str -LOCAL_ENV = TestEnvironment(EnvType.LOCAL_HOST, "http://127.0.0.1:3050", "http://127.0.0.1:8545") +LOCAL_ENV = TestEnvironment( + EnvType.LOCAL_HOST, "http://127.0.0.1:3050", "http://127.0.0.1:8545" +) diff --git a/tests/unit/test_contract_deploy.py b/tests/unit/test_contract_deploy.py index c4d50c8..ab4f95d 100644 --- a/tests/unit/test_contract_deploy.py +++ b/tests/unit/test_contract_deploy.py @@ -7,31 +7,43 @@ from .test_config import LOCAL_ENV from zksync2.core.utils import hash_byte_code from tests.contracts.utils import contract_path -from zksync2.manage_contracts.precompute_contract_deployer import PrecomputeContractDeployer -from zksync2.manage_contracts.contract_encoder_base import ContractEncoder, JsonConfiguration +from zksync2.manage_contracts.precompute_contract_deployer import ( + PrecomputeContractDeployer, +) +from zksync2.manage_contracts.contract_encoder_base import ( + ContractEncoder, + JsonConfiguration, +) from zksync2.module.module_builder import ZkSyncBuilder class ContractDeployerTests(TestCase): - def setUp(self) -> None: env = LOCAL_ENV self.web3 = ZkSyncBuilder.build(env.zksync_server) self.contract_deployer = PrecomputeContractDeployer(self.web3) directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - counter_contract = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) + counter_contract = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) self.counter_contract_bin = counter_contract.bytecode def test_compute_l2_create2(self): - expected = Web3.to_checksum_address("0xf7671F9178dF17CF2F94a51d5a97bF54f6dff25a") + expected = Web3.to_checksum_address( + "0xf7671F9178dF17CF2F94a51d5a97bF54f6dff25a" + ) sender = HexStr("0xa909312acfc0ed4370b8bd20dfe41c8ff6595194") - salt = b'\0' * 32 - addr = self.contract_deployer.compute_l2_create2_address(sender, self.counter_contract_bin, b'', salt) + salt = b"\0" * 32 + addr = self.contract_deployer.compute_l2_create2_address( + sender, self.counter_contract_bin, b"", salt + ) self.assertEqual(expected, addr) def test_compute_l2_create(self): - expected = Web3.to_checksum_address("0x5107b7154dfc1d3b7f1c4e19b5087e1d3393bcf4") + expected = Web3.to_checksum_address( + "0x5107b7154dfc1d3b7f1c4e19b5087e1d3393bcf4" + ) sender = HexStr("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf") addr = self.contract_deployer.compute_l2_create_address(sender, Nonce(3)) self.assertEqual(expected, addr) diff --git a/tests/unit/test_eip712.py b/tests/unit/test_eip712.py index 1e29e55..9f6229c 100644 --- a/tests/unit/test_eip712.py +++ b/tests/unit/test_eip712.py @@ -17,87 +17,125 @@ class Mail(EIP712Struct): def make_mail(from_, to, content) -> Mail: - setattr(Mail, 'from', Person) - setattr(Mail, 'to', Person) - setattr(Mail, 'contents', String()) - - kwargs = { - 'to': to, - 'from': from_, - 'contents': content - } + setattr(Mail, "from", Person) + setattr(Mail, "to", Person) + setattr(Mail, "contents", String()) + + kwargs = {"to": to, "from": from_, "contents": content} return Mail(**kwargs) class EIP712Tests(TestCase): - def setUp(self) -> None: - self.person_from = Person(name="Cow", wallet="0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826") - self.person_to = Person(name="Bob", wallet="0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB") - self.mail = make_mail(from_=self.person_from, to=self.person_to, content="Hello, Bob!") - self.domain = make_domain(name="Ether Mail", - version="1", - chainId=1, - verifyingContract="0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC") + self.person_from = Person( + name="Cow", wallet="0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + ) + self.person_to = Person( + name="Bob", wallet="0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + ) + self.mail = make_mail( + from_=self.person_from, to=self.person_to, content="Hello, Bob!" + ) + self.domain = make_domain( + name="Ether Mail", + version="1", + chainId=1, + verifyingContract="0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + ) def test_encode_type(self): result = self.mail.encode_type() - self.assertEqual('Mail(Person from,Person to,string contents)Person(string name,address wallet)', result) + self.assertEqual( + "Mail(Person from,Person to,string contents)Person(string name,address wallet)", + result, + ) def test_hash_encoded_type(self): result = self.mail.type_hash() - self.assertEqual('a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2', result.hex()) + self.assertEqual( + "a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2", + result.hex(), + ) def test_encode_person(self): - from_str = self.mail.get_data_value('from').to_message_json(self.domain) + from_str = self.mail.get_data_value("from").to_message_json(self.domain) value = json.loads(from_str) ret = encode_structured_data(value) - self.assertEqual('fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8', ret.body.hex()) + self.assertEqual( + "fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8", + ret.body.hex(), + ) - to_str = self.mail.get_data_value('to').to_message_json(self.domain) + to_str = self.mail.get_data_value("to").to_message_json(self.domain) value = json.loads(to_str) ret = encode_structured_data(value) - self.assertEqual('cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1', ret.body.hex()) + self.assertEqual( + "cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1", + ret.body.hex(), + ) def test_encode_mail_data(self): struct_message_json = self.mail.to_message_json(self.domain) value = json.loads(struct_message_json) ret = encode_structured_data(value) - self.assertEqual('c52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e', ret.body.hex()) + self.assertEqual( + "c52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e", + ret.body.hex(), + ) def test_singed_bytes(self): result_bytes = self.mail.signable_bytes(self.domain) ret = keccak_256(result_bytes) - self.assertEqual('be609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2', ret.hex()) + self.assertEqual( + "be609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2", + ret.hex(), + ) def test_encode_content(self): - val = self.mail.get_data_value('contents') + val = self.mail.get_data_value("contents") ret = keccak_256(val.encode()) - self.assertEqual('b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8', ret.hex()) + self.assertEqual( + "b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8", + ret.hex(), + ) def test_encode_domain(self): type_hash = self.domain.type_hash() ret = self.domain.encode_value() ret = type_hash + ret ret = keccak_256(ret) - self.assertEqual('f2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f', ret.hex()) + self.assertEqual( + "f2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f", + ret.hex(), + ) def test_encode_domain_members(self): - name = self.domain.get_data_value('name') + name = self.domain.get_data_value("name") name_hash = keccak_256(name.encode()) - self.assertEqual('c70ef06638535b4881fafcac8287e210e3769ff1a8e91f1b95d6246e61e4d3c6', name_hash.hex()) + self.assertEqual( + "c70ef06638535b4881fafcac8287e210e3769ff1a8e91f1b95d6246e61e4d3c6", + name_hash.hex(), + ) - version = self.domain.get_data_value('version') + version = self.domain.get_data_value("version") version_hash = keccak_256(version.encode()) - self.assertEqual('c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6', version_hash.hex()) - - chain_id = self.domain.get_data_value('chainId') - chain_id_padded = pad_front_bytes(chain_id.to_bytes(2, 'big'), 32) - self.assertEqual('0000000000000000000000000000000000000000000000000000000000000001', chain_id_padded.hex()) - - verified_contract = self.domain.get_data_value('verifyingContract') + self.assertEqual( + "c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", + version_hash.hex(), + ) + + chain_id = self.domain.get_data_value("chainId") + chain_id_padded = pad_front_bytes(chain_id.to_bytes(2, "big"), 32) + self.assertEqual( + "0000000000000000000000000000000000000000000000000000000000000001", + chain_id_padded.hex(), + ) + + verified_contract = self.domain.get_data_value("verifyingContract") verified_contract = verified_contract[2:] - verified_contract_hash = b'\0'*12 + bytes.fromhex(verified_contract) + verified_contract_hash = b"\0" * 12 + bytes.fromhex(verified_contract) - self.assertEqual("000000000000000000000000cccccccccccccccccccccccccccccccccccccccc", - verified_contract_hash.hex()) + self.assertEqual( + "000000000000000000000000cccccccccccccccccccccccccccccccccccccccc", + verified_contract_hash.hex(), + ) diff --git a/tests/unit/test_eth_signer.py b/tests/unit/test_eth_signer.py index 22ede7f..2f5ca86 100644 --- a/tests/unit/test_eth_signer.py +++ b/tests/unit/test_eth_signer.py @@ -17,32 +17,38 @@ class Mail(EIP712Struct): def make_mail(from_, to, content) -> Mail: - setattr(Mail, 'from', Person) - setattr(Mail, 'to', Person) - setattr(Mail, 'contents', String()) - - kwargs = { - 'to': to, - 'from': from_, - 'contents': content - } + setattr(Mail, "from", Person) + setattr(Mail, "to", Person) + setattr(Mail, "contents", String()) + + kwargs = {"to": to, "from": from_, "contents": content} return Mail(**kwargs) class EthSignerTests(TestCase): - _TEST_TYPED_EXPECTED_SIGNATURE = HexStr("0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751" - "c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c") + _TEST_TYPED_EXPECTED_SIGNATURE = HexStr( + "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751" + "c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c" + ) def setUp(self) -> None: - self.domain = make_domain(name="Ether Mail", - version="1", - chainId=1, - verifyingContract="0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC") - self.person_from = Person(name="Cow", wallet="0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826") - self.person_to = Person(name="Bob", wallet="0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB") - self.mail = make_mail(from_=self.person_from, to=self.person_to, content="Hello, Bob!") - - private_key = keccak_256("cow".encode('utf-8')) + self.domain = make_domain( + name="Ether Mail", + version="1", + chainId=1, + verifyingContract="0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + ) + self.person_from = Person( + name="Cow", wallet="0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + ) + self.person_to = Person( + name="Bob", wallet="0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + ) + self.mail = make_mail( + from_=self.person_from, to=self.person_to, content="Hello, Bob!" + ) + + private_key = keccak_256("cow".encode("utf-8")) self.account: LocalAccount = Account.from_key(private_key) self.signer = PrivateKeyEthSigner(self.account, 1) @@ -51,5 +57,7 @@ def test_sign_typed_data(self): self.assertEqual(self._TEST_TYPED_EXPECTED_SIGNATURE, sm.signature.hex()) def test_verify_signed_typed_data(self): - ret = self.signer.verify_typed_data(self._TEST_TYPED_EXPECTED_SIGNATURE, self.mail, self.domain) + ret = self.signer.verify_typed_data( + self._TEST_TYPED_EXPECTED_SIGNATURE, self.mail, self.domain + ) self.assertTrue(ret) diff --git a/tests/unit/test_transaction712.py b/tests/unit/test_transaction712.py index f9466c0..0e431f6 100644 --- a/tests/unit/test_transaction712.py +++ b/tests/unit/test_transaction712.py @@ -11,12 +11,17 @@ from tests.contracts.utils import contract_path from .test_config import LOCAL_ENV -from zksync2.manage_contracts.contract_encoder_base import ContractEncoder, JsonConfiguration +from zksync2.manage_contracts.contract_encoder_base import ( + ContractEncoder, + JsonConfiguration, +) from zksync2.module.request_types import EIP712Meta from zksync2.transaction.transaction712 import Transaction712 from zksync2.transaction.transaction_builders import TxCreateContract -PRIVATE_KEY2 = bytes.fromhex("fd1f96220fa3a40c46d65f81d61dd90af600746fd47e5c82673da937a48b38ef") +PRIVATE_KEY2 = bytes.fromhex( + "fd1f96220fa3a40c46d65f81d61dd90af600746fd47e5c82673da937a48b38ef" +) class Transaction712Tests(TestCase): @@ -26,13 +31,19 @@ class Transaction712Tests(TestCase): SENDER = HexStr("0x1234512345123451234512345123451234512345") RECEIVER = HexStr("0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC") - TRANSACTION_SIGNATURE = "Transaction(uint256 txType,uint256 from,uint256 to,uint256 gasLimit,uint256 " \ - "gasPerPubdataByteLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas," \ - "uint256 paymaster,uint256 nonce,uint256 value,bytes data,bytes32[] factoryDeps," \ - "bytes paymasterInput)" + TRANSACTION_SIGNATURE = ( + "Transaction(uint256 txType,uint256 from,uint256 to,uint256 gasLimit,uint256 " + "gasPerPubdataByteLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas," + "uint256 paymaster,uint256 nonce,uint256 value,bytes data,bytes32[] factoryDeps," + "bytes paymasterInput)" + ) - EXPECTED_ENCODED_VALUE = '0x1e40bcee418db11047ffefb27b304f8ec1b5d644c35c56878f5cc12988b3162d' - EXPECTED_ENCODED_BYTES = "0x7519adb6e67031ee048d921120687e4fbdf83961bcf43756f349d689eed2b80c" + EXPECTED_ENCODED_VALUE = ( + "0x1e40bcee418db11047ffefb27b304f8ec1b5d644c35c56878f5cc12988b3162d" + ) + EXPECTED_ENCODED_BYTES = ( + "0x7519adb6e67031ee048d921120687e4fbdf83961bcf43756f349d689eed2b80c" + ) def setUp(self) -> None: # self.web3 = Web3(EthereumTesterProvider(PyEVMBackend())) @@ -41,30 +52,40 @@ def setUp(self) -> None: self.account: LocalAccount = Account.from_key(PRIVATE_KEY2) directory = Path(__file__).parent path = directory / Path("../contracts/Counter.json") - self.counter_contract_encoder = ContractEncoder.from_json(self.web3, path.resolve(), JsonConfiguration.STANDARD) - self.tx712 = Transaction712(chain_id=self.CHAIN_ID, - nonce=self.NONCE, - gas_limit=self.GAS_LIMIT, - to=self.RECEIVER, - value=0, - data=self.counter_contract_encoder.encode_method(fn_name="increment", args=[42]), - maxPriorityFeePerGas=0, - maxFeePerGas=0, - from_=self.SENDER, - meta=EIP712Meta(0)) + self.counter_contract_encoder = ContractEncoder.from_json( + self.web3, path.resolve(), JsonConfiguration.STANDARD + ) + self.tx712 = Transaction712( + chain_id=self.CHAIN_ID, + nonce=self.NONCE, + gas_limit=self.GAS_LIMIT, + to=self.RECEIVER, + value=0, + data=self.counter_contract_encoder.encode_method( + fn_name="increment", args=[42] + ), + maxPriorityFeePerGas=0, + maxFeePerGas=0, + from_=self.SENDER, + meta=EIP712Meta(0), + ) def test_deploy_contract_tx712(self): - tx = TxCreateContract(web3=self.web3, - chain_id=280, - nonce=0, - from_=self.account.address.lower(), - gas_limit=0, # UNKNOWN AT THIS STATE - gas_price=250000000, - bytecode=self.counter_contract_encoder.bytecode) + tx = TxCreateContract( + web3=self.web3, + chain_id=280, + nonce=0, + from_=self.account.address.lower(), + gas_limit=0, # UNKNOWN AT THIS STATE + gas_price=250000000, + bytecode=self.counter_contract_encoder.bytecode, + ) tx_712 = tx.tx712(9910372) msg = tx_712.to_eip712_struct().hash_struct() - self.assertEqual("b65d7e33b4d31aa931d044aff74ad6780374acd5bcbd192b1b0210c40664ccb2", - msg.hex()) + self.assertEqual( + "b65d7e33b4d31aa931d044aff74ad6780374acd5bcbd192b1b0210c40664ccb2", + msg.hex(), + ) def test_encode_to_eip712_type_string(self): eip712_struct = self.tx712.to_eip712_struct() diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 5c6022c..b06191b 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -10,17 +10,23 @@ class UtilsTest(TestCase): - def setUp(self) -> None: self.env = LOCAL_ENV env_key = EnvPrivateKey("ZKSYNC_KEY1") self.zksync = ZkSyncBuilder.build(self.env.zksync_server) + def test_apply_l1_to_l2_alias(self): l1_contract_address = HexStr("0x702942B8205E5dEdCD3374E5f4419843adA76Eeb") l2_contract_address = apply_l1_to_l2_alias(l1_contract_address) - self.assertEqual(l2_contract_address.lower(), "0x813A42B8205E5DedCd3374e5f4419843ADa77FFC".lower()) + self.assertEqual( + l2_contract_address.lower(), + "0x813A42B8205E5DedCd3374e5f4419843ADa77FFC".lower(), + ) def test_undo_l1_to_l2_alias(self): l2_contract_address = HexStr("0x813A42B8205E5DedCd3374e5f4419843ADa77FFC") l1_contract_address = undo_l1_to_l2_alias(l2_contract_address) - self.assertEqual(l1_contract_address.lower(), "0x702942B8205E5dEdCD3374E5f4419843adA76Eeb".lower()) + self.assertEqual( + l1_contract_address.lower(), + "0x702942B8205E5dEdCD3374E5f4419843adA76Eeb".lower(), + ) diff --git a/zksync2/account/utils.py b/zksync2/account/utils.py index ea6cc45..7994ec4 100644 --- a/zksync2/account/utils.py +++ b/zksync2/account/utils.py @@ -1,29 +1,38 @@ from eth_typing import HexStr from web3.types import Nonce -from zksync2.core.types import DepositTransaction, RequestExecuteCallMsg, TransactionOptions +from zksync2.core.types import ( + DepositTransaction, + RequestExecuteCallMsg, + TransactionOptions, +) from zksync2.transaction.transaction712 import Transaction712 -def deposit_to_request_execute(transaction: DepositTransaction) -> RequestExecuteCallMsg: +def deposit_to_request_execute( + transaction: DepositTransaction, +) -> RequestExecuteCallMsg: return RequestExecuteCallMsg( - contract_address=transaction.to, - call_data=HexStr("0x"), - l2_gas_limit=transaction.l2_gas_limit, - l2_value=transaction.amount, - operator_tip=transaction.operator_tip, - gas_per_pubdata_byte=transaction.gas_per_pubdata_byte, - refund_recipient=transaction.refund_recipient, - options=transaction.options) + contract_address=transaction.to, + call_data=HexStr("0x"), + l2_gas_limit=transaction.l2_gas_limit, + l2_value=transaction.amount, + operator_tip=transaction.operator_tip, + gas_per_pubdata_byte=transaction.gas_per_pubdata_byte, + refund_recipient=transaction.refund_recipient, + options=transaction.options, + ) def options_from_712(tx: Transaction712) -> TransactionOptions: - return TransactionOptions(chain_id=tx.chain_id, - nonce=Nonce(tx.nonce), - gas_limit=tx.gas_limit, - max_fee_per_gas=tx.maxFeePerGas, - max_priority_fee_per_gas=tx.maxPriorityFeePerGas, - gas_price=tx.maxFeePerGas) + return TransactionOptions( + chain_id=tx.chain_id, + nonce=Nonce(tx.nonce), + gas_limit=tx.gas_limit, + max_fee_per_gas=tx.maxFeePerGas, + max_priority_fee_per_gas=tx.maxPriorityFeePerGas, + gas_price=tx.maxFeePerGas, + ) def prepare_transaction_options(options: TransactionOptions, from_: HexStr = None): @@ -31,7 +40,10 @@ def prepare_transaction_options(options: TransactionOptions, from_: HexStr = Non if options.value is not None: opt["value"] = options.value - if options.max_fee_per_gas is not None or options.max_priority_fee_per_gas is not None: + if ( + options.max_fee_per_gas is not None + or options.max_priority_fee_per_gas is not None + ): if options.max_priority_fee_per_gas is not None: opt["maxPriorityFeePerGas"] = options.max_priority_fee_per_gas if options.max_fee_per_gas is not None: @@ -49,4 +61,3 @@ def prepare_transaction_options(options: TransactionOptions, from_: HexStr = Non opt["from"] = from_ return opt - diff --git a/zksync2/account/wallet.py b/zksync2/account/wallet.py index 80342c4..8262b86 100644 --- a/zksync2/account/wallet.py +++ b/zksync2/account/wallet.py @@ -6,12 +6,8 @@ from eth_account.signers.base import BaseAccount - class Wallet(WalletL1, WalletL2): - def __init__(self, - zksync_web3: Web3, - eth_web3: Web3, - l1_account: BaseAccount): + def __init__(self, zksync_web3: Web3, eth_web3: Web3, l1_account: BaseAccount): self._eth_web3 = eth_web3 self._zksync_web3 = zksync_web3 self._l1_account = l1_account diff --git a/zksync2/account/wallet_l1.py b/zksync2/account/wallet_l1.py index 752ca41..e3e681a 100644 --- a/zksync2/account/wallet_l1.py +++ b/zksync2/account/wallet_l1.py @@ -13,16 +13,44 @@ from eth_account.signers.base import BaseAccount from eth_abi import abi -from zksync2.account.utils import deposit_to_request_execute, prepare_transaction_options -from zksync2.core.types import BridgeAddresses, Token, ZksMessageProof, EthBlockParams, \ - DepositTransaction, ADDRESS_DEFAULT, L1ToL2Log, RequestExecuteCallMsg, FullDepositFee, L1BridgeContracts, \ - TransactionOptions -from zksync2.core.utils import RecommendedGasLimit, to_bytes, is_eth, apply_l1_to_l2_alias, \ - get_custom_bridge_data, BOOTLOADER_FORMAL_ADDRESS, undo_l1_to_l2_alias, DEPOSIT_GAS_PER_PUBDATA_LIMIT -from zksync2.manage_contracts.contract_encoder_base import ContractEncoder, JsonConfiguration +from zksync2.account.utils import ( + deposit_to_request_execute, + prepare_transaction_options, +) +from zksync2.core.types import ( + BridgeAddresses, + Token, + ZksMessageProof, + EthBlockParams, + DepositTransaction, + ADDRESS_DEFAULT, + L1ToL2Log, + RequestExecuteCallMsg, + FullDepositFee, + L1BridgeContracts, + TransactionOptions, +) +from zksync2.core.utils import ( + RecommendedGasLimit, + to_bytes, + is_eth, + apply_l1_to_l2_alias, + get_custom_bridge_data, + BOOTLOADER_FORMAL_ADDRESS, + undo_l1_to_l2_alias, + DEPOSIT_GAS_PER_PUBDATA_LIMIT, +) +from zksync2.manage_contracts.contract_encoder_base import ( + ContractEncoder, + JsonConfiguration, +) from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses -from zksync2.manage_contracts.utils import zksync_abi_default, l1_bridge_abi_default, get_erc20_abi, \ - l2_bridge_abi_default +from zksync2.manage_contracts.utils import ( + zksync_abi_default, + l1_bridge_abi_default, + get_erc20_abi, + l2_bridge_abi_default, +) from zksync2.module.request_types import EIP712Meta from zksync2.transaction.transaction712 import Transaction712 from zksync2.transaction.transaction_builders import TxFunctionCall @@ -30,27 +58,33 @@ def check_base_cost(base_cost: int, value: int): if base_cost > value: - raise RuntimeError(f"The base cost of performing the priority operation is higher than" - f" the provided value parameter" - f" for the transaction: base_cost: ${base_cost}," - f" provided value: ${value}`") + raise RuntimeError( + f"The base cost of performing the priority operation is higher than" + f" the provided value parameter" + f" for the transaction: base_cost: ${base_cost}," + f" provided value: ${value}`" + ) + class WalletL1: DEPOSIT_GAS_PER_PUBDATA_LIMIT = 800 RECOMMENDED_DEPOSIT_L2_GAS_LIMIT = 10000000 - L1_MESSENGER_ADDRESS = '0x0000000000000000000000000000000000008008' + L1_MESSENGER_ADDRESS = "0x0000000000000000000000000000000000008008" - def __init__(self, - zksync_web3: Web3, - eth_web3: Web3, - l1_account: BaseAccount): + def __init__(self, zksync_web3: Web3, eth_web3: Web3, l1_account: BaseAccount): self._eth_web3 = eth_web3 self._eth_web3.middleware_onion.inject(geth_poa_middleware, layer=0) self._zksync_web3 = zksync_web3 - self._main_contract_address = Web3.to_checksum_address(self._zksync_web3.zksync.zks_main_contract()) - self.contract = self._eth_web3.eth.contract(self._main_contract_address, abi=zksync_abi_default()) + self._main_contract_address = Web3.to_checksum_address( + self._zksync_web3.zksync.zks_main_contract() + ) + self.contract = self._eth_web3.eth.contract( + self._main_contract_address, abi=zksync_abi_default() + ) self._l1_account = l1_account - self.bridge_addresses: BridgeAddresses = self._zksync_web3.zksync.zks_get_bridge_contracts() + self.bridge_addresses: BridgeAddresses = ( + self._zksync_web3.zksync.zks_get_bridge_contracts() + ) @property def main_contract(self) -> Union[Type[Contract], Contract]: @@ -64,15 +98,17 @@ def _get_withdraw_log(self, tx_receipt: TxReceipt, index: int = 0): topic = event_signature_to_log_topic("L1MessageSent(address,bytes32,bytes)") def impl_filter(log): - return log['address'] == self.L1_MESSENGER_ADDRESS and \ - log['topics'][0] == topic + return ( + log["address"] == self.L1_MESSENGER_ADDRESS + and log["topics"][0] == topic + ) - filtered_logs = list(filter(impl_filter, tx_receipt['logs'])) - return filtered_logs[index], int(tx_receipt['l1BatchTxIndex'], 16) + filtered_logs = list(filter(impl_filter, tx_receipt["logs"])) + return filtered_logs[index], int(tx_receipt["l1BatchTxIndex"], 16) def _get_withdraw_l2_to_l1_log(self, tx_receipt: TxReceipt, index: int = 0): msgs = [] - for i, e in enumerate(tx_receipt['l2ToL1Logs']): + for i, e in enumerate(tx_receipt["l2ToL1Logs"]): if e["sender"].lower() == self.L1_MESSENGER_ADDRESS.lower(): msgs.append((i, e)) l2_to_l1_log_index, log = msgs[index] @@ -82,11 +118,13 @@ def _finalize_withdrawal_params(self, withdraw_hash, index: int) -> dict: tx_receipt = self._zksync_web3.zksync.get_transaction_receipt(withdraw_hash) log, l1_batch_tx_id = self._get_withdraw_log(tx_receipt, index) l2_to_l1_log_index, _ = self._get_withdraw_l2_to_l1_log(tx_receipt, index) - sender = add_0x_prefix(HexStr(log['topics'][1][12:].hex())) - proof: ZksMessageProof = self._zksync_web3.zksync.zks_get_log_proof(withdraw_hash, l2_to_l1_log_index) - bytes_data = to_bytes(log['data']) + sender = add_0x_prefix(HexStr(log["topics"][1][12:].hex())) + proof: ZksMessageProof = self._zksync_web3.zksync.zks_get_log_proof( + withdraw_hash, l2_to_l1_log_index + ) + bytes_data = to_bytes(log["data"]) msg = self._zksync_web3.codec.decode(["bytes"], bytes_data)[0] - l1_batch_number = int(log['l1BatchNumber'], 16) + l1_batch_number = int(log["l1BatchNumber"], 16) return { "l1_batch_number": l1_batch_number, @@ -94,32 +132,50 @@ def _finalize_withdrawal_params(self, withdraw_hash, index: int) -> dict: "l2_tx_number_in_block": l1_batch_tx_id, "message": msg, "sender": sender, - "proof": proof.proof + "proof": proof.proof, } def get_l1_bridge_contracts(self) -> L1BridgeContracts: - return L1BridgeContracts(erc20=self._eth_web3.eth.contract(address=Web3.to_checksum_address(self.bridge_addresses.erc20_l1_default_bridge), - abi=l1_bridge_abi_default()), - weth=self._eth_web3.eth.contract(address=Web3.to_checksum_address(self.bridge_addresses.weth_bridge_l1), - abi=l1_bridge_abi_default())) - - def get_l1_balance(self, token: HexStr = ADDRESS_DEFAULT, block: EthBlockParams = EthBlockParams.LATEST) -> int: + return L1BridgeContracts( + erc20=self._eth_web3.eth.contract( + address=Web3.to_checksum_address( + self.bridge_addresses.erc20_l1_default_bridge + ), + abi=l1_bridge_abi_default(), + ), + weth=self._eth_web3.eth.contract( + address=Web3.to_checksum_address(self.bridge_addresses.weth_bridge_l1), + abi=l1_bridge_abi_default(), + ), + ) + + def get_l1_balance( + self, + token: HexStr = ADDRESS_DEFAULT, + block: EthBlockParams = EthBlockParams.LATEST, + ) -> int: if is_eth(token): return self._eth_web3.eth.get_balance(self.address, block.value) else: - token_contract = self._eth_web3.eth.contract(address=Web3.to_checksum_address(token), abi=get_erc20_abi()) + token_contract = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(token), abi=get_erc20_abi() + ) return token_contract.functions.balanceOf(self.address).call( - { - "chainId": self._eth_web3.eth.chain_id, - "from": self.address - }) + {"chainId": self._eth_web3.eth.chain_id, "from": self.address} + ) def get_allowance_l1(self, token: HexStr, bridge_address: Address = None): - token_contract = self._eth_web3.eth.contract(address=Web3.to_checksum_address(token), abi=get_erc20_abi()) + token_contract = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(token), abi=get_erc20_abi() + ) if bridge_address is None: l2_weth_token = ADDRESS_DEFAULT try: - l2_weth_token = self.get_l1_bridge_contracts().weth.functions.l2TokenAddress(token).call() + l2_weth_token = ( + self.get_l1_bridge_contracts() + .weth.functions.l2TokenAddress(token) + .call() + ) except: pass if l2_weth_token == ADDRESS_DEFAULT: @@ -130,7 +186,8 @@ def get_allowance_l1(self, token: HexStr, bridge_address: Address = None): { "chainId": self._eth_web3.eth.chain_id, "from": self.address, - }) + } + ) def l2_token_address(self, address: HexStr) -> HexStr: if is_eth(address): @@ -145,20 +202,30 @@ def l2_token_address(self, address: HexStr) -> HexStr: pass return contracts.erc20.functions.l2TokenAddress(address).call() - def approve_erc20(self, - token: HexStr, - amount: int, - bridge_address: HexStr = None, - gas_limit: int = None) -> TxReceipt: + def approve_erc20( + self, + token: HexStr, + amount: int, + bridge_address: HexStr = None, + gas_limit: int = None, + ) -> TxReceipt: if is_eth(token): - raise RuntimeError("ETH token can't be approved. The address of the token does not exist on L1") + raise RuntimeError( + "ETH token can't be approved. The address of the token does not exist on L1" + ) - erc20 = self._eth_web3.eth.contract(address=Web3.to_checksum_address(token), abi=get_erc20_abi()) + erc20 = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(token), abi=get_erc20_abi() + ) if bridge_address is None: l2_weth_token = ADDRESS_DEFAULT try: - l2_weth_token = self.get_l1_bridge_contracts().weth.functions.l2TokenAddress(token).call() + l2_weth_token = ( + self.get_l1_bridge_contracts() + .weth.functions.l2TokenAddress(token) + .call() + ) except: pass if l2_weth_token == ADDRESS_DEFAULT: @@ -168,29 +235,36 @@ def approve_erc20(self, if gas_limit is None: # TODO: get the approve(bridgeAddress, amount) estimateGas transaction to put correct gas_limit gas_limit = RecommendedGasLimit.ERC20_APPROVE - options = TransactionOptions(chain_id=self._eth_web3.eth.chain_id, - gas_price=self._eth_web3.eth.gas_price, - gas_limit=gas_limit, - nonce=self._eth_web3.eth.get_transaction_count(self.address)) - tx = erc20.functions.approve(bridge_address, - amount).build_transaction(prepare_transaction_options(options, self.address)) + options = TransactionOptions( + chain_id=self._eth_web3.eth.chain_id, + gas_price=self._eth_web3.eth.gas_price, + gas_limit=gas_limit, + nonce=self._eth_web3.eth.get_transaction_count(self.address), + ) + tx = erc20.functions.approve(bridge_address, amount).build_transaction( + prepare_transaction_options(options, self.address) + ) signed_tx = self._l1_account.sign_transaction(tx) tx_hash = self._eth_web3.eth.send_raw_transaction(signed_tx.rawTransaction) tx_receipt = self._eth_web3.eth.wait_for_transaction_receipt(tx_hash) return tx_receipt - def get_base_cost(self, - l2_gas_limit: int, - gas_per_pubdata_byte: int = DEPOSIT_GAS_PER_PUBDATA_LIMIT, - gas_price: int = None): + def get_base_cost( + self, + l2_gas_limit: int, + gas_per_pubdata_byte: int = DEPOSIT_GAS_PER_PUBDATA_LIMIT, + gas_price: int = None, + ): if gas_price is None: gas_price = self._eth_web3.eth.gas_price - options = TransactionOptions(chain_id=self._eth_web3.eth.chain_id, - nonce=self._eth_web3.eth.get_transaction_count(self.address)) - return self.contract.functions.l2TransactionBaseCost(gas_price, - l2_gas_limit, - gas_per_pubdata_byte).call(prepare_transaction_options(options, self.address)) + options = TransactionOptions( + chain_id=self._eth_web3.eth.chain_id, + nonce=self._eth_web3.eth.get_transaction_count(self.address), + ) + return self.contract.functions.l2TransactionBaseCost( + gas_price, l2_gas_limit, gas_per_pubdata_byte + ).call(prepare_transaction_options(options, self.address)) def prepare_deposit_tx(self, transaction: DepositTransaction) -> DepositTransaction: if transaction.options is None: @@ -200,39 +274,58 @@ def prepare_deposit_tx(self, transaction: DepositTransaction) -> DepositTransact if transaction.options.chain_id is None: transaction.options.chain_id = self._eth_web3.eth.chain_id if transaction.bridge_address is not None: - bridge_contract = self._eth_web3.eth.contract(address=Web3.to_checksum_address(transaction.bridge_address), - abi=l1_bridge_abi_default()) + bridge_contract = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(transaction.bridge_address), + abi=l1_bridge_abi_default(), + ) if transaction.custom_bridge_data is None: if transaction.bridge_address == self.bridge_addresses.weth_bridge_l1: transaction.custom_bridge_data = "0x" else: - token_contract = self._zksync_web3.zksync.contract(transaction.token, abi=get_erc20_abi()) - transaction.custom_bridge_data = get_custom_bridge_data(token_contract) + token_contract = self._zksync_web3.zksync.contract( + transaction.token, abi=get_erc20_abi() + ) + transaction.custom_bridge_data = get_custom_bridge_data( + token_contract + ) if transaction.l2_gas_limit is None: - l2_address = bridge_contract.functions.l2TokenAddress(transaction.token).call() - transaction.l2_gas_limit = self.estimate_custom_bridge_deposit_l2_gas(transaction.bridge_address, - l2_address, - transaction.token, - transaction.amount, - transaction.to, - transaction.custom_bridge_data, - self.address, - transaction.gas_per_pubdata_byte) + l2_address = bridge_contract.functions.l2TokenAddress( + transaction.token + ).call() + transaction.l2_gas_limit = self.estimate_custom_bridge_deposit_l2_gas( + transaction.bridge_address, + l2_address, + transaction.token, + transaction.amount, + transaction.to, + transaction.custom_bridge_data, + self.address, + transaction.gas_per_pubdata_byte, + ) elif transaction.l2_gas_limit is None: - transaction.l2_gas_limit = self.estimate_default_bridge_deposit_l2_gas(transaction.token, - transaction.amount, - transaction.to, - transaction.gas_per_pubdata_byte, - self.address) - if transaction.options.gas_price is None and transaction.options.max_fee_per_gas is None: + transaction.l2_gas_limit = self.estimate_default_bridge_deposit_l2_gas( + transaction.token, + transaction.amount, + transaction.to, + transaction.gas_per_pubdata_byte, + self.address, + ) + if ( + transaction.options.gas_price is None + and transaction.options.max_fee_per_gas is None + ): isReady, head = self.check_if_l1_chain_is_london_ready() if isReady: if transaction.options.max_priority_fee_per_gas is None: - transaction.options.max_priority_fee_per_gas = self._eth_web3.eth.max_priority_fee - transaction.options.max_fee_per_gas = int(((head["baseFeePerGas"] * 3)/2) - + transaction.options.max_priority_fee_per_gas) + transaction.options.max_priority_fee_per_gas = ( + self._eth_web3.eth.max_priority_fee + ) + transaction.options.max_fee_per_gas = int( + ((head["baseFeePerGas"] * 3) / 2) + + transaction.options.max_priority_fee_per_gas + ) else: transaction.options.gas_price = self._eth_web3.eth.gas_price @@ -242,12 +335,16 @@ def prepare_deposit_tx(self, transaction: DepositTransaction) -> DepositTransact else: gas_price_for_estimation = transaction.options.gas_price - base_cost = self.get_base_cost(transaction.l2_gas_limit, - transaction.gas_per_pubdata_byte, - gas_price_for_estimation) + base_cost = self.get_base_cost( + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + gas_price_for_estimation, + ) if is_eth(transaction.token): - transaction.options.value = base_cost + transaction.operator_tip + transaction.amount + transaction.options.value = ( + base_cost + transaction.operator_tip + transaction.amount + ) else: if transaction.refund_recipient is None: transaction.refund_recipient = ADDRESS_DEFAULT @@ -257,8 +354,10 @@ def prepare_deposit_tx(self, transaction: DepositTransaction) -> DepositTransact return transaction - def get_full_required_deposit_fee(self, transaction: DepositTransaction) -> FullDepositFee: - #It is assumed that the L2 fee for the transaction does not depend on its value. + def get_full_required_deposit_fee( + self, transaction: DepositTransaction + ) -> FullDepositFee: + # It is assumed that the L2 fee for the transaction does not depend on its value. dummy_amount = 1 if transaction.options is None: @@ -268,39 +367,58 @@ def get_full_required_deposit_fee(self, transaction: DepositTransaction) -> Full transaction.to = self.address if transaction.bridge_address is not None: - bridge_contract = self._eth_web3.eth.contract(address=Web3.to_checksum_address(transaction.bridge_address), - abi=l1_bridge_abi_default()) + bridge_contract = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(transaction.bridge_address), + abi=l1_bridge_abi_default(), + ) if transaction.custom_bridge_data is None: if transaction.bridge_address == self.bridge_addresses.weth_bridge_l1: transaction.custom_bridge_data = "0x" else: - token_contract = self._zksync_web3.zksync.contract(transaction.token, abi=get_erc20_abi()) - transaction.custom_bridge_data = get_custom_bridge_data(token_contract) + token_contract = self._zksync_web3.zksync.contract( + transaction.token, abi=get_erc20_abi() + ) + transaction.custom_bridge_data = get_custom_bridge_data( + token_contract + ) if transaction.l2_gas_limit is None: - l2_address = bridge_contract.functions.l2TokenAddress(transaction.token).call() - transaction.l2_gas_limit = self.estimate_custom_bridge_deposit_l2_gas(transaction.bridge_address, - l2_address, - transaction.token, - dummy_amount, - transaction.to, - transaction.custom_bridge_data, - self.address, - transaction.gas_per_pubdata_byte) + l2_address = bridge_contract.functions.l2TokenAddress( + transaction.token + ).call() + transaction.l2_gas_limit = self.estimate_custom_bridge_deposit_l2_gas( + transaction.bridge_address, + l2_address, + transaction.token, + dummy_amount, + transaction.to, + transaction.custom_bridge_data, + self.address, + transaction.gas_per_pubdata_byte, + ) elif transaction.l2_gas_limit is None: - transaction.l2_gas_limit = self.estimate_default_bridge_deposit_l2_gas(transaction.token, - dummy_amount, - transaction.to, - transaction.gas_per_pubdata_byte, - self.address) - if transaction.options.gas_price is None and transaction.options.max_fee_per_gas is None: + transaction.l2_gas_limit = self.estimate_default_bridge_deposit_l2_gas( + transaction.token, + dummy_amount, + transaction.to, + transaction.gas_per_pubdata_byte, + self.address, + ) + if ( + transaction.options.gas_price is None + and transaction.options.max_fee_per_gas is None + ): isReady, head = self.check_if_l1_chain_is_london_ready() if isReady: if transaction.options.max_priority_fee_per_gas is None: - transaction.options.max_priority_fee_per_gas = self._eth_web3.eth.max_priority_fee - transaction.options.max_fee_per_gas = int(((head["baseFeePerGas"] * 3)/2) - + transaction.options.max_priority_fee_per_gas) + transaction.options.max_priority_fee_per_gas = ( + self._eth_web3.eth.max_priority_fee + ) + transaction.options.max_fee_per_gas = int( + ((head["baseFeePerGas"] * 3) / 2) + + transaction.options.max_priority_fee_per_gas + ) else: transaction.options.gas_price = self._eth_web3.eth.gas_price @@ -310,22 +428,35 @@ def get_full_required_deposit_fee(self, transaction: DepositTransaction) -> Full else: gas_price_for_estimation = transaction.options.gas_price - base_cost = self.get_base_cost(transaction.l2_gas_limit, transaction.gas_per_pubdata_byte, - gas_price_for_estimation) + base_cost = self.get_base_cost( + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + gas_price_for_estimation, + ) self_balance_eth = self.get_l1_balance() # We could use 0, because the final fee will anyway be bigger than if base_cost >= (self_balance_eth + dummy_amount): - recommended_eth_balance = RecommendedGasLimit.L1_RECOMMENDED_ETH_DEPOSIT_GAS_LIMIT + recommended_eth_balance = ( + RecommendedGasLimit.L1_RECOMMENDED_ETH_DEPOSIT_GAS_LIMIT + ) if not is_eth(transaction.token): - recommended_eth_balance = RecommendedGasLimit.L1_RECOMMENDED_MIN_ERC_20_DEPOSIT_GAS_LIMIT - recommended_eth_balance = recommended_eth_balance * gas_price_for_estimation + base_cost + recommended_eth_balance = ( + RecommendedGasLimit.L1_RECOMMENDED_MIN_ERC_20_DEPOSIT_GAS_LIMIT + ) + recommended_eth_balance = ( + recommended_eth_balance * gas_price_for_estimation + base_cost + ) - RuntimeError("Not enough balance for deposit. Under the provided gas price, " + - f"the recommended balance to perform a deposit is ${recommended_eth_balance} ETH") + RuntimeError( + "Not enough balance for deposit. Under the provided gas price, " + + f"the recommended balance to perform a deposit is ${recommended_eth_balance} ETH" + ) if not is_eth(transaction.token): - allowance = self.get_allowance_l1(transaction.token, transaction.bridge_address) + allowance = self.get_allowance_l1( + transaction.token, transaction.bridge_address + ) if allowance < dummy_amount: RuntimeError("Not enough allowance to cover the deposit") @@ -339,13 +470,17 @@ def get_full_required_deposit_fee(self, transaction: DepositTransaction) -> Full transaction.amount = dummy_amount l1_gas_limit = self.estimate_gas_deposit(transaction) - full_cost: FullDepositFee = FullDepositFee(base_cost=base_cost, - l1_gas_limit=l1_gas_limit, - l2_gas_limit=transaction.l2_gas_limit) + full_cost: FullDepositFee = FullDepositFee( + base_cost=base_cost, + l1_gas_limit=l1_gas_limit, + l2_gas_limit=transaction.l2_gas_limit, + ) if transaction.options.gas_price is not None: full_cost.gas_price = transaction.options.gas_price else: - full_cost.max_priority_fee_per_gas = transaction.options.max_priority_fee_per_gas + full_cost.max_priority_fee_per_gas = ( + transaction.options.max_priority_fee_per_gas + ) full_cost.max_fee_per_gas = transaction.options.max_fee_per_gas return full_cost @@ -358,18 +493,26 @@ def deposit(self, transaction: DepositTransaction): return self.request_execute(tx) else: if transaction.approve_erc20: - self.approve_erc20(transaction.token, - transaction.amount, - transaction.bridge_address, - transaction.options.gas_limit) + self.approve_erc20( + transaction.token, + transaction.amount, + transaction.bridge_address, + transaction.options.gas_limit, + ) if transaction.bridge_address is not None: - l1_bridge = self._eth_web3.eth.contract(address=Web3.to_checksum_address(transaction.bridge_address), - abi=l1_bridge_abi_default()) + l1_bridge = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(transaction.bridge_address), + abi=l1_bridge_abi_default(), + ) else: l2_weth_token = ADDRESS_DEFAULT try: - l2_weth_token = self.get_l1_bridge_contracts().weth.functions.l2TokenAddress(transaction.token).call() + l2_weth_token = ( + self.get_l1_bridge_contracts() + .weth.functions.l2TokenAddress(transaction.token) + .call() + ) except: pass if l2_weth_token == ADDRESS_DEFAULT: @@ -378,23 +521,28 @@ def deposit(self, transaction: DepositTransaction): bridge_address = self.bridge_addresses.weth_bridge_l1 l1_bridge = self._eth_web3.eth.contract( address=Web3.to_checksum_address(bridge_address), - abi=l1_bridge_abi_default()) + abi=l1_bridge_abi_default(), + ) if transaction.options.nonce is None: - transaction.options.nonce = self._eth_web3.eth.get_transaction_count(self.address) - tx = l1_bridge.functions.deposit(transaction.to, - transaction.token, - transaction.amount, - transaction.l2_gas_limit, - transaction.gas_per_pubdata_byte, - transaction.refund_recipient - ).build_transaction({ + transaction.options.nonce = self._eth_web3.eth.get_transaction_count( + self.address + ) + tx = l1_bridge.functions.deposit( + transaction.to, + transaction.token, + transaction.amount, + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + transaction.refund_recipient, + ).build_transaction( + { "from": self.address, "maxFeePerGas": transaction.options.max_fee_per_gas, "maxPriorityFeePerGas": transaction.options.max_priority_fee_per_gas, "nonce": self._eth_web3.eth.get_transaction_count(self.address), "value": transaction.options.value, - - }) + } + ) signed_tx = self._l1_account.sign_transaction(tx) txn_hash = self._eth_web3.eth.send_raw_transaction(signed_tx.rawTransaction) @@ -403,33 +551,41 @@ def deposit(self, transaction: DepositTransaction): def estimate_gas_deposit(self, transaction: DepositTransaction): transaction = self.prepare_deposit_tx(transaction) if is_eth(transaction.token): - tx = self.contract.functions.requestL2Transaction(Web3.to_checksum_address(transaction.to), - transaction.l2_value, - HexStr("0x"), - transaction.l2_gas_limit, - transaction.gas_per_pubdata_byte, - list(), - self.address).build_transaction(prepare_transaction_options(transaction.options, self.address)) + tx = self.contract.functions.requestL2Transaction( + Web3.to_checksum_address(transaction.to), + transaction.l2_value, + HexStr("0x"), + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + list(), + self.address, + ).build_transaction( + prepare_transaction_options(transaction.options, self.address) + ) return self._eth_web3.eth.estimate_gas(tx) else: if transaction.bridge_address is None: bridge = self.get_l1_bridge_contracts().erc20 else: - bridge = self._eth_web3.eth.contract(Web3.to_checksum_address(transaction.bridge_address), - abi=get_erc20_abi()) + bridge = self._eth_web3.eth.contract( + Web3.to_checksum_address(transaction.bridge_address), + abi=get_erc20_abi(), + ) - tx = bridge.functions.deposit(transaction.to, - transaction.token, - transaction.amount, - transaction.l2_gas_limit, - transaction.gas_per_pubdata_byte, - self.address - ).build_transaction(prepare_transaction_options(transaction.options, self.address)) + tx = bridge.functions.deposit( + transaction.to, + transaction.token, + transaction.amount, + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + self.address, + ).build_transaction( + prepare_transaction_options(transaction.options, self.address) + ) return self._eth_web3.eth.estimate_gas(tx) - def claim_failed_deposit(self, deposit_hash: HexStr): receipt = self._zksync_web3.zksync.eth_get_transaction_receipt(deposit_hash) success_log: L1ToL2Log @@ -445,53 +601,68 @@ def claim_failed_deposit(self, deposit_hash: HexStr): transaction = self._zksync_web3.zksync.eth_get_transaction_by_hash(deposit_hash) l1_bridge_address = undo_l1_to_l2_alias(receipt.from_) - l1_bridge = self._eth_web3.eth.contract(address=Web3.to_checksum_address(l1_bridge_address), - abi=l1_bridge_abi_default()) + l1_bridge = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(l1_bridge_address), + abi=l1_bridge_abi_default(), + ) l2_bridge = self._eth_web3.eth.contract(abi=l2_bridge_abi_default()) calldata = l2_bridge.decode_function_input(transaction["data"]) - proof = self._zksync_web3.zksync.zks_get_log_proof(deposit_hash, success_log_index) + proof = self._zksync_web3.zksync.zks_get_log_proof( + deposit_hash, success_log_index + ) if proof is None: raise RuntimeError("Log proof not found!") - options = TransactionOptions(chain_id=self._eth_web3.eth.chain_id, - nonce=self._eth_web3.eth.get_transaction_count(self.address)) - return l1_bridge.functions.claimFailedDeposit(calldata[1]["_l1Sender"], - calldata[1]["_l1Token"], - to_bytes(deposit_hash), - receipt.block_number, - proof.id, - receipt.l1_batch_tx_index, - proof.proof).call(prepare_transaction_options(options, self.address)) - - def estimate_default_bridge_deposit_l2_gas(self, - token: HexStr, - amount: int, - to: HexStr, - gas_per_pubdata_byte: int = None, - from_: HexStr = None) -> int: + options = TransactionOptions( + chain_id=self._eth_web3.eth.chain_id, + nonce=self._eth_web3.eth.get_transaction_count(self.address), + ) + return l1_bridge.functions.claimFailedDeposit( + calldata[1]["_l1Sender"], + calldata[1]["_l1Token"], + to_bytes(deposit_hash), + receipt.block_number, + proof.id, + receipt.l1_batch_tx_index, + proof.proof, + ).call(prepare_transaction_options(options, self.address)) + + def estimate_default_bridge_deposit_l2_gas( + self, + token: HexStr, + amount: int, + to: HexStr, + gas_per_pubdata_byte: int = None, + from_: HexStr = None, + ) -> int: if from_ is None: from_ = self._l1_account.address if gas_per_pubdata_byte is None: gas_per_pubdata_byte = DEPOSIT_GAS_PER_PUBDATA_LIMIT if is_eth(token): - func_call = TxFunctionCall(to=to, - from_=from_, - value=amount, - gas_per_pub_data = gas_per_pubdata_byte) + func_call = TxFunctionCall( + to=to, from_=from_, value=amount, gas_per_pub_data=gas_per_pubdata_byte + ) return self._zksync_web3.zksync.zks_estimate_l1_to_l2_execute(func_call.tx) else: l2_weth_token = ADDRESS_DEFAULT try: - l2_weth_token = self.get_l1_bridge_contracts().weth.functions.l2TokenAddress(token).call() + l2_weth_token = ( + self.get_l1_bridge_contracts() + .weth.functions.l2TokenAddress(token) + .call() + ) except: pass if l2_weth_token == ADDRESS_DEFAULT: value = 0 l1_bridge_address = self.bridge_addresses.erc20_l1_default_bridge l2_bridge_address = self.bridge_addresses.erc20_l2_default_bridge - token_contract = self._eth_web3.eth.contract(Web3.to_checksum_address(token), abi=get_erc20_abi()) + token_contract = self._eth_web3.eth.contract( + Web3.to_checksum_address(token), abi=get_erc20_abi() + ) bridge_data = get_custom_bridge_data(token_contract) else: value = amount @@ -499,42 +670,53 @@ def estimate_default_bridge_deposit_l2_gas(self, l2_bridge_address = self.bridge_addresses.weth_bridge_l2 bridge_data = "0x" - return self.estimate_custom_bridge_deposit_l2_gas(l1_bridge_address, l2_bridge_address, - token, amount, to, bridge_data, from_, - gas_per_pubdata_byte, value) - - def estimate_custom_bridge_deposit_l2_gas(self, - l1_bridge_address: HexStr, - l2_bridge_address: HexStr, - token: HexStr, - amount: int, - to: HexStr, - bridge_data: bytes, - from_: HexStr, - gas_per_pubdata_byte: int = DEPOSIT_GAS_PER_PUBDATA_LIMIT, - value: int = 0) -> int: + return self.estimate_custom_bridge_deposit_l2_gas( + l1_bridge_address, + l2_bridge_address, + token, + amount, + to, + bridge_data, + from_, + gas_per_pubdata_byte, + value, + ) + + def estimate_custom_bridge_deposit_l2_gas( + self, + l1_bridge_address: HexStr, + l2_bridge_address: HexStr, + token: HexStr, + amount: int, + to: HexStr, + bridge_data: bytes, + from_: HexStr, + gas_per_pubdata_byte: int = DEPOSIT_GAS_PER_PUBDATA_LIMIT, + value: int = 0, + ) -> int: calldata = self.get_erc_20_call_data(token, from_, to, amount, bridge_data) - tx = TxFunctionCall(from_=apply_l1_to_l2_alias(l1_bridge_address), - to=l2_bridge_address, - data=calldata, - gas_per_pub_data=gas_per_pubdata_byte, - value=value) + tx = TxFunctionCall( + from_=apply_l1_to_l2_alias(l1_bridge_address), + to=l2_bridge_address, + data=calldata, + gas_per_pub_data=gas_per_pubdata_byte, + value=value, + ) return self._zksync_web3.zksync.zks_estimate_l1_to_l2_execute(tx.tx) - def get_erc_20_call_data(self, - l1_token_address: HexStr, - l1_sender: HexStr, - l2_receiver: HexStr, - amount: int, - bridge_data: bytes) -> HexStr: + def get_erc_20_call_data( + self, + l1_token_address: HexStr, + l1_sender: HexStr, + l2_receiver: HexStr, + amount: int, + bridge_data: bytes, + ) -> HexStr: l2_bridge = self._eth_web3.eth.contract(abi=l2_bridge_abi_default()) - return l2_bridge.encodeABI("finalizeDeposit",( - l1_sender, - l2_receiver, - l1_token_address, - amount, - bridge_data - )) + return l2_bridge.encodeABI( + "finalizeDeposit", + (l1_sender, l2_receiver, l1_token_address, amount, bridge_data), + ) def finalize_withdrawal(self, withdraw_hash, index: int = 0): params = self._finalize_withdrawal_params(withdraw_hash, index) @@ -542,39 +724,52 @@ def finalize_withdrawal(self, withdraw_hash, index: int = 0): for proof in params["proof"]: merkle_proof.append(to_bytes(proof)) - options = TransactionOptions(chain_id=self._eth_web3.eth.chain_id, - nonce=self._eth_web3.eth.get_transaction_count(self.address)) + options = TransactionOptions( + chain_id=self._eth_web3.eth.chain_id, + nonce=self._eth_web3.eth.get_transaction_count(self.address), + ) if is_eth(params["sender"]): withdraw_to = HexStr("0x" + params["message"][4:24].hex()) if withdraw_to.lower() == self.bridge_addresses.weth_bridge_l1.lower(): - tx = self.get_l1_bridge_contracts().weth.functions.finalizeEthWithdrawal(params["l1_batch_number"], - params["l2_message_index"], - params["l2_tx_number_in_block"], - params["message"], - merkle_proof).build_transaction( - prepare_transaction_options(options, self.address) + tx = ( + self.get_l1_bridge_contracts() + .weth.functions.finalizeEthWithdrawal( + params["l1_batch_number"], + params["l2_message_index"], + params["l2_tx_number_in_block"], + params["message"], + merkle_proof, + ) + .build_transaction( + prepare_transaction_options(options, self.address) + ) ) else: - tx = self.contract.functions.finalizeEthWithdrawal(params["l1_batch_number"], - params["l2_message_index"], - params["l2_tx_number_in_block"], - params["message"], - merkle_proof).build_transaction( - prepare_transaction_options(options, self.address) - ) + tx = self.contract.functions.finalizeEthWithdrawal( + params["l1_batch_number"], + params["l2_message_index"], + params["l2_tx_number_in_block"], + params["message"], + merkle_proof, + ).build_transaction(prepare_transaction_options(options, self.address)) signed = self._l1_account.sign_transaction(tx) tx_hash = self._eth_web3.eth.send_raw_transaction(signed.rawTransaction) return tx_hash else: - l2_bridge = self._zksync_web3.zksync.contract(address=params["sender"], abi=l2_bridge_abi_default()) - l1_bridge = self._eth_web3.eth.contract(address=Web3.to_checksum_address( - l2_bridge.functions.l1Bridge().call()), - abi=l1_bridge_abi_default()) - return l1_bridge.functions.finalizeWithdrawal(params["l1_batch_number"], - params["l2_message_index"], - params["message"], - merkle_proof).build_transaction(prepare_transaction_options(options, self.address)) + l2_bridge = self._zksync_web3.zksync.contract( + address=params["sender"], abi=l2_bridge_abi_default() + ) + l1_bridge = self._eth_web3.eth.contract( + address=Web3.to_checksum_address(l2_bridge.functions.l1Bridge().call()), + abi=l1_bridge_abi_default(), + ) + return l1_bridge.functions.finalizeWithdrawal( + params["l1_batch_number"], + params["l2_message_index"], + params["message"], + merkle_proof, + ).build_transaction(prepare_transaction_options(options, self.address)) def is_withdrawal_finalized(self, withdraw_hash, index: int = 0): tx_receipt = self._zksync_web3.zksync.get_transaction_receipt(withdraw_hash) @@ -582,43 +777,58 @@ def is_withdrawal_finalized(self, withdraw_hash, index: int = 0): l2_to_l1_log_index = self._get_withdraw_l2_to_l1_log(tx_receipt, index) sender = add_0x_prefix(HexStr(log.topics[1][12:].hex())) hex_hash = withdraw_hash.hex() - proof: ZksMessageProof = self._zksync_web3.zksync.zks_get_log_proof(hex_hash, l2_to_l1_log_index) + proof: ZksMessageProof = self._zksync_web3.zksync.zks_get_log_proof( + hex_hash, l2_to_l1_log_index + ) l2_block_number = log["l1BatchNumber"] - options = TransactionOptions(chain_id=self._eth_web3.eth.chain_id, - nonce=self._eth_web3.eth.get_transaction_count(self.address)) + options = TransactionOptions( + chain_id=self._eth_web3.eth.chain_id, + nonce=self._eth_web3.eth.get_transaction_count(self.address), + ) if is_eth(sender): - return self.contract.functions.isEthWithdrawalFinalized(l2_block_number, - proof.id).call(prepare_transaction_options(options, self.address)) + return self.contract.functions.isEthWithdrawalFinalized( + l2_block_number, proof.id + ).call(prepare_transaction_options(options, self.address)) else: # TODO: check should it be different account for L1/L2 - l1_bridge = self._eth_web3.eth.contract(address=Web3.to_checksum_address( - self.bridge_addresses.erc20_l1_default_bridge), - abi=l1_bridge_abi_default()) - return l1_bridge.functions.isWithdrawalFinalized(l2_block_number, proof.id).call() + l1_bridge = self._eth_web3.eth.contract( + address=Web3.to_checksum_address( + self.bridge_addresses.erc20_l1_default_bridge + ), + abi=l1_bridge_abi_default(), + ) + return l1_bridge.functions.isWithdrawalFinalized( + l2_block_number, proof.id + ).call() def request_execute(self, transaction: RequestExecuteCallMsg): transaction = self.get_request_execute_transaction(transaction) - tx = self.contract.functions.requestL2Transaction(transaction.contract_address, - transaction.l2_value, - transaction.call_data, - transaction.l2_gas_limit, - transaction.gas_per_pubdata_byte, - transaction.factory_deps, - transaction.refund_recipient).build_transaction(prepare_transaction_options(transaction.options, transaction.from_)) + tx = self.contract.functions.requestL2Transaction( + transaction.contract_address, + transaction.l2_value, + transaction.call_data, + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + transaction.factory_deps, + transaction.refund_recipient, + ).build_transaction( + prepare_transaction_options(transaction.options, transaction.from_) + ) signed_tx = self._l1_account.sign_transaction(tx) tx_hash = self._eth_web3.eth.send_raw_transaction(signed_tx.rawTransaction) return tx_hash - def check_if_l1_chain_is_london_ready(self): head = self._eth_web3.eth.get_block("latest") if head["baseFeePerGas"] is not None: return True, head return False, head - def get_request_execute_transaction(self, transaction: RequestExecuteCallMsg) -> RequestExecuteCallMsg: + def get_request_execute_transaction( + self, transaction: RequestExecuteCallMsg + ) -> RequestExecuteCallMsg: if transaction.options is None: transaction.options = TransactionOptions() if transaction.factory_deps is None: @@ -628,20 +838,37 @@ def get_request_execute_transaction(self, transaction: RequestExecuteCallMsg) -> if transaction.from_ is None: transaction.from_ = self.address if transaction.options.nonce is None: - transaction.options.nonce = self._eth_web3.eth.get_transaction_count(self.address) + transaction.options.nonce = self._eth_web3.eth.get_transaction_count( + self.address + ) if transaction.l2_gas_limit == 0: - meta = EIP712Meta(gas_per_pub_data=transaction.gas_per_pubdata_byte, - factory_deps=transaction.factory_deps) - transaction.l2_gas_limit = self._zksync_web3.zksync.zks_estimate_l1_to_l2_execute({"from": transaction.from_, - "to": transaction.contract_address, - "eip712Meta": meta}) - if transaction.options.gas_price is None and transaction.options.max_fee_per_gas is None: + meta = EIP712Meta( + gas_per_pub_data=transaction.gas_per_pubdata_byte, + factory_deps=transaction.factory_deps, + ) + transaction.l2_gas_limit = ( + self._zksync_web3.zksync.zks_estimate_l1_to_l2_execute( + { + "from": transaction.from_, + "to": transaction.contract_address, + "eip712Meta": meta, + } + ) + ) + if ( + transaction.options.gas_price is None + and transaction.options.max_fee_per_gas is None + ): isReady, head = self.check_if_l1_chain_is_london_ready() if isReady: if transaction.options.max_priority_fee_per_gas is None: - transaction.options.max_priority_fee_per_gas = self._zksync_web3.zksync.max_priority_fee - transaction.options.max_fee_per_gas = int(((head["baseFeePerGas"] * 3) / 2) - + transaction.options.max_priority_fee_per_gas) + transaction.options.max_priority_fee_per_gas = ( + self._zksync_web3.zksync.max_priority_fee + ) + transaction.options.max_fee_per_gas = int( + ((head["baseFeePerGas"] * 3) / 2) + + transaction.options.max_priority_fee_per_gas + ) else: transaction.options.gas_price = self._eth_web3.eth.gas_price @@ -651,10 +878,16 @@ def get_request_execute_transaction(self, transaction: RequestExecuteCallMsg) -> else: gas_price_for_estimation = transaction.options.gas_price - base_cost = self.get_base_cost(transaction.l2_gas_limit, transaction.gas_per_pubdata_byte, gas_price_for_estimation) + base_cost = self.get_base_cost( + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + gas_price_for_estimation, + ) if transaction.options.value is None: - transaction.options.value = base_cost + transaction.operator_tip + transaction.l2_value + transaction.options.value = ( + base_cost + transaction.operator_tip + transaction.l2_value + ) check_base_cost(base_cost, transaction.options.value) @@ -662,13 +895,16 @@ def get_request_execute_transaction(self, transaction: RequestExecuteCallMsg) -> def estimate_gas_request_execute(self, transaction: RequestExecuteCallMsg) -> int: transaction = self.get_request_execute_transaction(transaction) - tx = self.contract.functions.requestL2Transaction(Web3.to_checksum_address(transaction.contract_address), - transaction.l2_value, - transaction.call_data, - transaction.l2_gas_limit, - transaction.gas_per_pubdata_byte, - transaction.factory_deps, - transaction.refund_recipient).build_transaction(prepare_transaction_options(transaction.options, self.address)) + tx = self.contract.functions.requestL2Transaction( + Web3.to_checksum_address(transaction.contract_address), + transaction.l2_value, + transaction.call_data, + transaction.l2_gas_limit, + transaction.gas_per_pubdata_byte, + transaction.factory_deps, + transaction.refund_recipient, + ).build_transaction( + prepare_transaction_options(transaction.options, self.address) + ) return self._eth_web3.eth.estimate_gas(tx) - diff --git a/zksync2/account/wallet_l2.py b/zksync2/account/wallet_l2.py index a7bcd17..0270755 100644 --- a/zksync2/account/wallet_l2.py +++ b/zksync2/account/wallet_l2.py @@ -5,54 +5,81 @@ from web3 import Web3 from zksync2.account.utils import prepare_transaction_options, options_from_712 -from zksync2.core.types import ZkBlockParams, L2BridgeContracts, TransferTransaction, TransactionOptions, \ - WithdrawTransaction, ADDRESS_DEFAULT +from zksync2.core.types import ( + ZkBlockParams, + L2BridgeContracts, + TransferTransaction, + TransactionOptions, + WithdrawTransaction, + ADDRESS_DEFAULT, +) from zksync2.core.utils import is_eth from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses -from zksync2.manage_contracts.utils import zksync_abi_default, nonce_holder_abi_default, l2_bridge_abi_default, \ - get_erc20_abi +from zksync2.manage_contracts.utils import ( + zksync_abi_default, + nonce_holder_abi_default, + l2_bridge_abi_default, + get_erc20_abi, +) from zksync2.module.response_types import ZksAccountBalances from zksync2.signer.eth_signer import PrivateKeyEthSigner from zksync2.transaction.transaction_builders import TxFunctionCall, TxWithdraw class WalletL2: - def __init__(self, - zksync_web3: Web3, - eth_web3: Web3, - l1_account: BaseAccount): + def __init__(self, zksync_web3: Web3, eth_web3: Web3, l1_account: BaseAccount): self._eth_web3 = eth_web3 self._zksync_web3 = zksync_web3 self._main_contract_address = self._zksync_web3.zksync.zks_main_contract() self._l1_account = l1_account - self.contract = self._eth_web3.eth.contract(Web3.to_checksum_address(self._main_contract_address), abi=zksync_abi_default()) - - def get_balance(self, block_tag = ZkBlockParams.COMMITTED.value, token_address: HexStr = None) -> int: - return self._zksync_web3.zksync.zks_get_balance(self._l1_account.address, block_tag, token_address) + self.contract = self._eth_web3.eth.contract( + Web3.to_checksum_address(self._main_contract_address), + abi=zksync_abi_default(), + ) + + def get_balance( + self, block_tag=ZkBlockParams.COMMITTED.value, token_address: HexStr = None + ) -> int: + return self._zksync_web3.zksync.zks_get_balance( + self._l1_account.address, block_tag, token_address + ) def get_all_balances(self) -> ZksAccountBalances: - return self._zksync_web3.zksync.zks_get_all_account_balances(self._l1_account.address) + return self._zksync_web3.zksync.zks_get_all_account_balances( + self._l1_account.address + ) def get_deployment_nonce(self) -> int: - nonce_holder = self._zksync_web3.zksync.contract(address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, - abi=nonce_holder_abi_default()) - deployment_nonce = nonce_holder.functions.getDeploymentNonce(self._l1_account.address).call( - { - "from": self._l1_account.address - }) + nonce_holder = self._zksync_web3.zksync.contract( + address=ZkSyncAddresses.NONCE_HOLDER_ADDRESS.value, + abi=nonce_holder_abi_default(), + ) + deployment_nonce = nonce_holder.functions.getDeploymentNonce( + self._l1_account.address + ).call({"from": self._l1_account.address}) return deployment_nonce def get_l2_bridge_contracts(self) -> L2BridgeContracts: addresses = self._zksync_web3.zksync.zks_get_bridge_contracts() - return L2BridgeContracts(erc20=self._zksync_web3.eth.contract(address=Web3.to_checksum_address(addresses.erc20_l2_default_bridge), - abi=l2_bridge_abi_default()), - weth=self._zksync_web3.eth.contract(address=Web3.to_checksum_address(addresses.weth_bridge_l2), - abi=l2_bridge_abi_default())) + return L2BridgeContracts( + erc20=self._zksync_web3.eth.contract( + address=Web3.to_checksum_address(addresses.erc20_l2_default_bridge), + abi=l2_bridge_abi_default(), + ), + weth=self._zksync_web3.eth.contract( + address=Web3.to_checksum_address(addresses.weth_bridge_l2), + abi=l2_bridge_abi_default(), + ), + ) def transfer(self, tx: TransferTransaction) -> HexStr: - tx_fun_call = self._zksync_web3.zksync.get_transfer_transaction(tx, self._l1_account.address) + tx_fun_call = self._zksync_web3.zksync.get_transfer_transaction( + tx, self._l1_account.address + ) if tx.options.gas_limit == 0: - tx_712 = tx_fun_call.tx712(self._zksync_web3.zksync.zks_estimate_gas_transfer(tx_fun_call.tx)) + tx_712 = tx_fun_call.tx712( + self._zksync_web3.zksync.zks_estimate_gas_transfer(tx_fun_call.tx) + ) if tx.token_address is None or is_eth(tx.token_address): signer = PrivateKeyEthSigner(self._l1_account, tx.options.chain_id) @@ -63,15 +90,20 @@ def transfer(self, tx: TransferTransaction) -> HexStr: return tx_hash else: - token_contract = self._zksync_web3.zksync.contract(tx.token_address, abi=get_erc20_abi()) + token_contract = self._zksync_web3.zksync.contract( + tx.token_address, abi=get_erc20_abi() + ) options = options_from_712(tx_712) - transaction = token_contract.functions.transfer(tx.to, tx.amount).build_transaction( - prepare_transaction_options(options, - self._l1_account.address) + transaction = token_contract.functions.transfer( + tx.to, tx.amount + ).build_transaction( + prepare_transaction_options(options, self._l1_account.address) ) signed = self._l1_account.sign_transaction(transaction) - tx_hash = self._zksync_web3.zksync.send_raw_transaction(signed.rawTransaction) + tx_hash = self._zksync_web3.zksync.send_raw_transaction( + signed.rawTransaction + ) return tx_hash @@ -81,7 +113,10 @@ def withdraw(self, tx: WithdrawTransaction): if tx.options.chain_id is None: tx.options.chain_id = self._zksync_web3.zksync.chain_id if tx.options.nonce is None: - tx.options.nonce = self._zksync_web3.zksync.get_transaction_count(Web3.to_checksum_address(self._l1_account.address), ZkBlockParams.LATEST.value) + tx.options.nonce = self._zksync_web3.zksync.get_transaction_count( + Web3.to_checksum_address(self._l1_account.address), + ZkBlockParams.LATEST.value, + ) if tx.options.gas_price is None: tx.options.gas_price = self._zksync_web3.zksync.gas_price @@ -96,7 +131,7 @@ def withdraw(self, tx: WithdrawTransaction): gas_limit=0 if tx.options.gas_limit is None else tx.options.gas_limit, gas_price=tx.options.gas_price, token=tx.token, - bridge_address=tx.bridge_address + bridge_address=tx.bridge_address, ) estimated_gas = self._zksync_web3.zksync.eth_estimate_gas(transaction.tx) @@ -108,19 +143,26 @@ def withdraw(self, tx: WithdrawTransaction): if tx.bridge_address is None: l2_weth_token = ADDRESS_DEFAULT try: - l2_weth_token = self.get_l2_bridge_contracts().weth.functions.l1TokenAddress(tx.token).call() + l2_weth_token = ( + self.get_l2_bridge_contracts() + .weth.functions.l1TokenAddress(tx.token) + .call() + ) except: pass if l2_weth_token == ADDRESS_DEFAULT: tx.bridge_address = self.get_l2_bridge_contracts().erc20 else: tx.bridge_address = self.get_l2_bridge_contracts().weth - bridge = self._zksync_web3.zksync.contract(address=Web3.to_checksum_address(tx.bridge_address), - abi=l2_bridge_abi_default()) - transaction = bridge.functions.withdraw(self._l1_account.address, - tx.token, - tx.amount).build_transaction(prepare_transaction_options(tx.options, self._l1_account.address)) + bridge = self._zksync_web3.zksync.contract( + address=Web3.to_checksum_address(tx.bridge_address), + abi=l2_bridge_abi_default(), + ) + transaction = bridge.functions.withdraw( + self._l1_account.address, tx.token, tx.amount + ).build_transaction( + prepare_transaction_options(tx.options, self._l1_account.address) + ) signed_tx = self._l1_account.sign_transaction(transaction) return self._zksync_web3.zksync.send_raw_transaction(signed_tx.rawTransaction) - diff --git a/zksync2/core/types.py b/zksync2/core/types.py index 88f5718..97353b6 100644 --- a/zksync2/core/types.py +++ b/zksync2/core/types.py @@ -18,6 +18,7 @@ class RecommendedGasLimit(IntEnum): ERC20_APPROVE = 50000 DEPOSIT_GAS_PER_PUBDATA_LIMIT = 800 + ADDRESS_DEFAULT = HexStr("0x" + "0" * 40) L2_ETH_TOKEN_ADDRESS = HexStr("0x000000000000000000000000000000000000800a") @@ -85,11 +86,13 @@ class BridgeAddresses: weth_bridge_l1: HexStr weth_bridge_l2: HexStr + @dataclass class L1BridgeContracts: erc20: Contract weth: Contract + @dataclass class L2BridgeContracts: erc20: Contract @@ -134,6 +137,7 @@ class ContractAccountInfo: account_abstraction_version: AccountAbstractionVersion account_nonce_ordering: AccountNonceOrdering + @dataclass class BlockRange: beginning: str @@ -285,10 +289,3 @@ class FullDepositFee: max_fee_per_gas: int = None max_priority_fee_per_gas: int = None gas_price: int = None - - - - - - - diff --git a/zksync2/core/utils.py b/zksync2/core/utils.py index 9e15679..c7c402d 100644 --- a/zksync2/core/utils.py +++ b/zksync2/core/utils.py @@ -13,12 +13,13 @@ L1_TO_L2_ALIAS_OFFSET = "0x1111000000000000000000000000000000001111" ADDRESS_DEFAULT = HexStr("0x" + "0" * 40) -L2_ETH_TOKEN_ADDRESS = HexStr('0x000000000000000000000000000000000000800a') +L2_ETH_TOKEN_ADDRESS = HexStr("0x000000000000000000000000000000000000800a") BOOTLOADER_FORMAL_ADDRESS = HexStr("0x0000000000000000000000000000000000008001") DEPOSIT_GAS_PER_PUBDATA_LIMIT = 800 MAX_PRIORITY_FEE_PER_GAS = 100_000_000 + def int_to_bytes(x: int) -> bytes: return x.to_bytes((x.bit_length() + 7) // 8, byteorder=sys.byteorder) @@ -63,19 +64,22 @@ def get_custom_bridge_data(token_contract) -> bytes: name = token_contract.functions.name().call() symbol = token_contract.functions.symbol().call() decimals = token_contract.functions.decimals().call() - name_encoded = encode(['string'], [name]) - symbol_encoded = encode(['string'], [symbol]) - decimals_encoded = encode(['uint256'], [decimals]) + name_encoded = encode(["string"], [name]) + symbol_encoded = encode(["string"], [symbol]) + decimals_encoded = encode(["uint256"], [decimals]) - return encode(['bytes', 'bytes', 'bytes'], [name_encoded, symbol_encoded, decimals_encoded]) + return encode( + ["bytes", "bytes", "bytes"], [name_encoded, symbol_encoded, decimals_encoded] + ) def apply_l1_to_l2_alias(address: HexStr): value = (int(L1_TO_L2_ALIAS_OFFSET, 16) + int(address, 16)) % ADDRESS_MODULO hex_result = remove_0x_prefix(Web3.to_hex(value)) - result = hex_result.rjust(40, '0') + result = hex_result.rjust(40, "0") return add_0x_prefix(result) + def undo_l1_to_l2_alias(address: HexStr): result = int(address, 16) - int(L1_TO_L2_ALIAS_OFFSET, 16) if result < 0: @@ -87,6 +91,7 @@ def undo_l1_to_l2_alias(address: HexStr): class RequestExecuteTransaction: pass + class RecommendedGasLimit(IntEnum): DEPOSIT = 10000000 EXECUTE = 620000 @@ -94,4 +99,3 @@ class RecommendedGasLimit(IntEnum): DEPOSIT_GAS_PER_PUBDATA_LIMIT = 800 L1_RECOMMENDED_ETH_DEPOSIT_GAS_LIMIT = 200000 L1_RECOMMENDED_MIN_ERC_20_DEPOSIT_GAS_LIMIT = 400000 - diff --git a/zksync2/eip712/domain_separator.py b/zksync2/eip712/domain_separator.py index 0704e0a..e06c843 100644 --- a/zksync2/eip712/domain_separator.py +++ b/zksync2/eip712/domain_separator.py @@ -1,14 +1,17 @@ from zksync2.eip712.struct import EIP712Struct from zksync2.eip712.types import String, Uint, Address, Bytes -def make_domain(name=None, version=None, chainId=None, verifyingContract=None, salt=None): + +def make_domain( + name=None, version=None, chainId=None, verifyingContract=None, salt=None +): """Helper method to create the standard EIP712Domain struct for you. Per the standard, if a value is not used then the parameter is omitted from the struct entirely. """ if all(i is None for i in [name, version, chainId, verifyingContract, salt]): - raise ValueError('At least one argument must be given.') + raise ValueError("At least one argument must be given.") class EIP712Domain(EIP712Struct): pass @@ -16,18 +19,18 @@ class EIP712Domain(EIP712Struct): kwargs = dict() if name is not None: EIP712Domain.name = String() - kwargs['name'] = str(name) + kwargs["name"] = str(name) if version is not None: EIP712Domain.version = String() - kwargs['version'] = str(version) + kwargs["version"] = str(version) if chainId is not None: EIP712Domain.chainId = Uint(256) - kwargs['chainId'] = int(chainId) + kwargs["chainId"] = int(chainId) if verifyingContract is not None: EIP712Domain.verifyingContract = Address() - kwargs['verifyingContract'] = verifyingContract + kwargs["verifyingContract"] = verifyingContract if salt is not None: EIP712Domain.salt = Bytes(32) - kwargs['salt'] = salt + kwargs["salt"] = salt return EIP712Domain(**kwargs) diff --git a/zksync2/eip712/struct.py b/zksync2/eip712/struct.py index 0562033..049378c 100644 --- a/zksync2/eip712/struct.py +++ b/zksync2/eip712/struct.py @@ -12,8 +12,8 @@ class OrderedAttributesMeta(type): - """Metaclass to ensure struct attribute order is preserved. - """ + """Metaclass to ensure struct attribute order is preserved.""" + @classmethod def __prepare__(mcs, name, bases): return OrderedDict() @@ -30,6 +30,7 @@ class MyStruct(EIP712Struct): struct_instance = MyStruct(some_param='some_value') """ + def __init__(self, **kwargs): super(EIP712Struct, self).__init__(self.type_name, None) members = self.get_members() @@ -62,16 +63,14 @@ def encode_value(self, value=None): else: # Regular types are encoded as normal encoded_values.append(typ.encode_value(self.values[name])) - return b''.join(encoded_values) + return b"".join(encoded_values) def get_data_value(self, name): - """Get the value of the given struct parameter. - """ + """Get the value of the given struct parameter.""" return self.values.get(name) def set_data_value(self, name, value): - """Set the value of the given struct parameter. - """ + """Set the value of the given struct parameter.""" if name in self.values: self.values[name] = value @@ -90,22 +89,28 @@ def data_dict(self): @classmethod def _encode_type(cls, resolve_references: bool) -> str: - member_sigs = [f'{typ.type_name} {name}' for name, typ in cls.get_members()] + member_sigs = [f"{typ.type_name} {name}" for name, typ in cls.get_members()] struct_sig = f'{cls.type_name}({",".join(member_sigs)})' if resolve_references: reference_structs = set() cls._gather_reference_structs(reference_structs) - sorted_structs = sorted(list(s for s in reference_structs if s != cls), key=lambda s: s.type_name) + sorted_structs = sorted( + list(s for s in reference_structs if s != cls), + key=lambda s: s.type_name, + ) for struct in sorted_structs: struct_sig += struct._encode_type(resolve_references=False) return struct_sig @classmethod def _gather_reference_structs(cls, struct_set): - """Finds reference structs defined in this struct type, and inserts them into the given set. - """ - structs = [m[1] for m in cls.get_members() if isinstance(m[1], type) and issubclass(m[1], EIP712Struct)] + """Finds reference structs defined in this struct type, and inserts them into the given set.""" + structs = [ + m[1] + for m in cls.get_members() + if isinstance(m[1], type) and issubclass(m[1], EIP712Struct) + ] for struct in structs: if struct not in struct_set: struct_set.add(struct) @@ -129,7 +134,7 @@ def hash_struct(self) -> bytes: hash_struct => keccak(type_hash || encode_data) """ - return keccak(b''.join([self.type_hash(), self.encode_value()])) + return keccak(b"".join([self.type_hash(), self.encode_value()])) @classmethod def get_members(cls) -> List[Tuple[str, EIP712Type]]: @@ -137,30 +142,36 @@ def get_members(cls) -> List[Tuple[str, EIP712Type]]: Each tuple is (, ). The list's order is determined by definition order. """ - members = [m for m in cls.__dict__.items() if isinstance(m[1], EIP712Type) - or (isinstance(m[1], type) and issubclass(m[1], EIP712Struct))] + members = [ + m + for m in cls.__dict__.items() + if isinstance(m[1], EIP712Type) + or (isinstance(m[1], type) and issubclass(m[1], EIP712Struct)) + ] return members @staticmethod def _assert_domain(domain): result = domain or default_domain if not result: - raise ValueError('Domain must be provided, or eip712.default_domain must be set.') + raise ValueError( + "Domain must be provided, or eip712.default_domain must be set." + ) return result - def to_message(self, domain: 'EIP712Struct' = None) -> dict: + def to_message(self, domain: "EIP712Struct" = None) -> dict: """Convert a struct into a dictionary suitable for messaging. - Dictionary is of the form: - { - 'primaryType': Name of the primary type, - 'types': Definition of each included struct type (including the domain type) - 'domain': Values for the domain struct, - 'message': Values for the message struct, - } + Dictionary is of the form: + { + 'primaryType': Name of the primary type, + 'types': Definition of each included struct type (including the domain type) + 'domain': Values for the domain struct, + 'message': Values for the message struct, + } - :returns: This struct + the domain in dict form, structured as specified for EIP712 messages. - """ + :returns: This struct + the domain in dict form, structured as specified for EIP712 messages. + """ domain = self._assert_domain(domain) structs = {domain, self} self._gather_reference_structs(structs) @@ -168,26 +179,29 @@ def to_message(self, domain: 'EIP712Struct' = None) -> dict: # Build type dictionary types = dict() for struct in structs: - members_json = [{ - 'name': m[0], - 'type': m[1].type_name, - } for m in struct.get_members()] + members_json = [ + { + "name": m[0], + "type": m[1].type_name, + } + for m in struct.get_members() + ] types[struct.type_name] = members_json result = { - 'primaryType': self.type_name, - 'types': types, - 'domain': domain.data_dict(), - 'message': self.data_dict(), + "primaryType": self.type_name, + "types": types, + "domain": domain.data_dict(), + "message": self.data_dict(), } return result - def to_message_json(self, domain: 'EIP712Struct' = None) -> str: + def to_message_json(self, domain: "EIP712Struct" = None) -> str: message = self.to_message(domain) return json.dumps(message, cls=BytesJSONEncoder) - def signable_bytes(self, domain: 'EIP712Struct' = None) -> bytes: + def signable_bytes(self, domain: "EIP712Struct" = None) -> bytes: """Return a ``bytes`` object suitable for signing, as specified for EIP712. As per the spec, bytes are constructed as follows: @@ -197,11 +211,11 @@ def signable_bytes(self, domain: 'EIP712Struct' = None) -> bytes: :return: The bytes object """ domain = self._assert_domain(domain) - result = b'\x19\x01' + domain.hash_struct() + self.hash_struct() + result = b"\x19\x01" + domain.hash_struct() + self.hash_struct() return result @classmethod - def from_message(cls, message_dict: dict) -> 'StructTuple': + def from_message(cls, message_dict: dict) -> "StructTuple": """Convert a message dictionary into two EIP712Struct objects - one for domain, another for the message struct. Returned as a StructTuple, which has the attributes ``message`` and ``domain``. @@ -218,24 +232,26 @@ def from_message(cls, message_dict: dict) -> 'StructTuple': structs = dict() unfulfilled_struct_params = defaultdict(list) - for type_name in message_dict['types']: + for type_name in message_dict["types"]: # Dynamically construct struct class from dict representation StructFromJSON = type(type_name, (EIP712Struct,), {}) - for member in message_dict['types'][type_name]: + for member in message_dict["types"][type_name]: # Either a basic solidity type is set, or None if referring to a reference struct (we'll fill it later) - member_name = member['name'] - member_sol_type = from_solidity_type(member['type']) + member_name = member["name"] + member_sol_type = from_solidity_type(member["type"]) setattr(StructFromJSON, member_name, member_sol_type) if member_sol_type is None: # Track the refs we'll need to set later. - unfulfilled_struct_params[type_name].append((member_name, member['type'])) + unfulfilled_struct_params[type_name].append( + (member_name, member["type"]) + ) structs[type_name] = StructFromJSON # Now that custom structs have been parsed, pass through again to set the references for struct_name, unfulfilled_member_names in unfulfilled_struct_params.items(): - regex_pattern = r'([a-zA-Z0-9_]+)(\[(\d+)?\])?' + regex_pattern = r"([a-zA-Z0-9_]+)(\[(\d+)?\])?" struct_class = structs[struct_name] for name, type_name in unfulfilled_member_names: @@ -244,16 +260,18 @@ def from_message(cls, message_dict: dict) -> 'StructTuple': ref_struct = structs[base_type_name] if match.group(2): # The type is an array of the struct - arr_len = match.group(3) or 0 # length of 0 means the array is dynamically sized + arr_len = ( + match.group(3) or 0 + ) # length of 0 means the array is dynamically sized setattr(struct_class, name, Array(ref_struct, arr_len)) else: setattr(struct_class, name, ref_struct) - primary_struct = structs[message_dict['primaryType']] - domain_struct = structs['EIP712Domain'] + primary_struct = structs[message_dict["primaryType"]] + domain_struct = structs["EIP712Domain"] - primary_result = primary_struct(**message_dict['message']) - domain_result = domain_struct(**message_dict['domain']) + primary_result = primary_struct(**message_dict["message"]) + domain_result = domain_struct(**message_dict["domain"]) result = StructTuple(message=primary_result, domain=domain_result) return result @@ -272,15 +290,21 @@ def _assert_property_type(cls, key, value): if isinstance(typ, type) and issubclass(typ, EIP712Struct): # We expect an EIP712Struct instance. Assert that's true, and check the struct signature too. - if not isinstance(value, EIP712Struct) or value._encode_type(False) != typ._encode_type(False): - raise ValueError(f'Given value is of type {type(value)}, but we expected {typ}') + if not isinstance(value, EIP712Struct) or value._encode_type( + False + ) != typ._encode_type(False): + raise ValueError( + f"Given value is of type {type(value)}, but we expected {typ}" + ) else: # Since it isn't a nested struct, its an EIP712Type try: typ.encode_value(value) except Exception as e: - raise ValueError(f'The python type {type(value)} does not appear ' - f'to be supported for data type {typ}.') from e + raise ValueError( + f"The python type {type(value)} does not appear " + f"to be supported for data type {typ}." + ) from e def __getitem__(self, key): """Provide access directly to the underlying value dictionary""" @@ -295,7 +319,7 @@ def __setitem__(self, key, value): return self.values.__setitem__(key, value) def __delitem__(self, _): - raise TypeError('Deleting entries from an EIP712Struct is not allowed.') + raise TypeError("Deleting entries from an EIP712Struct is not allowed.") def __eq__(self, other): if not other: @@ -309,7 +333,10 @@ def __eq__(self, other): return False # Our structs are considered equal if their type signature and encoded value signature match. # E.g., like computing signable bytes but without a domain separator - return self.encode_type() == other.encode_type() and self.encode_value() == other.encode_value() + return ( + self.encode_type() == other.encode_type() + and self.encode_value() == other.encode_value() + ) def __hash__(self): value_hashes = [hash(k) ^ hash(v) for k, v in self.values.items()] diff --git a/zksync2/eip712/types.py b/zksync2/eip712/types.py index 0ab615a..f6fbc39 100644 --- a/zksync2/eip712/types.py +++ b/zksync2/eip712/types.py @@ -11,6 +11,7 @@ class EIP712Type: Generally you wouldn't use this - instead, see the subclasses below. Or you may want an EIP712Struct instead. """ + def __init__(self, type_name: str, none_val: Any): self.type_name = type_name self.none_val = none_val @@ -34,8 +35,8 @@ def _encode_value(self, value) -> bytes: pass def __eq__(self, other): - self_type = getattr(self, 'type_name') - other_type = getattr(other, 'type_name') + self_type = getattr(self, "type_name") + other_type = getattr(other, "type_name") return self_type is not None and self_type == other_type @@ -44,7 +45,9 @@ def __hash__(self): class Array(EIP712Type): - def __init__(self, member_type: Union[EIP712Type, Type[EIP712Type]], fixed_length: int = 0): + def __init__( + self, member_type: Union[EIP712Type, Type[EIP712Type]], fixed_length: int = 0 + ): """Represents an array member type. Example: @@ -54,9 +57,9 @@ def __init__(self, member_type: Union[EIP712Type, Type[EIP712Type]], fixed_lengt """ fixed_length = int(fixed_length) if fixed_length == 0: - type_name = f'{member_type.type_name}[]' + type_name = f"{member_type.type_name}[]" else: - type_name = f'{member_type.type_name}[{fixed_length}]' + type_name = f"{member_type.type_name}[{fixed_length}]" self.member_type = member_type self.fixed_length = fixed_length super(Array, self).__init__(type_name, []) @@ -65,13 +68,13 @@ def _encode_value(self, value): """Arrays are encoded by concatenating their encoded contents, and taking the keccak256 hash.""" encoder = self.member_type encoded_values = [encoder.encode_value(v) for v in value] - return keccak(b''.join(encoded_values)) + return keccak(b"".join(encoded_values)) class Address(EIP712Type): def __init__(self): """Represents an ``address`` type.""" - super(Address, self).__init__('address', 0) + super(Address, self).__init__("address", 0) def _encode_value(self, value): """Addresses are encoded like Uint160 numbers.""" @@ -89,7 +92,7 @@ def _encode_value(self, value): class Boolean(EIP712Type): def __init__(self): """Represents a ``bool`` type.""" - super(Boolean, self).__init__('bool', False) + super(Boolean, self).__init__("bool", False) def _encode_value(self, value): """Booleans are encoded like the uint256 values of 0 and 1.""" @@ -98,7 +101,7 @@ def _encode_value(self, value): elif value is True: return Uint(256).encode_value(1) else: - raise ValueError(f'Must be True or False. Got: {value}') + raise ValueError(f"Must be True or False. Got: {value}") class Bytes(EIP712Type): @@ -115,13 +118,13 @@ def __init__(self, length: int = 0): length = int(length) if length == 0: # Special case: Length of 0 means a dynamic bytes type - type_name = 'bytes' + type_name = "bytes" elif 1 <= length <= 32: - type_name = f'bytes{length}' + type_name = f"bytes{length}" else: - raise ValueError(f'Byte length must be between 1 or 32. Got: {length}') + raise ValueError(f"Byte length must be between 1 or 32. Got: {length}") self.length = length - super(Bytes, self).__init__(type_name, b'') + super(Bytes, self).__init__(type_name, b"") def _encode_value(self, value): """Static bytesN types are encoded by right-padding to 32 bytes. Dynamic bytes types are keccak256 hashed.""" @@ -133,7 +136,9 @@ def _encode_value(self, value): return keccak(value) else: if len(value) > self.length: - raise ValueError(f'{self.type_name} was given bytes with length {len(value)}') + raise ValueError( + f"{self.type_name} was given bytes with length {len(value)}" + ) padding = bytes(32 - len(value)) return value + padding @@ -149,20 +154,22 @@ def __init__(self, length: int = 256): """ length = int(length) if length < 8 or length > 256 or length % 8 != 0: - raise ValueError(f'Int length must be a multiple of 8, between 8 and 256. Got: {length}') + raise ValueError( + f"Int length must be a multiple of 8, between 8 and 256. Got: {length}" + ) self.length = length - super(Int, self).__init__(f'int{length}', 0) + super(Int, self).__init__(f"int{length}", 0) def _encode_value(self, value: int): """Ints are encoded by padding them to 256-bit representations.""" - value.to_bytes(self.length // 8, byteorder='big', signed=True) # For validation - return value.to_bytes(32, byteorder='big', signed=True) + value.to_bytes(self.length // 8, byteorder="big", signed=True) # For validation + return value.to_bytes(32, byteorder="big", signed=True) class String(EIP712Type): def __init__(self): """Represents a string type.""" - super(String, self).__init__('string', '') + super(String, self).__init__("string", "") def _encode_value(self, value): """Strings are encoded by taking the keccak256 hash of their contents.""" @@ -180,38 +187,42 @@ def __init__(self, length: int = 256): """ length = int(length) if length < 8 or length > 256 or length % 8 != 0: - raise ValueError(f'Uint length must be a multiple of 8, between 8 and 256. Got: {length}') + raise ValueError( + f"Uint length must be a multiple of 8, between 8 and 256. Got: {length}" + ) self.length = length - super(Uint, self).__init__(f'uint{length}', 0) + super(Uint, self).__init__(f"uint{length}", 0) def _encode_value(self, value: int): """Uints are encoded by padding them to 256-bit representations.""" - value.to_bytes(self.length // 8, byteorder='big', signed=False) # For validation - return value.to_bytes(32, byteorder='big', signed=False) + value.to_bytes( + self.length // 8, byteorder="big", signed=False + ) # For validation + return value.to_bytes(32, byteorder="big", signed=False) # This helper dict maps solidity's type names to our EIP712Type classes solidity_type_map = { - 'address': Address, - 'bool': Boolean, - 'bytes': Bytes, - 'int': Int, - 'string': String, - 'uint': Uint, + "address": Address, + "bool": Boolean, + "bytes": Bytes, + "int": Int, + "string": String, + "uint": Uint, } def from_solidity_type(solidity_type: str): """Convert a string into the EIP712Type implementation. Basic types only.""" - pattern = r'([a-z]+)(\d+)?(\[(\d+)?\])?' + pattern = r"([a-z]+)(\d+)?(\[(\d+)?\])?" match = re.match(pattern, solidity_type) if match is None: return None type_name = match.group(1) # The type name, like the "bytes" in "bytes32" - opt_len = match.group(2) # An optional length spec, like the "32" in "bytes32" - is_array = match.group(3) # Basically just checks for square brackets + opt_len = match.group(2) # An optional length spec, like the "32" in "bytes32" + is_array = match.group(3) # Basically just checks for square brackets array_len = match.group(4) # For fixed length arrays only, this is the length if type_name not in solidity_type_map: diff --git a/zksync2/manage_contracts/contract_encoder_base.py b/zksync2/manage_contracts/contract_encoder_base.py index 7f1ab02..c937a1b 100644 --- a/zksync2/manage_contracts/contract_encoder_base.py +++ b/zksync2/manage_contracts/contract_encoder_base.py @@ -15,18 +15,22 @@ class JsonConfiguration(Enum): class BaseContractEncoder: - @classmethod - def from_json(cls, web3: Web3, compiled_contract: Path, conf_type: JsonConfiguration = JsonConfiguration.COMBINED): - with compiled_contract.open(mode='r') as json_f: + def from_json( + cls, + web3: Web3, + compiled_contract: Path, + conf_type: JsonConfiguration = JsonConfiguration.COMBINED, + ): + with compiled_contract.open(mode="r") as json_f: data = json.load(json_f) if conf_type == JsonConfiguration.COMBINED: contracts = list() - for contract_path, contract_data in data['contracts'].items(): + for contract_path, contract_data in data["contracts"].items(): # Check if 'abi' key exists - if 'abi' in contract_data and 'bin' in contract_data: - abi = contract_data['abi'] - bin = contract_data['bin'] + if "abi" in contract_data and "bin" in contract_data: + abi = contract_data["abi"] + bin = contract_data["bin"] contracts.append(cls(web3, abi=abi, bytecode=bin)) return contracts @@ -39,7 +43,9 @@ def __init__(self, web3: Web3, abi, bytecode: Optional[bytes] = None): if bytecode is None: self.instance_contract = self.web3.eth.contract(abi=self.abi) else: - self.instance_contract = self.web3.eth.contract(abi=self.abi, bytecode=bytecode) + self.instance_contract = self.web3.eth.contract( + abi=self.abi, bytecode=bytecode + ) def encode_method(self, fn_name, args: tuple) -> HexStr: return self.instance_contract.encodeABI(fn_name, args) @@ -50,8 +56,7 @@ def contract(self): class ContractEncoder(BaseContractEncoder): - - def __init__(self, web3: Web3, abi, bytecode = None): + def __init__(self, web3: Web3, abi, bytecode=None): super(ContractEncoder, self).__init__(web3, abi, bytecode) def encode_constructor(self, *args: Any, **kwargs: Any) -> bytes: diff --git a/zksync2/manage_contracts/contract_factory.py b/zksync2/manage_contracts/contract_factory.py index fb3d037..3db2d70 100644 --- a/zksync2/manage_contracts/contract_factory.py +++ b/zksync2/manage_contracts/contract_factory.py @@ -82,7 +82,7 @@ def _deploy_create( gas_price=self.web3.zksync.gas_price, bytecode=self.byte_code, call_data=call_data, - deps=factory_deps + deps=factory_deps, ) estimate_gas = self.web3.zksync.eth_estimate_gas(create_contract.tx) diff --git a/zksync2/manage_contracts/paymaster_utils.py b/zksync2/manage_contracts/paymaster_utils.py index 336edbb..86f41eb 100644 --- a/zksync2/manage_contracts/paymaster_utils.py +++ b/zksync2/manage_contracts/paymaster_utils.py @@ -9,8 +9,6 @@ paymaster_flow_abi_cache = None - - class PaymasterFlowEncoder(BaseContractEncoder): def __init__(self, web3: Web3): super(PaymasterFlowEncoder, self).__init__( diff --git a/zksync2/manage_contracts/precompute_contract_deployer.py b/zksync2/manage_contracts/precompute_contract_deployer.py index 670a2f9..cb94263 100644 --- a/zksync2/manage_contracts/precompute_contract_deployer.py +++ b/zksync2/manage_contracts/precompute_contract_deployer.py @@ -16,6 +16,7 @@ icontract_deployer_abi_cache = None + class PrecomputeContractDeployer: DEFAULT_SALT = b"\0" * 32 CREATE_FUNC = "create" diff --git a/zksync2/manage_contracts/utils.py b/zksync2/manage_contracts/utils.py index dc30335..a1d4f78 100644 --- a/zksync2/manage_contracts/utils.py +++ b/zksync2/manage_contracts/utils.py @@ -22,9 +22,9 @@ def zksync_abi_default(): if zksync_abi_cache is None: with pkg_resources.path(contract_abi, "IZkSync.json") as p: - with p.open(mode='r') as json_file: + with p.open(mode="r") as json_file: data = json.load(json_file) - zksync_abi_cache = data['abi'] + zksync_abi_cache = data["abi"] return zksync_abi_cache @@ -76,9 +76,9 @@ def l1_bridge_abi_default(): if l1_bridge_abi_cache is None: with pkg_resources.path(contract_abi, "IL1Bridge.json") as p: - with p.open(mode='r') as json_file: + with p.open(mode="r") as json_file: data = json.load(json_file) - l1_bridge_abi_cache = data['abi'] + l1_bridge_abi_cache = data["abi"] return l1_bridge_abi_cache @@ -108,4 +108,4 @@ class ERC20Encoder(BaseContractEncoder): def __init__(self, web3: Web3, abi: Optional[dict] = None): if abi is None: abi = get_erc20_abi() - super(ERC20Encoder, self).__init__(web3, abi) \ No newline at end of file + super(ERC20Encoder, self).__init__(web3, abi) diff --git a/zksync2/module/request_types.py b/zksync2/module/request_types.py index 20b48f0..c9b187c 100644 --- a/zksync2/module/request_types.py +++ b/zksync2/module/request_types.py @@ -41,5 +41,6 @@ class EIP712Meta: total=False, ) + class TransactionType(Enum): EIP_712_TX_TYPE = 113 diff --git a/zksync2/module/response_types.py b/zksync2/module/response_types.py index d664edb..d29bbc3 100644 --- a/zksync2/module/response_types.py +++ b/zksync2/module/response_types.py @@ -21,19 +21,11 @@ "ZksContractDebugInfo", {"assemblyCode": HexStr, "pcLineMapping": Dict[int, int]} ) -ZksBlockRange = TypedDict( - "ZksBlockRange", - { - "begining": int, - "end": int - }) +ZksBlockRange = TypedDict("ZksBlockRange", {"begining": int, "end": int}) ZksBaseSystemContractsHashes = TypedDict( - "ZksBaseSystemContractsHashes", - { - "bootloader": str, - "defaultAa": str - }) + "ZksBaseSystemContractsHashes", {"bootloader": str, "defaultAa": str} +) ZksBatchDetails = TypedDict( "ZksBatchDetails", { @@ -51,8 +43,9 @@ "provenAt": datetime, "rootHash": str, "status": str, - "timestamp": int - }) + "timestamp": int, + }, +) ZksBlockDetails = TypedDict( "ZksBlockDetails", @@ -68,7 +61,9 @@ "provenAt": datetime, "rootHash": str, "status": str, - "timestamp": int}) + "timestamp": int, + }, +) ZksTransactionDetails = TypedDict( "ZksTransactionDetails", @@ -80,7 +75,9 @@ "initiatorAddress": str, "isL1Originated": bool, "receivedAt": datetime, - "status": str}) + "status": str, + }, +) ZksL1ToL2Log = TypedDict( "ZksL1ToL2Log", @@ -97,7 +94,7 @@ "key": HexStr, "value": HexStr, "logIndex": HexStr, - } + }, ) ZksTransactionReceipt = TypedDict( @@ -107,8 +104,8 @@ "to": HexStr, "blockNumber": int, "l1BatchTxIndex": HexStr, - "l2ToL1Logs": List[ZksL1ToL2Log] - } + "l2ToL1Logs": List[ZksL1ToL2Log], + }, ) ZksEstimateFee = NewType("ZksEstimateFee", Fee) diff --git a/zksync2/module/zksync_module.py b/zksync2/module/zksync_module.py index f50cce8..01418a7 100644 --- a/zksync2/module/zksync_module.py +++ b/zksync2/module/zksync_module.py @@ -20,20 +20,44 @@ apply_formatter_if, apply_formatters_to_dict, apply_list_to_array_formatter, - to_hex_if_integer, PYTHONIC_RESULT_FORMATTERS, FILTER_RESULT_FORMATTERS, - apply_module_to_formatters, is_not_null, to_ascii_if_bytes + to_hex_if_integer, + PYTHONIC_RESULT_FORMATTERS, + FILTER_RESULT_FORMATTERS, + apply_module_to_formatters, + is_not_null, + to_ascii_if_bytes, ) from web3.eth import Eth from web3.types import RPCEndpoint, _Hash32, TxReceipt, BlockIdentifier -from zksync2.core.types import Limit, From, ContractSourceDebugInfo, \ - BridgeAddresses, TokenAddress, ZksMessageProof, BatchDetails, BlockRange, BlockDetails, BaseSystemContractsHashes, \ - TransactionDetails, ADDRESS_DEFAULT, ZkBlockParams, L1ToL2Log, TransferTransaction, TransactionOptions, \ - WithdrawTransaction, ContractAccountInfo +from zksync2.core.types import ( + Limit, + From, + ContractSourceDebugInfo, + BridgeAddresses, + TokenAddress, + ZksMessageProof, + BatchDetails, + BlockRange, + BlockDetails, + BaseSystemContractsHashes, + TransactionDetails, + ADDRESS_DEFAULT, + ZkBlockParams, + L1ToL2Log, + TransferTransaction, + TransactionOptions, + WithdrawTransaction, + ContractAccountInfo, +) from zksync2.core.utils import is_eth, MAX_PRIORITY_FEE_PER_GAS from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses -from zksync2.manage_contracts.utils import ERC20Encoder, get_erc20_abi, icontract_deployer_abi_default, \ - l2_bridge_abi_default +from zksync2.manage_contracts.utils import ( + ERC20Encoder, + get_erc20_abi, + icontract_deployer_abi_default, + l2_bridge_abi_default, +) from zksync2.module.request_types import * from zksync2.module.response_types import * from zksync2.core.types import TransactionReceipt @@ -76,9 +100,7 @@ def bytes_to_list(v: bytes) -> List[int]: def meta_formatter(eip712: EIP712Meta) -> dict: - ret = { - "gasPerPubdata": integer_to_hex(eip712.gas_per_pub_data) - } + ret = {"gasPerPubdata": integer_to_hex(eip712.gas_per_pub_data)} if eip712.custom_signature is not None: ret["customSignature"] = eip712.custom_signature.hex() @@ -91,39 +113,49 @@ def meta_formatter(eip712: EIP712Meta) -> dict: paymaster_input = bytes_to_list(pp_params.paymaster_input) ret["paymasterParams"] = { "paymaster": pp_params.paymaster, - "paymasterInput": paymaster_input + "paymasterInput": paymaster_input, } return ret ZKS_TRANSACTION_PARAMS_FORMATTERS = { - 'data': to_ascii_if_bytes, - 'from': apply_formatter_if(is_address, to_checksum_address), - 'gas': to_hex_if_integer, - 'gasPrice': to_hex_if_integer, - 'maxPriorityFeePerGas': to_hex_if_integer, - 'nonce': to_hex_if_integer, - 'to': apply_formatter_if(is_not_null, to_checksum_address), - 'value': to_hex_if_integer, - 'chainId': to_hex_if_integer, - 'transactionType': to_hex_if_integer, - 'eip712Meta': meta_formatter, + "data": to_ascii_if_bytes, + "from": apply_formatter_if(is_address, to_checksum_address), + "gas": to_hex_if_integer, + "gasPrice": to_hex_if_integer, + "maxPriorityFeePerGas": to_hex_if_integer, + "nonce": to_hex_if_integer, + "to": apply_formatter_if(is_not_null, to_checksum_address), + "value": to_hex_if_integer, + "chainId": to_hex_if_integer, + "transactionType": to_hex_if_integer, + "eip712Meta": meta_formatter, } -zks_transaction_request_formatter = apply_formatters_to_dict(ZKS_TRANSACTION_PARAMS_FORMATTERS) +zks_transaction_request_formatter = apply_formatters_to_dict( + ZKS_TRANSACTION_PARAMS_FORMATTERS +) ZKSYNC_REQUEST_FORMATTERS: [RPCEndpoint, Callable[..., Any]] = { - eth_estimate_gas_rpc: apply_formatter_at_index(zks_transaction_request_formatter, 0), - zks_estimate_fee_rpc: apply_formatter_at_index(zks_transaction_request_formatter, 0), - zks_estimate_gas_l1_to_l2_rpc: apply_formatter_at_index(zks_transaction_request_formatter, 0), + eth_estimate_gas_rpc: apply_formatter_at_index( + zks_transaction_request_formatter, 0 + ), + zks_estimate_fee_rpc: apply_formatter_at_index( + zks_transaction_request_formatter, 0 + ), + zks_estimate_gas_l1_to_l2_rpc: apply_formatter_at_index( + zks_transaction_request_formatter, 0 + ), } def to_token(t: dict) -> Token: - return Token(l1_address=to_checksum_address(t["l1Address"]), - l2_address=to_checksum_address(t["l2Address"]), - symbol=t["symbol"], - decimals=t["decimals"]) + return Token( + l1_address=to_checksum_address(t["l1Address"]), + l2_address=to_checksum_address(t["l2Address"]), + symbol=t["symbol"], + decimals=t["decimals"], + ) def to_bridge_address(t: dict) -> BridgeAddresses: @@ -131,82 +163,104 @@ def to_bridge_address(t: dict) -> BridgeAddresses: erc20_l1_default_bridge=HexStr(to_checksum_address(t["l1Erc20DefaultBridge"])), erc20_l2_default_bridge=HexStr(to_checksum_address(t["l2Erc20DefaultBridge"])), weth_bridge_l1=HexStr(to_checksum_address(t["l1WethBridge"])), - weth_bridge_l2=HexStr(to_checksum_address(t["l2WethBridge"])) + weth_bridge_l2=HexStr(to_checksum_address(t["l2WethBridge"])), ) + def to_batch_details(t: dict) -> BatchDetails: - datetime_format = '%Y-%m-%dT%H:%M:%S.%fZ' - base_sys_contract_hashes = BaseSystemContractsHashes(bootloader=t["baseSystemContractsHashes"]["bootloader"], - default_aa=t["baseSystemContractsHashes"]["default_aa"]) - return BatchDetails(base_system_contracts_hashes=base_sys_contract_hashes, - commit_tx_hash=t["commitTxHash"], - committed_at=datetime.strptime(t["committedAt"], datetime_format), - execute_tx_hash=t["executeTxHash"], - executed_at=datetime.strptime(t["executedAt"], datetime_format), - l1_gas_price=t["l1GasPrice"], - l1_tx_count=t["l1TxCount"], - l2_fair_gas_price=t["l2FairGasPrice"], - l2_tx_count=t["l2TxCount"], - number=t["number"], - prove_tx_hash=t["proveTxHash"], - proven_at=datetime.strptime(t["provenAt"], datetime_format), - root_hash=t["rootHash"], - status=t["status"], - timestamp=t["timestamp"]) + datetime_format = "%Y-%m-%dT%H:%M:%S.%fZ" + base_sys_contract_hashes = BaseSystemContractsHashes( + bootloader=t["baseSystemContractsHashes"]["bootloader"], + default_aa=t["baseSystemContractsHashes"]["default_aa"], + ) + return BatchDetails( + base_system_contracts_hashes=base_sys_contract_hashes, + commit_tx_hash=t["commitTxHash"], + committed_at=datetime.strptime(t["committedAt"], datetime_format), + execute_tx_hash=t["executeTxHash"], + executed_at=datetime.strptime(t["executedAt"], datetime_format), + l1_gas_price=t["l1GasPrice"], + l1_tx_count=t["l1TxCount"], + l2_fair_gas_price=t["l2FairGasPrice"], + l2_tx_count=t["l2TxCount"], + number=t["number"], + prove_tx_hash=t["proveTxHash"], + proven_at=datetime.strptime(t["provenAt"], datetime_format), + root_hash=t["rootHash"], + status=t["status"], + timestamp=t["timestamp"], + ) + def to_block_details(t: dict) -> BlockDetails: - datetime_format = '%Y-%m-%dT%H:%M:%S.%fZ' - return BlockDetails(commit_tx_hash = t["commitTxHash"], - committed_at = datetime.strptime(t["committedAt"], datetime_format), - execute_tx_hash = t["executeTxHash"], - executed_at = datetime.strptime(t["executedAt"], datetime_format), - l1_tx_count = t["l1TxCount"], - l2_tx_count = t["l2TxCount"], - number = t["number"], - prove_tx_hash = t["proveTxHash"], - proven_at = datetime.strptime(t["provenAt"], datetime_format), - root_hash = t["rootHash"], - status = t["status"], - timestamp = t["timestamp"]) + datetime_format = "%Y-%m-%dT%H:%M:%S.%fZ" + return BlockDetails( + commit_tx_hash=t["commitTxHash"], + committed_at=datetime.strptime(t["committedAt"], datetime_format), + execute_tx_hash=t["executeTxHash"], + executed_at=datetime.strptime(t["executedAt"], datetime_format), + l1_tx_count=t["l1TxCount"], + l2_tx_count=t["l2TxCount"], + number=t["number"], + prove_tx_hash=t["proveTxHash"], + proven_at=datetime.strptime(t["provenAt"], datetime_format), + root_hash=t["rootHash"], + status=t["status"], + timestamp=t["timestamp"], + ) + + def to_transaction_details(t: dict) -> TransactionDetails: - return TransactionDetails(ethCommitTxHash = t["ethCommitTxHash"], - ethExecuteTxHash = t["ethExecuteTxHash"], - ethProveTxHash = t["ethProveTxHash"], - fee = t["fee"], - initiatorAddress = t["initiatorAddress"], - isL1Originated = t["isL1Originated"], - receivedAt = t["receivedAt"], - status = t["status"]) + return TransactionDetails( + ethCommitTxHash=t["ethCommitTxHash"], + ethExecuteTxHash=t["ethExecuteTxHash"], + ethProveTxHash=t["ethProveTxHash"], + fee=t["fee"], + initiatorAddress=t["initiatorAddress"], + isL1Originated=t["isL1Originated"], + receivedAt=t["receivedAt"], + status=t["status"], + ) + def to_transaction_receipt(t: dict) -> TransactionReceipt: logs = [] for log in t["l2ToL1Logs"]: logs.append(to_l2_to_l1_logs(log)) - return TransactionReceipt(from_=t["from"], - to=t["to"], - block_number=t["blockNumber"], - l1_batch_tx_index=t["l1BatchTxIndex"], - l2_to_l1_logs=logs) + return TransactionReceipt( + from_=t["from"], + to=t["to"], + block_number=t["blockNumber"], + l1_batch_tx_index=t["l1BatchTxIndex"], + l2_to_l1_logs=logs, + ) + def to_l2_to_l1_logs(t: dict) -> L1ToL2Log: - return L1ToL2Log(block_hash=t["blockHash"], - block_number=t["blockNumber"], - l1_batch_number=t["l1BatchNumber"], - transaction_index=t["transactionIndex"], - transaction_hash=t["transactionHash"], - transaction_log_index=t["transactionLogIndex"], - shard_id=t["shardId"], - is_service=t["isService"], - sender=t["sender"], - key=t["key"], - value=t["value"], - log_index=t["logIndex"]) + return L1ToL2Log( + block_hash=t["blockHash"], + block_number=t["blockNumber"], + l1_batch_number=t["l1BatchNumber"], + transaction_index=t["transactionIndex"], + transaction_hash=t["transactionHash"], + transaction_log_index=t["transactionLogIndex"], + shard_id=t["shardId"], + is_service=t["isService"], + sender=t["sender"], + key=t["key"], + value=t["value"], + log_index=t["logIndex"], + ) + def to_transaction_by_hash(t: dict) -> Transaction712: return Transaction712() + + def to_block_range(t: dict) -> BlockRange: - return BlockRange(beginning=t["beginning"], - end=t["end"]) + return BlockRange(beginning=t["beginning"], end=t["end"]) + + def to_zks_account_balances(t: dict) -> ZksAccountBalances: result = dict() for k, v in t.items(): @@ -215,20 +269,20 @@ def to_zks_account_balances(t: dict) -> ZksAccountBalances: def to_fee(v: dict) -> Fee: - gas_limit = int(remove_0x_prefix(v['gas_limit']), 16) - max_fee_per_gas = int(remove_0x_prefix(v['max_fee_per_gas']), 16) - max_priority_fee_per_gas = int(remove_0x_prefix(v['max_priority_fee_per_gas']), 16) - gas_per_pubdata_limit = int(remove_0x_prefix(v['gas_per_pubdata_limit']), 16) - return Fee(gas_limit=gas_limit, - max_fee_per_gas=max_fee_per_gas, - max_priority_fee_per_gas=max_priority_fee_per_gas, - gas_per_pubdata_limit=gas_per_pubdata_limit) + gas_limit = int(remove_0x_prefix(v["gas_limit"]), 16) + max_fee_per_gas = int(remove_0x_prefix(v["max_fee_per_gas"]), 16) + max_priority_fee_per_gas = int(remove_0x_prefix(v["max_priority_fee_per_gas"]), 16) + gas_per_pubdata_limit = int(remove_0x_prefix(v["gas_per_pubdata_limit"]), 16) + return Fee( + gas_limit=gas_limit, + max_fee_per_gas=max_fee_per_gas, + max_priority_fee_per_gas=max_priority_fee_per_gas, + gas_per_pubdata_limit=gas_per_pubdata_limit, + ) def to_msg_proof(v: dict) -> ZksMessageProof: - return ZksMessageProof(id=v['id'], - proof=v['proof'], - root=v['root']) + return ZksMessageProof(id=v["id"], proof=v["proof"], root=v["root"]) ZKSYNC_RESULT_FORMATTERS: Dict[RPCEndpoint, Callable[..., Any]] = { @@ -242,12 +296,12 @@ def to_msg_proof(v: dict) -> ZksMessageProof: zks_get_l1_batch_block_range_rpc: to_block_range, zks_get_transaction_details_rpc: to_transaction_details, eth_get_transaction_receipt_rpc: to_transaction_receipt, - eth_get_transaction_by_hash_rpc: to_transaction_by_hash + eth_get_transaction_by_hash_rpc: to_transaction_by_hash, } def zksync_get_request_formatters( - method_name: Union[RPCEndpoint, Callable[..., RPCEndpoint]] + method_name: Union[RPCEndpoint, Callable[..., RPCEndpoint]] ) -> Dict[str, Callable[..., Any]]: request_formatter_maps = ( ZKSYNC_REQUEST_FORMATTERS, @@ -260,8 +314,8 @@ def zksync_get_request_formatters( def zksync_get_result_formatters( - method_name: Union[RPCEndpoint, Callable[..., RPCEndpoint]], - module: "Module", + method_name: Union[RPCEndpoint, Callable[..., RPCEndpoint]], + module: "Module", ) -> Dict[str, Callable[..., Any]]: # formatters = combine_formatters((PYTHONIC_RESULT_FORMATTERS,), method_name) # formatters_requiring_module = combine_formatters( @@ -273,49 +327,41 @@ def zksync_get_result_formatters( # return compose(*partial_formatters, *formatters) formatters = combine_formatters( - (ZKSYNC_RESULT_FORMATTERS, - PYTHONIC_RESULT_FORMATTERS), - method_name + (ZKSYNC_RESULT_FORMATTERS, PYTHONIC_RESULT_FORMATTERS), method_name ) formatters_requiring_module = combine_formatters( - (FILTER_RESULT_FORMATTERS,), - method_name + (FILTER_RESULT_FORMATTERS,), method_name ) partial_formatters = apply_module_to_formatters( - formatters_requiring_module, - module, - method_name + formatters_requiring_module, module, method_name ) return compose(*partial_formatters, *formatters) class ZkSync(Eth, ABC): - _zks_l1_batch_number: Method[Callable[[], ZksL1BatchNumber]] = Method( - zks_l1_batch_number_rpc, - mungers=None + zks_l1_batch_number_rpc, mungers=None ) _zks_get_l1_batch_block_range: Method[Callable[[int], ZksBlockRange]] = Method( - zks_get_l1_batch_block_range_rpc, - mungers=[default_root_munger] + zks_get_l1_batch_block_range_rpc, mungers=[default_root_munger] ) _zks_get_l1_batch_details: Method[Callable[[int], ZksBatchDetails]] = Method( zks_get_l1_batch_details_rpc, mungers=[default_root_munger], - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _zks_get_block_details: Method[Callable[[int], ZksBlockDetails]] = Method( zks_get_block_details_rpc, mungers=[default_root_munger], request_formatters=zksync_get_request_formatters, - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _zks_get_transaction_details: Method[Callable[[str], ZksEstimateFee]] = Method( zks_get_transaction_details_rpc, mungers=[default_root_munger], request_formatters=zksync_get_request_formatters, - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _zks_estimate_gas_l1_to_l2: Method[Callable[[Transaction], int]] = Method( zks_estimate_gas_l1_to_l2_rpc, @@ -326,85 +372,84 @@ class ZkSync(Eth, ABC): zks_estimate_fee_rpc, mungers=[default_root_munger], request_formatters=zksync_get_request_formatters, - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _zks_main_contract: Method[Callable[[], ZksMainContract]] = Method( - zks_main_contract_rpc, - mungers=None + zks_main_contract_rpc, mungers=None ) _zks_get_token_price: Method[Callable[[TokenAddress], ZksTokenPrice]] = Method( - zks_get_token_price_rpc, - mungers=[default_root_munger] + zks_get_token_price_rpc, mungers=[default_root_munger] ) _zks_l1_chain_id: Method[Callable[[], ZksL1ChainId]] = Method( - zks_l1_chain_id_rpc, - mungers=None + zks_l1_chain_id_rpc, mungers=None ) - _zks_get_all_account_balances: Method[Callable[[Address], ZksAccountBalances]] = Method( + _zks_get_all_account_balances: Method[ + Callable[[Address], ZksAccountBalances] + ] = Method( zks_get_all_account_balances_rpc, mungers=[default_root_munger], - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _zks_get_bridge_contracts: Method[Callable[[], ZksBridgeAddresses]] = Method( zks_get_bridge_contracts_rpc, mungers=[default_root_munger], - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) - _zks_get_l2_to_l1_msg_proof: Method[Callable[[int, Address, str, Optional[int]], ZksMessageProof]] = Method( + _zks_get_l2_to_l1_msg_proof: Method[ + Callable[[int, Address, str, Optional[int]], ZksMessageProof] + ] = Method( zks_get_l2_to_l1_msg_proof_prc, mungers=[default_root_munger], request_formatters=zksync_get_request_formatters, - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) - _zks_get_l2_to_l1_log_proof: Method[Callable[[Address, Optional[int]], ZksMessageProof]] = Method( + _zks_get_l2_to_l1_log_proof: Method[ + Callable[[Address, Optional[int]], ZksMessageProof] + ] = Method( zks_get_l2_to_l1_log_proof_prc, mungers=[default_root_munger], request_formatters=zksync_get_request_formatters, - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _eth_estimate_gas: Method[Callable[[Transaction], int]] = Method( eth_estimate_gas_rpc, mungers=[default_root_munger], - request_formatters=zksync_get_request_formatters + request_formatters=zksync_get_request_formatters, ) - _eth_get_transaction_receipt: Method[Callable[[HexStr], ZksTransactionReceipt]] = Method( + _eth_get_transaction_receipt: Method[ + Callable[[HexStr], ZksTransactionReceipt] + ] = Method( eth_get_transaction_receipt_rpc, mungers=[default_root_munger], - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) _eth_get_transaction_by_hash: Method[Callable[[HexStr], ZksTransactions]] = Method( eth_get_transaction_by_hash_rpc, mungers=[default_root_munger], - result_formatters=zksync_get_result_formatters + result_formatters=zksync_get_result_formatters, ) # TODO: implement it - _zks_set_contract_debug_info: Method[Callable[[Address, - ContractSourceDebugInfo], - ZksSetContractDebugInfoResult]] = Method( - zks_set_contract_debug_info_rpc, - mungers=[default_root_munger] - ) - _zks_get_contract_debug_info: Method[Callable[[Address], ContractSourceDebugInfo]] = Method( - zks_get_contract_debug_info_rpc, - mungers=[default_root_munger] - ) + _zks_set_contract_debug_info: Method[ + Callable[[Address, ContractSourceDebugInfo], ZksSetContractDebugInfoResult] + ] = Method(zks_set_contract_debug_info_rpc, mungers=[default_root_munger]) + _zks_get_contract_debug_info: Method[ + Callable[[Address], ContractSourceDebugInfo] + ] = Method(zks_get_contract_debug_info_rpc, mungers=[default_root_munger]) - _zks_get_transaction_trace: Method[Callable[[Address], ZksTransactionTrace]] = Method( - zks_get_transaction_trace_rpc, - mungers=[default_root_munger] - ) + _zks_get_transaction_trace: Method[ + Callable[[Address], ZksTransactionTrace] + ] = Method(zks_get_transaction_trace_rpc, mungers=[default_root_munger]) _zks_get_testnet_paymaster_address: Method[Callable[[], HexStr]] = Method( - zks_get_testnet_paymaster_address, - mungers=[default_root_munger] + zks_get_testnet_paymaster_address, mungers=[default_root_munger] ) def __init__(self, web3: "Web3"): @@ -430,14 +475,19 @@ def zks_get_transaction_details(self, txHash: str) -> TransactionDetails: def zks_estimate_gas_l1_to_l2(self, transaction: Transaction) -> int: return int(self._zks_estimate_gas_l1_to_l2(transaction), 16) - def zks_estimate_gas_transfer(self, transaction: Transaction, token_address: HexStr = ADDRESS_DEFAULT) -> int: - + def zks_estimate_gas_transfer( + self, transaction: Transaction, token_address: HexStr = ADDRESS_DEFAULT + ) -> int: if token_address is not None and not is_eth(token_address): transfer_params = (transaction["to"], transaction["value"]) transaction["value"] = 0 - contract = self.contract(Web3.to_checksum_address(token_address), abi=get_erc20_abi()) + contract = self.contract( + Web3.to_checksum_address(token_address), abi=get_erc20_abi() + ) transaction["data"] = contract.encodeABI("transfer", args=transfer_params) - transaction["nonce"] = self.get_transaction_count(transaction["from_"], ZkBlockParams.COMMITTED.value) + transaction["nonce"] = self.get_transaction_count( + transaction["from_"], ZkBlockParams.COMMITTED.value + ) return self.eth_estimate_gas(transaction) @@ -461,12 +511,19 @@ def zks_get_token_price(self, token_address: TokenAddress) -> Decimal: def zks_l1_chain_id(self) -> int: return self._zks_l1_chain_id() - def zks_get_balance(self, address: HexStr, block_tag = ZkBlockParams.COMMITTED.value, token_address: HexStr = None) -> int: + def zks_get_balance( + self, + address: HexStr, + block_tag=ZkBlockParams.COMMITTED.value, + token_address: HexStr = None, + ) -> int: if token_address is None or is_eth(token_address): return self.get_balance(to_checksum_address(address), block_tag) try: - token = self.contract(Web3.to_checksum_address(token_address), abi=get_erc20_abi()) + token = self.contract( + Web3.to_checksum_address(token_address), abi=get_erc20_abi() + ) return token.functions.balanceOf(address).call() except: return 0 @@ -475,8 +532,10 @@ def l1_token_address(self, token: HexStr) -> HexStr: if is_eth(token): return ADDRESS_DEFAULT bridge_address = self.zks_get_bridge_contracts() - l2_weth_bridge = self.contract(Web3.to_checksum_address(bridge_address.weth_bridge_l2), - abi=l2_bridge_abi_default()) + l2_weth_bridge = self.contract( + Web3.to_checksum_address(bridge_address.weth_bridge_l2), + abi=l2_bridge_abi_default(), + ) try: l1_weth_token = l2_weth_bridge.functions.l1TokenAddress(token).call() if not is_eth(l1_weth_token): @@ -484,8 +543,10 @@ def l1_token_address(self, token: HexStr) -> HexStr: except: pass - erc20_bridge = self.contract(Web3.to_checksum_address(bridge_address.erc20_l2_default_bridge), - abi=l2_bridge_abi_default()) + erc20_bridge = self.contract( + Web3.to_checksum_address(bridge_address.erc20_l2_default_bridge), + abi=l2_bridge_abi_default(), + ) return erc20_bridge.functions.l1TokenAddress(token).call() @@ -493,8 +554,10 @@ def l2_token_address(self, token: HexStr) -> HexStr: if is_eth(token): return ADDRESS_DEFAULT bridge_address = self.zks_get_bridge_contracts() - l2_weth_bridge = self.contract(Web3.to_checksum_address(bridge_address.weth_bridge_l2), - abi=l2_bridge_abi_default()) + l2_weth_bridge = self.contract( + Web3.to_checksum_address(bridge_address.weth_bridge_l2), + abi=l2_bridge_abi_default(), + ) try: l1_weth_token = l2_weth_bridge.functions.l2TokenAddress(token).call() if not is_eth(l1_weth_token): @@ -502,8 +565,10 @@ def l2_token_address(self, token: HexStr) -> HexStr: except: pass - erc20_bridge = self.contract(Web3.to_checksum_address(bridge_address.erc20_l2_default_bridge), - abi=l2_bridge_abi_default()) + erc20_bridge = self.contract( + Web3.to_checksum_address(bridge_address.erc20_l2_default_bridge), + abi=l2_bridge_abi_default(), + ) return erc20_bridge.functions.l2TokenAddress(token).call() @@ -515,11 +580,9 @@ def zks_get_bridge_contracts(self) -> BridgeAddresses: self.bridge_addresses = self._zks_get_bridge_contracts() return self.bridge_addresses - def zks_get_l2_to_l1_msg_proof(self, - block: int, - sender: HexStr, - message: str, - l2log_pos: Optional[int]) -> ZksMessageProof: + def zks_get_l2_to_l1_msg_proof( + self, block: int, sender: HexStr, message: str, l2log_pos: Optional[int] + ) -> ZksMessageProof: return self._zks_get_l2_to_l1_msg_proof(block, sender, message, l2log_pos) def zks_get_log_proof(self, tx_hash: HexStr, index: int = None) -> ZksMessageProof: @@ -550,10 +613,9 @@ def get_l2_transaction_from_priority_op(self, tx_receipt, main_contract: Contrac self.wait_for_transaction_receipt(l2_hash) return self.get_transaction(l2_hash) - def wait_for_transaction_receipt(self, - transaction_hash: _Hash32, - timeout: float = 120, - poll_latency: float = 0.1) -> TxReceipt: + def wait_for_transaction_receipt( + self, transaction_hash: _Hash32, timeout: float = 120, poll_latency: float = 0.1 + ) -> TxReceipt: try: with Timeout(timeout) as _timeout: while True: @@ -561,8 +623,7 @@ def wait_for_transaction_receipt(self, tx_receipt = self.get_transaction_receipt(transaction_hash) except TransactionNotFound: tx_receipt = None - if tx_receipt is not None and \ - tx_receipt["blockHash"] is not None: + if tx_receipt is not None and tx_receipt["blockHash"] is not None: break _timeout.sleep(poll_latency) return tx_receipt @@ -572,10 +633,9 @@ def wait_for_transaction_receipt(self, f"Transaction {HexBytes(transaction_hash) !r} is not in the chain after {timeout} seconds" ) - def wait_finalized(self, - transaction_hash: _Hash32, - timeout: float = 120, - poll_latency: float = 0.1) -> TxReceipt: + def wait_finalized( + self, transaction_hash: _Hash32, timeout: float = 120, poll_latency: float = 0.1 + ) -> TxReceipt: try: with Timeout(timeout) as _timeout: while True: @@ -584,9 +644,11 @@ def wait_finalized(self, tx_receipt = self.get_transaction_receipt(transaction_hash) except TransactionNotFound: tx_receipt = None - if tx_receipt is not None and \ - tx_receipt["blockHash"] is not None and \ - block["number"] >= tx_receipt["blockNumber"]: + if ( + tx_receipt is not None + and tx_receipt["blockHash"] is not None + and block["number"] >= tx_receipt["blockNumber"] + ): break _timeout.sleep(poll_latency) return tx_receipt @@ -596,13 +658,19 @@ def wait_finalized(self, f"Transaction {HexBytes(transaction_hash) !r} is not in the chain after {timeout} seconds" ) - def get_withdraw_transaction(self, tx: WithdrawTransaction, from_: HexStr,) -> TxWithdraw: + def get_withdraw_transaction( + self, + tx: WithdrawTransaction, + from_: HexStr, + ) -> TxWithdraw: if tx.options is None: tx.options = TransactionOptions() if tx.options.chain_id is None: tx.options.chain_id = self.chain_id if tx.options.nonce is None: - tx.options.nonce = self.get_transaction_count(Web3.to_checksum_address(from_), ZkBlockParams.LATEST.value) + tx.options.nonce = self.get_transaction_count( + Web3.to_checksum_address(from_), ZkBlockParams.LATEST.value + ) if tx.options.gas_price is None: tx.options.gas_price = self.gas_price if tx.options.gas_limit is None: @@ -616,18 +684,22 @@ def get_withdraw_transaction(self, tx: WithdrawTransaction, from_: HexStr,) -> T gas_limit=tx.options.gas_limit, gas_price=tx.options.gas_price, token=tx.token, - bridge_address=tx.bridge_address + bridge_address=tx.bridge_address, ) return transaction - def get_transfer_transaction(self, tx: TransferTransaction, from_: HexStr) -> TxFunctionCall: + def get_transfer_transaction( + self, tx: TransferTransaction, from_: HexStr + ) -> TxFunctionCall: if tx.options is None: tx.options = TransactionOptions() if tx.options.chain_id is None: tx.options.chain_id = self.chain_id if tx.options.nonce is None: - tx.options.nonce = self.get_transaction_count(Web3.to_checksum_address(from_), ZkBlockParams.LATEST.value) + tx.options.nonce = self.get_transaction_count( + Web3.to_checksum_address(from_), ZkBlockParams.LATEST.value + ) if tx.options.gas_price is None: tx.options.gas_price = self.gas_price if tx.options.max_priority_fee_per_gas is None: @@ -638,7 +710,9 @@ def get_transfer_transaction(self, tx: TransferTransaction, from_: HexStr) -> Tx call_data = "0x" if tx.token_address is not None and not is_eth(tx.token_address): transfer_params = (tx.to, tx.amount) - contract = self.contract(Web3.to_checksum_address(tx.token_address), abi=get_erc20_abi()) + contract = self.contract( + Web3.to_checksum_address(tx.token_address), abi=get_erc20_abi() + ) call_data = contract.encodeABI("transfer", transfer_params) transaction = TxFunctionCall( chain_id=tx.options.chain_id, @@ -656,8 +730,15 @@ def get_transfer_transaction(self, tx: TransferTransaction, from_: HexStr) -> Tx return transaction def get_contract_account_info(self, address: HexStr) -> ContractAccountInfo: - deployer = self.contract(address=Web3.to_checksum_address(ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value), - abi=icontract_deployer_abi_default()) - data = deployer.functions.getAccountInfo(Web3.to_checksum_address(address)).call() - return ContractAccountInfo(account_abstraction_version=data[0], - account_nonce_ordering=data[1]) + deployer = self.contract( + address=Web3.to_checksum_address( + ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value + ), + abi=icontract_deployer_abi_default(), + ) + data = deployer.functions.getAccountInfo( + Web3.to_checksum_address(address) + ).call() + return ContractAccountInfo( + account_abstraction_version=data[0], account_nonce_ordering=data[1] + ) diff --git a/zksync2/transaction/transaction_builders.py b/zksync2/transaction/transaction_builders.py index 5a65914..12a6316 100644 --- a/zksync2/transaction/transaction_builders.py +++ b/zksync2/transaction/transaction_builders.py @@ -9,15 +9,21 @@ from zksync2.core.types import Token, BridgeAddresses, TransactionOptions from zksync2.core.utils import is_eth, MAX_PRIORITY_FEE_PER_GAS from zksync2.manage_contracts.deploy_addresses import ZkSyncAddresses -from zksync2.manage_contracts.precompute_contract_deployer import PrecomputeContractDeployer +from zksync2.manage_contracts.precompute_contract_deployer import ( + PrecomputeContractDeployer, +) from zksync2.manage_contracts.utils import l2_bridge_abi_default, eth_token_abi_default -from zksync2.module.request_types import EIP712Meta, TransactionType, Transaction as ZkTx +from zksync2.module.request_types import ( + EIP712Meta, + TransactionType, + Transaction as ZkTx, +) from zksync2.transaction.transaction712 import Transaction712 -L2_ETH_TOKEN_ADDRESS = HexStr('0x000000000000000000000000000000000000800a') +L2_ETH_TOKEN_ADDRESS = HexStr("0x000000000000000000000000000000000000800a") -class TxBase(ABC): +class TxBase(ABC): def __init__(self, trans: ZkTx): self.tx_: ZkTx = trans @@ -26,37 +32,42 @@ def tx(self) -> ZkTx: return self.tx_ def tx712(self, estimated_gas: int) -> Transaction712: - return Transaction712(chain_id=self.tx["chain_id"], - nonce=Nonce(self.tx["nonce"]), - gas_limit=estimated_gas, - to=self.tx["to"], - value=self.tx["value"], - data=self.tx["data"], - maxPriorityFeePerGas=self.tx["maxPriorityFeePerGas"], - maxFeePerGas=self.tx["gasPrice"], - from_=self.tx["from"], - meta=self.tx["eip712Meta"]) + return Transaction712( + chain_id=self.tx["chain_id"], + nonce=Nonce(self.tx["nonce"]), + gas_limit=estimated_gas, + to=self.tx["to"], + value=self.tx["value"], + data=self.tx["data"], + maxPriorityFeePerGas=self.tx["maxPriorityFeePerGas"], + maxFeePerGas=self.tx["gasPrice"], + from_=self.tx["from"], + meta=self.tx["eip712Meta"], + ) class TxFunctionCall(TxBase, ABC): - - def __init__(self, - from_: HexStr, - to: HexStr, - value: int = 0, - chain_id: int = None, - nonce: int = None, - data: HexStr = HexStr("0x"), - gas_limit: int = 0, - gas_price: int = 0, - max_priority_fee_per_gas: int = MAX_PRIORITY_FEE_PER_GAS, - paymaster_params=None, - custom_signature=None, - gas_per_pub_data: int = EIP712Meta.GAS_PER_PUB_DATA_DEFAULT): - eip712_meta = EIP712Meta(gas_per_pub_data=gas_per_pub_data, - custom_signature=custom_signature, - factory_deps=None, - paymaster_params=paymaster_params) + def __init__( + self, + from_: HexStr, + to: HexStr, + value: int = 0, + chain_id: int = None, + nonce: int = None, + data: HexStr = HexStr("0x"), + gas_limit: int = 0, + gas_price: int = 0, + max_priority_fee_per_gas: int = MAX_PRIORITY_FEE_PER_GAS, + paymaster_params=None, + custom_signature=None, + gas_per_pub_data: int = EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, + ): + eip712_meta = EIP712Meta( + gas_per_pub_data=gas_per_pub_data, + custom_signature=custom_signature, + factory_deps=None, + paymaster_params=paymaster_params, + ) super(TxFunctionCall, self).__init__( trans={ @@ -70,195 +81,227 @@ def __init__(self, "value": value, "data": data, "transactionType": TransactionType.EIP_712_TX_TYPE.value, - "eip712Meta": eip712_meta - }) -class TxCreateContract(TxBase, ABC): + "eip712Meta": eip712_meta, + } + ) - def __init__(self, - web3: Web3, - chain_id: int, - nonce: int, - from_: HexStr, - bytecode: bytes, - gas_price: int, - gas_limit: int = 0, - deps: List[bytes] = None, - call_data: Optional[bytes] = None, - value: int = 0, - max_priority_fee_per_gas=100_000_000 - ): + +class TxCreateContract(TxBase, ABC): + def __init__( + self, + web3: Web3, + chain_id: int, + nonce: int, + from_: HexStr, + bytecode: bytes, + gas_price: int, + gas_limit: int = 0, + deps: List[bytes] = None, + call_data: Optional[bytes] = None, + value: int = 0, + max_priority_fee_per_gas=100_000_000, + ): contract_deployer = PrecomputeContractDeployer(web3) - generated_call_data = contract_deployer.encode_create(bytecode=bytecode, call_data=call_data) + generated_call_data = contract_deployer.encode_create( + bytecode=bytecode, call_data=call_data + ) factory_deps = [] if deps is not None: for dep in deps: factory_deps.append(dep) factory_deps.append(bytecode) - eip712_meta = EIP712Meta(gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, - custom_signature=None, - factory_deps=factory_deps, - paymaster_params=None) + eip712_meta = EIP712Meta( + gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, + custom_signature=None, + factory_deps=factory_deps, + paymaster_params=None, + ) - super(TxCreateContract, self).__init__(trans={ - "chain_id": chain_id, - "nonce": nonce, - "from": from_, - "to": Web3.to_checksum_address(ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value), - "gas": gas_limit, - "gasPrice": gas_price, - "maxPriorityFeePerGas": max_priority_fee_per_gas, - "value": value, - "data": HexStr(generated_call_data), - "transactionType": TransactionType.EIP_712_TX_TYPE.value, - "eip712Meta": eip712_meta - }) + super(TxCreateContract, self).__init__( + trans={ + "chain_id": chain_id, + "nonce": nonce, + "from": from_, + "to": Web3.to_checksum_address( + ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value + ), + "gas": gas_limit, + "gasPrice": gas_price, + "maxPriorityFeePerGas": max_priority_fee_per_gas, + "value": value, + "data": HexStr(generated_call_data), + "transactionType": TransactionType.EIP_712_TX_TYPE.value, + "eip712Meta": eip712_meta, + } + ) class TxCreate2Contract(TxBase, ABC): - - def __init__(self, - web3: Web3, - chain_id: int, - nonce: int, - from_: HexStr, - gas_limit: int, - gas_price: int, - bytecode: bytes, - deps: List[bytes] = None, - call_data: Optional[bytes] = None, - value: int = 0, - max_priority_fee_per_gas=100_000_000, - salt: Optional[bytes] = None - ): + def __init__( + self, + web3: Web3, + chain_id: int, + nonce: int, + from_: HexStr, + gas_limit: int, + gas_price: int, + bytecode: bytes, + deps: List[bytes] = None, + call_data: Optional[bytes] = None, + value: int = 0, + max_priority_fee_per_gas=100_000_000, + salt: Optional[bytes] = None, + ): contract_deployer = PrecomputeContractDeployer(web3) - generated_call_data = contract_deployer.encode_create2(bytecode=bytecode, - call_data=call_data, - salt=salt) + generated_call_data = contract_deployer.encode_create2( + bytecode=bytecode, call_data=call_data, salt=salt + ) factory_deps = [] if deps is not None: for dep in deps: factory_deps.append(dep) factory_deps.append(bytecode) - eip712_meta = EIP712Meta(gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, - custom_signature=None, - factory_deps=factory_deps, - paymaster_params=None) - super(TxCreate2Contract, self).__init__(trans={ - "chain_id": chain_id, - "nonce": nonce, - "from": from_, - "to": Web3.to_checksum_address(ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value), - "gas": gas_limit, - "gasPrice": gas_price, - "maxPriorityFeePerGas": max_priority_fee_per_gas, - "value": value, - "data": HexStr(generated_call_data), - "transactionType": TransactionType.EIP_712_TX_TYPE.value, - "eip712Meta": eip712_meta - }) + eip712_meta = EIP712Meta( + gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, + custom_signature=None, + factory_deps=factory_deps, + paymaster_params=None, + ) + super(TxCreate2Contract, self).__init__( + trans={ + "chain_id": chain_id, + "nonce": nonce, + "from": from_, + "to": Web3.to_checksum_address( + ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value + ), + "gas": gas_limit, + "gasPrice": gas_price, + "maxPriorityFeePerGas": max_priority_fee_per_gas, + "value": value, + "data": HexStr(generated_call_data), + "transactionType": TransactionType.EIP_712_TX_TYPE.value, + "eip712Meta": eip712_meta, + } + ) class TxCreateAccount(TxBase, ABC): - - def __init__(self, - web3: Web3, - chain_id: int, - nonce: int, - from_: HexStr, - bytecode: bytes, - gas_price: int, - gas_limit: int = 0, - deps: List[bytes] = None, - call_data: Optional[bytes] = None, - value: int = 0, - max_priority_fee_per_gas=100_000_000 - ): + def __init__( + self, + web3: Web3, + chain_id: int, + nonce: int, + from_: HexStr, + bytecode: bytes, + gas_price: int, + gas_limit: int = 0, + deps: List[bytes] = None, + call_data: Optional[bytes] = None, + value: int = 0, + max_priority_fee_per_gas=100_000_000, + ): contract_deployer = PrecomputeContractDeployer(web3) - generated_call_data = contract_deployer.encode_create_account(bytecode=bytecode, call_data=call_data) + generated_call_data = contract_deployer.encode_create_account( + bytecode=bytecode, call_data=call_data + ) factory_deps = [] if deps is not None: for dep in deps: factory_deps.append(dep) factory_deps.append(bytecode) - eip712_meta = EIP712Meta(gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, - custom_signature=None, - factory_deps=factory_deps, - paymaster_params=None) + eip712_meta = EIP712Meta( + gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, + custom_signature=None, + factory_deps=factory_deps, + paymaster_params=None, + ) - super(TxCreateAccount, self).__init__(trans={ - "chain_id": chain_id, - "nonce": nonce, - "from": from_, - "to": Web3.to_checksum_address(ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value), - "gas": gas_limit, - "gasPrice": gas_price, - "maxPriorityFeePerGas": max_priority_fee_per_gas, - "value": value, - "data": HexStr(generated_call_data), - "transactionType": TransactionType.EIP_712_TX_TYPE.value, - "eip712Meta": eip712_meta - }) + super(TxCreateAccount, self).__init__( + trans={ + "chain_id": chain_id, + "nonce": nonce, + "from": from_, + "to": Web3.to_checksum_address( + ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value + ), + "gas": gas_limit, + "gasPrice": gas_price, + "maxPriorityFeePerGas": max_priority_fee_per_gas, + "value": value, + "data": HexStr(generated_call_data), + "transactionType": TransactionType.EIP_712_TX_TYPE.value, + "eip712Meta": eip712_meta, + } + ) class TxCreate2Account(TxBase, ABC): - - def __init__(self, - web3: Web3, - chain_id: int, - nonce: int, - from_: HexStr, - gas_limit: int, - gas_price: int, - bytecode: bytes, - deps: List[bytes] = None, - call_data: Optional[bytes] = None, - value: int = 0, - max_priority_fee_per_gas=100_000_000, - salt: Optional[bytes] = None - ): + def __init__( + self, + web3: Web3, + chain_id: int, + nonce: int, + from_: HexStr, + gas_limit: int, + gas_price: int, + bytecode: bytes, + deps: List[bytes] = None, + call_data: Optional[bytes] = None, + value: int = 0, + max_priority_fee_per_gas=100_000_000, + salt: Optional[bytes] = None, + ): contract_deployer = PrecomputeContractDeployer(web3) - generated_call_data = contract_deployer.encode_create2_account(bytecode=bytecode, - call_data=call_data, - salt=salt) + generated_call_data = contract_deployer.encode_create2_account( + bytecode=bytecode, call_data=call_data, salt=salt + ) factory_deps = [] if deps is not None: for dep in deps: factory_deps.append(dep) factory_deps.append(bytecode) - eip712_meta = EIP712Meta(gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, - custom_signature=None, - factory_deps=factory_deps, - paymaster_params=None) - super(TxCreate2Account, self).__init__(trans={ - "chain_id": chain_id, - "nonce": nonce, - "from": from_, - "to": Web3.to_checksum_address(ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value), - "gas": gas_limit, - "gasPrice": gas_price, - "maxPriorityFeePerGas": max_priority_fee_per_gas, - "value": value, - "data": HexStr(generated_call_data), - "transactionType": TransactionType.EIP_712_TX_TYPE.value, - "eip712Meta": eip712_meta - }) - -class TxWithdraw(TxBase, ABC): + eip712_meta = EIP712Meta( + gas_per_pub_data=EIP712Meta.GAS_PER_PUB_DATA_DEFAULT, + custom_signature=None, + factory_deps=factory_deps, + paymaster_params=None, + ) + super(TxCreate2Account, self).__init__( + trans={ + "chain_id": chain_id, + "nonce": nonce, + "from": from_, + "to": Web3.to_checksum_address( + ZkSyncAddresses.CONTRACT_DEPLOYER_ADDRESS.value + ), + "gas": gas_limit, + "gasPrice": gas_price, + "maxPriorityFeePerGas": max_priority_fee_per_gas, + "value": value, + "data": HexStr(generated_call_data), + "transactionType": TransactionType.EIP_712_TX_TYPE.value, + "eip712Meta": eip712_meta, + } + ) - def __init__(self, - web3: Web3, - token: HexStr, - amount: int, - gas_limit: int, - account: BaseAccount, - gas_price: int = None, - to: HexStr = None, - bridge_address: HexStr = None, - chain_id: int = None, - nonce: int = None): +class TxWithdraw(TxBase, ABC): + def __init__( + self, + web3: Web3, + token: HexStr, + amount: int, + gas_limit: int, + account: BaseAccount, + gas_price: int = None, + to: HexStr = None, + bridge_address: HexStr = None, + chain_id: int = None, + nonce: int = None, + ): # INFO: send to self if to is None: to = account.address @@ -270,29 +313,37 @@ def __init__(self, if is_eth(token): if chain_id is None: web3.zksync.chain_id - contract = web3.zksync.contract(Web3.to_checksum_address(L2_ETH_TOKEN_ADDRESS), abi=eth_token_abi_default()) - tx = contract.functions.withdraw(to).build_transaction({ - "nonce": nonce, - "chainId": chain_id, - "gas": gas_limit, - "gasPrice": gas_price, - "value": amount, - "from": account.address, - }) + contract = web3.zksync.contract( + Web3.to_checksum_address(L2_ETH_TOKEN_ADDRESS), + abi=eth_token_abi_default(), + ) + tx = contract.functions.withdraw(to).build_transaction( + { + "nonce": nonce, + "chainId": chain_id, + "gas": gas_limit, + "gasPrice": gas_price, + "value": amount, + "from": account.address, + } + ) else: if bridge_address is None: - bridge_addresses: BridgeAddresses = web3.zksync.zks_get_bridge_contracts() + bridge_addresses: BridgeAddresses = ( + web3.zksync.zks_get_bridge_contracts() + ) bridge_address = bridge_addresses.erc20_l2_default_bridge - l2_bridge = web3.eth.contract(address=Web3.to_checksum_address(bridge_address), - abi=l2_bridge_abi_default()) - tx = l2_bridge.functions.withdraw(to, - token, - amount).build_transaction( - { - "from": account.address, - "nonce": nonce, - "gas": gas_limit, - }) + l2_bridge = web3.eth.contract( + address=Web3.to_checksum_address(bridge_address), + abi=l2_bridge_abi_default(), + ) + tx = l2_bridge.functions.withdraw(to, token, amount).build_transaction( + { + "from": account.address, + "nonce": nonce, + "gas": gas_limit, + } + ) super(TxWithdraw, self).__init__(trans=tx) @property @@ -300,5 +351,5 @@ def tx(self) -> ZkTx: return self.tx_ def estimated_gas(self, estimated_gas: int) -> ZkTx: - self.tx_['gas'] = estimated_gas - return self.tx_ \ No newline at end of file + self.tx_["gas"] = estimated_gas + return self.tx_