diff --git a/.github/scripts/interop.sh b/.github/scripts/interop.sh new file mode 100755 index 000000000000..d5aee4619ef1 --- /dev/null +++ b/.github/scripts/interop.sh @@ -0,0 +1,40 @@ +sudo rm -rf ./volumes && zk_supervisor clean containers && zk_inception up -o false + +zk_inception ecosystem init --deploy-paymaster --deploy-erc20 \ + --deploy-ecosystem --l1-rpc-url=http://localhost:8545 \ + --server-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --server-db-name=zksync_server_localhost_era \ + --prover-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --prover-db-name=zksync_prover_localhost_era \ + --ignore-prerequisites --observability=false --skip-submodules-checkout \ + --chain era # --no-port-reallocation + # --skip-contract-compilation-override \ + +zk_inception chain create \ + --chain-name second \ + --chain-id 505 \ + --prover-mode no-proofs \ + --wallet-creation localhost \ + --l1-batch-commit-data-generator-mode rollup \ + --base-token-address 0x0000000000000000000000000000000000000001 \ + --base-token-price-nominator 1 \ + --base-token-price-denominator 1 \ + --set-as-default false \ + --ignore-prerequisites --skip-submodules-checkout --skip-contract-compilation-override + +zk_inception chain init \ + --deploy-paymaster \ + --l1-rpc-url=http://localhost:8545 \ + --server-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --server-db-name=zksync_server_localhost_gateway \ + --prover-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ + --prover-db-name=zksync_prover_localhost_gateway \ + --chain second --skip-submodules-checkout --no-port-reallocation + +zk_inception server --ignore-prerequisites --chain era &> ./rollup.log & + +zk_inception server --ignore-prerequisites --chain second &> ./second.log & + +# sleep 20 + +# zk_supervisor test integration -t "Interop" --no-deps --ignore-prerequisites --chain era diff --git a/.github/workflows/ci-core-reusable.yml b/.github/workflows/ci-core-reusable.yml index fed26bbbb3bf..cf51c939c346 100644 --- a/.github/workflows/ci-core-reusable.yml +++ b/.github/workflows/ci-core-reusable.yml @@ -349,6 +349,109 @@ jobs: wait $PID2 wait $PID3 + interop: + name: Interop (consensus=false, base_token="Eth", sync_layer = false) + strategy: + # In matrix jobs, fail-fast is true by default. + # To be consistent with the rest of the workflow we disable it explicitly. + fail-fast: false + matrix: + # FIXME: support consensus tests for SL migration + consensus: [false] + # FIXME: support custom tokens + base_token: ["Eth"] + # FIXME: run tests even when not using synclayer + sync_layer: [true] + env: + SERVER_COMPONENTS: "api,tree,eth,state_keeper,housekeeper,commitment_generator,vm_runner_protective_reads" + + runs-on: [matterlabs-ci-runner] + steps: + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: Setup environment + run: | + echo ZKSYNC_HOME=$(pwd) >> $GITHUB_ENV + echo $(pwd)/bin >> $GITHUB_PATH + echo IN_DOCKER=1 >> .env + echo RUN_CONTRACT_VERIFICATION_TEST=true >> .env + echo ZKSYNC_DEBUG_LOGS=true >> .env + + - name: Download zksolc/solc and zkvyper/vyper + run: | + sudo apt update && sudo apt install wget -y + + mkdir -p $(pwd)/etc/solc-bin/0.8.23 + wget https://github.com/ethereum/solc-bin/raw/gh-pages/linux-amd64/solc-linux-amd64-v0.8.23%2Bcommit.f704f362 + mv solc-linux-amd64-v0.8.23+commit.f704f362 $(pwd)/etc/solc-bin/0.8.23/solc + chmod +x $(pwd)/etc/solc-bin/0.8.23/solc + + mkdir -p $(pwd)/etc/solc-bin/zkVM-0.8.23-1.0.0 + wget https://github.com/matter-labs/era-solidity/releases/download/0.8.23-1.0.0/solc-linux-amd64-0.8.23-1.0.0 -O $(pwd)/etc/solc-bin/zkVM-0.8.23-1.0.0/solc + chmod +x $(pwd)/etc/solc-bin/zkVM-0.8.23-1.0.0/solc + + mkdir -p $(pwd)/etc/zksolc-bin/v1.3.21 + wget https://github.com/matter-labs/zksolc-bin/raw/main/linux-amd64/zksolc-linux-amd64-musl-v1.3.21 + mv zksolc-linux-amd64-musl-v1.3.21 $(pwd)/etc/zksolc-bin/v1.3.21/zksolc + chmod +x $(pwd)/etc/zksolc-bin/v1.3.21/zksolc + + mkdir -p $(pwd)/etc/vyper-bin/0.3.10 + wget -O vyper0.3.10 https://github.com/vyperlang/vyper/releases/download/v0.3.10/vyper.0.3.10%2Bcommit.91361694.linux + mv vyper0.3.10 $(pwd)/etc/vyper-bin/0.3.10/vyper + chmod +x $(pwd)/etc/vyper-bin/0.3.10/vyper + + mkdir -p $(pwd)/etc/zkvyper-bin/v1.3.13 + wget https://github.com/matter-labs/zkvyper-bin/raw/main/linux-amd64/zkvyper-linux-amd64-musl-v1.3.13 + mv zkvyper-linux-amd64-musl-v1.3.13 $(pwd)/etc/zkvyper-bin/v1.3.13/zkvyper + chmod +x $(pwd)/etc/zkvyper-bin/v1.3.13/zkvyper + + - name: Start services + run: | + ci_localnet_up + ci_run pre_download_compilers.sh + ci_run sccache --start-server + + - name: Init + run: | + ci_run git config --global --add safe.directory /usr/src/zksync + ci_run git config --global --add safe.directory /usr/src/zksync/sdk/binaryen + ci_run git config --global --add safe.directory /usr/src/zksync/contracts/system-contracts + ci_run git config --global --add safe.directory /usr/src/zksync/contracts + ci_run zk + ci_run run_retried rustup show + ci_run zk config compile + ci_run zk init ${{ matrix.base_token == 'Custom' && '--base-token-name BAT' || ''}} ${{ matrix.deployment_mode == 'Validium' && '--validium-mode' || ''}} + + # `sleep 5` because we need to wait until server started properly + - name: Run server + run: | + ci_run zk server --use-node-framework --components=$SERVER_COMPONENTS &>server.log & + ci_run sleep 5 + + - name: Run contract verifier + run: | + ci_run zk contract_verifier &>contract_verifier.log & + ci_run sleep 2 + + - name: Init second chain + run: | + ci_run zk env test-chain + ci_run zk config compile test-chain --diff 5 + ci_run zk init hyper + + - name: Run second server + run: | + ci_run zk server --use-node-framework --components=$SERVER_COMPONENTS &>server.log & + ci_run sleep 5 + + - name: Server integration tests + run: ci_run zk test i server + + + - name: Upload logs uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 if: always() diff --git a/Cargo.toml b/Cargo.toml index 94fadb25968a..82a5a979f72e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,9 @@ members = [ ] resolver = "2" -exclude = [] +exclude = [ + "contracts/system-contracts/bootloader/test_infra", +] # for `perf` profiling [profile.perf] diff --git a/chains/second/ZkStack.yaml b/chains/second/ZkStack.yaml new file mode 100644 index 000000000000..794f73481034 --- /dev/null +++ b/chains/second/ZkStack.yaml @@ -0,0 +1,14 @@ +id: 3 +name: second +chain_id: 505 +prover_version: NoProofs +configs: /Users/kalmanlajko/programming/zksync/tmp2/zksync-era/./chains/second/configs/ +rocks_db_path: ./chains/second/db/ +external_node_config_path: null +artifacts_path: ./chains/second/artifacts/ +l1_batch_commit_data_generator_mode: Rollup +base_token: + address: '0x0000000000000000000000000000000000000001' + nominator: 1 + denominator: 1 +wallet_creation: Localhost diff --git a/chains/second/configs/contracts.yaml b/chains/second/configs/contracts.yaml new file mode 100644 index 000000000000..67af2629dfe7 --- /dev/null +++ b/chains/second/configs/contracts.yaml @@ -0,0 +1,43 @@ +create2_factory_addr: 0xe441cf0795af14ddb9f7984da85cd36db1b8790d +create2_factory_salt: 0x88923c4cbe9c208bdd041f7c19b2d0f7e16d312e3576f17934dd390b7a2c5cc5 +ecosystem_contracts: + bridgehub_proxy_addr: 0xf05aea6cd198a77da9ee3ea47d26cdcbfb3fde19 + state_transition_proxy_addr: 0x45b36bb8104407fd994e4261208b838cb230accb + transparent_proxy_admin_addr: 0x8cdfcf26e9f7ae1c49111cd165f3ce5711601f49 + stm_deployment_tracker_proxy_addr: 0x39490b0765545597619a2e8d6603932656902db9 + validator_timelock_addr: 0xfad37d465138449737299da612b71bfb86041983 + diamond_cut_data: 0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000cfeebf117657f8cacd70f57f6c0b2632775adb9d0000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000005f52b485277002800aa3b764177e9fdc0f51834600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000130e18b681000000000000000000000000000000000000000000000000000000001733894500000000000000000000000000000000000000000000000000000000fc57565f000000000000000000000000000000000000000000000000000000001cc5d1030000000000000000000000000000000000000000000000000000000021f603d700000000000000000000000000000000000000000000000000000000235d9eb50000000000000000000000000000000000000000000000000000000027ae4c16000000000000000000000000000000000000000000000000000000002878fe74000000000000000000000000000000000000000000000000000000003f42d5dd0000000000000000000000000000000000000000000000000000000041cf49bb000000000000000000000000000000000000000000000000000000004623c91d000000000000000000000000000000000000000000000000000000004dd18bf5000000000000000000000000000000000000000000000000000000006223258e0000000000000000000000000000000000000000000000000000000064b554ad0000000000000000000000000000000000000000000000000000000064bf8d6600000000000000000000000000000000000000000000000000000000a9f6d94100000000000000000000000000000000000000000000000000000000b784610700000000000000000000000000000000000000000000000000000000be6f11cf00000000000000000000000000000000000000000000000000000000e76db86500000000000000000000000000000000000000000000000000000000000000000000000000000000dd9eaca18ac93fa8d83924d7136557fefd7c6726000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000002d06d49e5b000000000000000000000000000000000000000000000000000000000ec6b0b700000000000000000000000000000000000000000000000000000000fe26699e0000000000000000000000000000000000000000000000000000000018e3a941000000000000000000000000000000000000000000000000000000001de72e340000000000000000000000000000000000000000000000000000000022c5cf230000000000000000000000000000000000000000000000000000000029b98c670000000000000000000000000000000000000000000000000000000033ce93fe000000000000000000000000000000000000000000000000000000003408e470000000000000000000000000000000000000000000000000000000003591c1a000000000000000000000000000000000000000000000000000000000396073820000000000000000000000000000000000000000000000000000000039d7d4aa0000000000000000000000000000000000000000000000000000000046657fe90000000000000000000000000000000000000000000000000000000052ef6b2c000000000000000000000000000000000000000000000000000000005a59033500000000000000000000000000000000000000000000000000000000631f4bac000000000000000000000000000000000000000000000000000000006a27e8b5000000000000000000000000000000000000000000000000000000006e9960c30000000000000000000000000000000000000000000000000000000074f4d30d0000000000000000000000000000000000000000000000000000000079823c9a000000000000000000000000000000000000000000000000000000007a0ed627000000000000000000000000000000000000000000000000000000007b30c8da00000000000000000000000000000000000000000000000000000000946ebad100000000000000000000000000000000000000000000000000000000960dcf240000000000000000000000000000000000000000000000000000000098acd7a6000000000000000000000000000000000000000000000000000000009cd939e4000000000000000000000000000000000000000000000000000000009d1b5a8100000000000000000000000000000000000000000000000000000000a1954fc500000000000000000000000000000000000000000000000000000000adfca15e00000000000000000000000000000000000000000000000000000000af6a2dcd00000000000000000000000000000000000000000000000000000000b22dd78e00000000000000000000000000000000000000000000000000000000b8c2f66f00000000000000000000000000000000000000000000000000000000bd7c541200000000000000000000000000000000000000000000000000000000c3bbd2d700000000000000000000000000000000000000000000000000000000cdffacc600000000000000000000000000000000000000000000000000000000d046815600000000000000000000000000000000000000000000000000000000d86970d800000000000000000000000000000000000000000000000000000000db1f0bf900000000000000000000000000000000000000000000000000000000e5355c7500000000000000000000000000000000000000000000000000000000e81e0ba100000000000000000000000000000000000000000000000000000000ea6c029c00000000000000000000000000000000000000000000000000000000ef3f0bae00000000000000000000000000000000000000000000000000000000f5c1182c00000000000000000000000000000000000000000000000000000000facd743b00000000000000000000000000000000000000000000000000000000fd791f3c00000000000000000000000000000000000000000000000000000000000000000000000000000000401924984b5680a77d049d53a0d8537e1e44eafd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b042901c70000000000000000000000000000000000000000000000000000000012f43dab00000000000000000000000000000000000000000000000000000000eb67241900000000000000000000000000000000000000000000000000000000263b7f8e000000000000000000000000000000000000000000000000000000006c0960f9000000000000000000000000000000000000000000000000000000007efda2ae00000000000000000000000000000000000000000000000000000000b473318e00000000000000000000000000000000000000000000000000000000d077255100000000000000000000000000000000000000000000000000000000ddcc9eec00000000000000000000000000000000000000000000000000000000e4948f4300000000000000000000000000000000000000000000000000000000e717bab7000000000000000000000000000000000000000000000000000000000000000000000000000000005df7d9b337021691050d6b2f9c74cf54fd9302bf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000040f23da4300000000000000000000000000000000000000000000000000000000e12a61370000000000000000000000000000000000000000000000000000000098f8196200000000000000000000000000000000000000000000000000000000cf02827d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000004f7a9d1de7c84de2d546a7377c60ea454117ef410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100098504c365264e12aa9fdf10652e73dd7c8cbe9c3a3a045070f0277af80d0100055dbd629567931421dcebb4b38da3dab317ac5e0abacb7dedc14e3d033c00000000000000000000000000000000000000000000000000000000044aa200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000001d4c00000000000000000000000000000000000000000000000000000000004c4b40000000000000000000000000000000000000000000000000000000000000182b8000000000000000000000000000000000000000000000000000000000ee6b2800000000000000000000000003522467fbcd7d48d3b4da6428ac8728793cd074a + force_deployments_data: 0x0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000007b06e9081e998c761c32ec7d56e449fd74f0fe3010000fd53068fc35c6a23fee067bcfd3fc0d880ba4f79d8b65aafbff02f305d000000000000000000000000be58a336a246b5f36154a5d73f958cfd852cdd3a000000000000000000000000000000000000000000000000000000000000006401000a1917cc40206afbcb59515fe12ac96056f008db6d01df958d4f289ff80501000535cb5d6c8221a56902072a3dde9ea4af3fa20b584fde6bd63c118694a9010005e3b9cc76d0a2402f5b32ed4e26c91b26c95e7ab8bdfb221bcd817f50d5010002eb7a16926de53a9e148cf3ab4720232541c8848e9b2535666354ef98660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + native_token_vault_addr: 0x94fd61f67f3362fd6980c2bd8989b1f93dd6eab4 +bridges: + erc20: + l1_address: 0x1561d571d3645266ea631884580bd8c5e634a5dd + l2_address: '0x0000000000000000000000000000000000010003' + shared: + l1_address: 0x07b06e9081e998c761c32ec7d56e449fd74f0fe3 + l2_address: '0x0000000000000000000000000000000000010003' + l1_nullifier_addr: 0x4686a7279d56e6238b7884d8e41bdc39f84e311c +l1: + default_upgrade_addr: 0x6d09ac6e0671c859ebea076346caa080820a587d + diamond_proxy_addr: 0x238b583e086e507c70ec60d60636e362f7467ea4 + governance_addr: 0x8a9dc757f84f2323cfe0ff555ef29363f0f8cb9f + chain_admin_addr: 0xa6fba37e028416e514b769ad767d3264775e78a1 + access_control_restriction_addr: 0x9be3e70228e06b02306a934cf17a8eb7c09b048b + chain_proxy_admin_addr: 0xfd285e11becbd6d81d32944947be1f97e321784f + multicall3_addr: 0x730a8c8fe82fb5d2b1b25bb7fa7cd73c1ef24009 + verifier_addr: 0x4f7a9d1de7c84de2d546a7377c60ea454117ef41 + validator_timelock_addr: 0xfad37d465138449737299da612b71bfb86041983 + base_token_addr: '0x0000000000000000000000000000000000000001' + rollup_l1_da_validator_addr: 0x9da4f47faf710c629b8d3fecb156453edd7822b9 + validium_l1_da_validator_addr: 0xd4b187f8d873e49f5ec81ec5b562f178e11a14e8 + transaction_filterer_addr: '0x0000000000000000000000000000000000000000' +l2: + testnet_paymaster_addr: 0x6d89cce5a8768668f4218a0b37cce5d234576a03 + default_l2_upgrader: 0x318137d99e9c1140dfef5e8c008e94b87ea5e1b1 + da_validator_addr: 0x8d223f4c39d5460ab3fc495a34e2559e1a4c1fd8 + l2_native_token_vault_proxy_addr: '0x0000000000000000000000000000000000010004' + legacy_shared_bridge_addr: 0xfcce3dbc002cfb8254e0d2eb2517e337414ee80f + consensus_registry: 0x5397bac0d1fae531f32156300b27187c552d78f2 + multicall3: 0x55f6f01d04a21e76cbd2de9d4a9ff6ee9f8893a6 +user_facing_bridgehub: 0xf05aea6cd198a77da9ee3ea47d26cdcbfb3fde19 +user_facing_diamond_proxy: 0x238b583e086e507c70ec60d60636e362f7467ea4 diff --git a/chains/second/configs/external_node.yaml b/chains/second/configs/external_node.yaml new file mode 100644 index 000000000000..e97b04fb3900 --- /dev/null +++ b/chains/second/configs/external_node.yaml @@ -0,0 +1,8 @@ +l1_chain_id: 9 +l2_chain_id: 270 +l1_batch_commit_data_generator_mode: Rollup + +main_node_url: http://localhost:3050 +main_node_rate_limit_rps: 1000 + +gateway_url: http://localhost:3052 diff --git a/chains/second/configs/general.yaml b/chains/second/configs/general.yaml new file mode 100644 index 000000000000..7b0f49e7b3a8 --- /dev/null +++ b/chains/second/configs/general.yaml @@ -0,0 +1,390 @@ +postgres: + max_connections: 100 + statement_timeout_sec: 300 + test: + server_url: postgres://postgres:notsecurepassword@localhost:5433/zksync_local_test + prover_url: postgres://postgres:notsecurepassword@localhost:5433/prover_local_test +api: + web3_json_rpc: + http_port: 3050 + http_url: http://127.0.0.1:3050 + ws_port: 3051 + ws_url: ws://127.0.0.1:3051 + req_entities_limit: 10000 + filters_limit: 10000 + subscriptions_limit: 10000 + pubsub_polling_interval: 200 + max_nonce_ahead: 40 + gas_price_scale_factor: 1.5 + estimate_gas_scale_factor: 1.3 + estimate_gas_acceptable_overestimation: 5000 + max_tx_size: 1000000 + filters_disabled: false + api_namespaces: + - en + - eth + - net + - web3 + - zks + - pubsub + - debug + extended_api_tracing: false + estimate_gas_optimize_search: false + prometheus: + listener_port: 3312 + pushgateway_url: http://127.0.0.1:9091 + push_interval_ms: 100 + healthcheck: + port: 3071 + merkle_tree: + port: 3072 +contract_verifier: + port: 3070 + url: http://127.0.0.1:3070 + compilation_timeout: 240 + polling_interval: 1000 + threads_per_server: 128 + prometheus_port: 3318 +circuit_breaker: + sync_interval_ms: 120000 + http_req_max_retry_number: 10 + http_req_retry_interval_sec: 2 + replication_lag_limit_sec: 100 +mempool: + sync_interval_ms: 10 + sync_batch_size: 1000 + capacity: 10000000 + stuck_tx_timeout: 172800 + remove_stuck_txs: true + delay_interval: 100 +operations_manager: + delay_interval: 100 +state_keeper: + transaction_slots: 8192 + block_commit_deadline_ms: 2500 + miniblock_commit_deadline_ms: 1000 + miniblock_seal_queue_capacity: 10 + max_single_tx_gas: 15000000 + max_allowed_l2_tx_gas_limit: 15000000000 + reject_tx_at_geometry_percentage: 0.95 + reject_tx_at_eth_params_percentage: 0.95 + reject_tx_at_gas_percentage: 0.95 + close_block_at_geometry_percentage: 0.95 + close_block_at_eth_params_percentage: 0.95 + close_block_at_gas_percentage: 0.95 + minimal_l2_gas_price: 100000000 + compute_overhead_part: 0.0 + pubdata_overhead_part: 1.0 + batch_overhead_l1_gas: 800000 + max_gas_per_batch: 200000000 + max_pubdata_per_batch: 500000 + fee_model_version: V2 + validation_computational_gas_limit: 300000 + save_call_traces: true + max_circuits_per_batch: 31100 + miniblock_max_payload_size: 1000000 + protective_reads_persistence_enabled: false +house_keeper: + l1_batch_metrics_reporting_interval_ms: 10000 +prover: + setup_data_path: data/keys + prometheus_port: 3315 + max_attempts: 10 + generation_timeout_in_secs: 600 + setup_load_mode: FROM_DISK + specialized_group_id: 100 + queue_capacity: 10 + witness_vector_receiver_port: 3316 + zone_read_url: http://metadata.google.internal/computeMetadata/v1/instance/zone + shall_save_to_public_bucket: true + availability_check_interval_in_secs: 10000 + public_object_store: + file_backed: + file_backed_base_path: ./chains/second/artifacts/ + max_retries: 10 + prover_object_store: + file_backed: + file_backed_base_path: ./chains/second/artifacts/ + max_retries: 10 + cloud_type: LOCAL +prometheus: + listener_port: 3314 + pushgateway_url: http://127.0.0.1:9091 + push_interval_ms: 100 +db: + state_keeper_db_path: /Users/kalmanlajko/programming/zksync/tmp2/zksync-era/./chains/second/db/main/state_keeper + merkle_tree: + path: /Users/kalmanlajko/programming/zksync/tmp2/zksync-era/./chains/second/db/main/tree + mode: FULL + multi_get_chunk_size: 500 + block_cache_size_mb: 128 + memtable_capacity_mb: 256 + stalled_writes_timeout_sec: 60 + max_l1_batches_per_iter: 20 + experimental: + state_keeper_db_block_cache_capacity_mb: 128 + reads_persistence_enabled: false + processing_delay_ms: 0 + include_indices_and_filters_in_block_cache: false +eth: + sender: + aggregated_proof_sizes: + - 1 + wait_confirmations: 1 + tx_poll_period: 1 + aggregate_tx_poll_period: 1 + max_txs_in_flight: 30 + proof_sending_mode: SKIP_EVERY_PROOF + max_aggregated_tx_gas: 15000000 + max_eth_tx_data_size: 120000 + max_aggregated_blocks_to_commit: 1 + max_aggregated_blocks_to_execute: 45 + aggregated_block_commit_deadline: 1 + aggregated_block_prove_deadline: 10 + aggregated_block_execute_deadline: 10 + timestamp_criteria_max_allowed_lag: 30 + max_acceptable_priority_fee_in_gwei: 100000000000 + pubdata_sending_mode: BLOBS + tx_aggregation_paused: false + tx_aggregation_only_prove_and_execute: false + gas_adjuster: + default_priority_fee_per_gas: 1000000000 + max_base_fee_samples: 100 + pricing_formula_parameter_a: 1.5 + pricing_formula_parameter_b: 1.001 + internal_l1_pricing_multiplier: 0.8 + poll_period: 5 + num_samples_for_blob_base_fee_estimate: 10 + internal_pubdata_pricing_multiplier: 1.0 + settlement_mode: SettlesToL1 + watcher: + confirmations_for_eth_event: 0 + eth_node_poll_interval: 300 +witness_generator: + generation_timeout_in_secs: 900 + max_attempts: 10 + shall_save_to_public_bucket: true + prometheus_listener_port: 3116 + max_circuits_in_flight: 500 +witness_vector_generator: + max_prover_reservation_duration_in_secs: 1000 + prover_instance_wait_timeout_in_secs: 200 + prover_instance_poll_time_in_milli_secs: 250 + prometheus_listener_port: 3420 + prometheus_pushgateway_url: http://127.0.0.1:9091 + prometheus_push_interval_ms: 100 + specialized_group_id: 100 +proof_compressor: + compression_mode: 1 + prometheus_listener_port: 3321 + prometheus_pushgateway_url: http://127.0.0.1:9091 + prometheus_push_interval_ms: 100 + generation_timeout_in_secs: 3600 + max_attempts: 5 + universal_setup_path: keys/setup/setup_2^24.key + universal_setup_download_url: https://storage.googleapis.com/matterlabs-setup-keys-us/setup-keys/setup_2^24.key + verify_wrapper_proof: true +data_handler: + http_port: 3320 + proof_generation_timeout_in_secs: 18000 + tee_support: true +prover_group: + group_0: + - circuit_id: 1 + aggregation_round: 4 + - circuit_id: 2 + aggregation_round: 2 + - circuit_id: 255 + aggregation_round: 0 + group_1: + - circuit_id: 1 + aggregation_round: 0 + group_2: + - circuit_id: 2 + aggregation_round: 0 + - circuit_id: 4 + aggregation_round: 0 + - circuit_id: 6 + aggregation_round: 0 + - circuit_id: 9 + aggregation_round: 0 + group_3: + - circuit_id: 3 + aggregation_round: 0 + group_4: + - circuit_id: 11 + aggregation_round: 0 + - circuit_id: 12 + aggregation_round: 0 + - circuit_id: 13 + aggregation_round: 0 + group_5: + - circuit_id: 5 + aggregation_round: 0 + group_6: + - circuit_id: 3 + aggregation_round: 1 + group_7: + - circuit_id: 7 + aggregation_round: 0 + group_8: + - circuit_id: 8 + aggregation_round: 0 + group_9: + - circuit_id: 12 + aggregation_round: 1 + - circuit_id: 13 + aggregation_round: 1 + - circuit_id: 14 + aggregation_round: 1 + - circuit_id: 15 + aggregation_round: 1 + group_10: + - circuit_id: 10 + aggregation_round: 0 + group_11: + - circuit_id: 7 + aggregation_round: 1 + - circuit_id: 8 + aggregation_round: 1 + - circuit_id: 10 + aggregation_round: 1 + - circuit_id: 11 + aggregation_round: 1 + group_12: + - circuit_id: 4 + aggregation_round: 1 + - circuit_id: 5 + aggregation_round: 1 + - circuit_id: 6 + aggregation_round: 1 + - circuit_id: 9 + aggregation_round: 1 + group_13: + - circuit_id: 14 + aggregation_round: 0 + - circuit_id: 15 + aggregation_round: 0 + - circuit_id: 255 + aggregation_round: 0 + group_14: + - circuit_id: 16 + aggregation_round: 1 + - circuit_id: 17 + aggregation_round: 1 + - circuit_id: 18 + aggregation_round: 1 +prover_gateway: + api_url: http://127.0.0.1:3320 + api_poll_duration_secs: 15 + prometheus_listener_port: 3310 + prometheus_pushgateway_url: http://127.0.0.1:9091 + prometheus_push_interval_ms: 100 +snapshot_creator: + storage_logs_chunk_size: 1000000 + concurrent_queries_count: 25 + object_store: + file_backed: + file_backed_base_path: ./chains/second/artifacts/ + max_retries: 10 + version: 0 +observability: + log_format: plain + log_directives: zksync_multivm=trace,zksync_node_test_utils=info,zksync_state_keeper=info,zksync_reorg_detector=info,zksync_consistency_checker=info,zksync_metadata_calculator=info,zksync_node_sync=info,zksync_node_consensus=info,zksync_contract_verification_server=info,zksync_node_api_server=info,zksync_tee_verifier_input_producer=info,zksync_node_framework=info,zksync_block_reverter=info,zksync_commitment_generator=debug,zksync_node_db_pruner=info,zksync_eth_sender=info,zksync_node_fee_model=info,zksync_node_genesis=info,zksync_house_keeper=info,zksync_proof_data_handler=info,zksync_shared_metrics=info,zksync_node_test_utils=info,zksync_vm_runner=info,zksync_consensus_bft=info,zksync_consensus_network=info,zksync_consensus_storage=info,zksync_core_leftovers=debug,zksync_server=debug,zksync_contract_verifier=debug,zksync_dal=info,zksync_db_connection=info,zksync_eth_client=info,zksync_eth_watch=debug,zksync_storage=info,zksync_db_manager=info,zksync_merkle_tree=info,zksync_state=debug,zksync_utils=debug,zksync_queued_job_processor=info,zksync_types=info,zksync_mempool=debug,loadnext=info,vm=info,zksync_object_store=info,zksync_external_node=info,zksync_witness_generator=info,zksync_prover_fri=info,zksync_witness_vector_generator=info,zksync_web3_decl=debug,zksync_health_check=debug,zksync_proof_fri_compressor=info,vise_exporter=error,snapshots_creator=debug,zksync_base_token_adjuster=debug,zksync_external_price_api=debug,zksync_external_proof_integration_api=info +protective_reads_writer: + db_path: /Users/kalmanlajko/programming/zksync/tmp2/zksync-era/./chains/second/db/main/protective_reads + window_size: 3 + first_processed_batch: 0 +core_object_store: + file_backed: + file_backed_base_path: ./chains/second/artifacts/ + max_retries: 10 +snapshot_recovery: + enabled: false + postgres: + max_concurrency: 10 + tree: + chunk_size: 200000 + object_store: + file_backed: + file_backed_base_path: ./chains/second/artifacts/ + max_retries: 100 + experimental: + tree_recovery_parallel_persistence_buffer: 1 + drop_storage_key_preimages: true +pruning: + enabled: true + chunk_size: 10 + removal_delay_sec: 60 + data_retention_sec: 3600 +commitment_generator: + max_parallelism: 10 +da_dispatcher: + polling_interval_ms: 5000 + max_rows_to_dispatch: 100 + max_retries: 5 +base_token_adjuster: + price_polling_interval_ms: 30000 + price_cache_update_interval_ms: 2000 + max_tx_gas: 80000 + default_priority_fee_per_gas: 1000000 + max_acceptable_priority_fee_in_gwei: 100000000000 + l1_receipt_checking_sleep_ms: 30000 + l1_receipt_checking_max_attempts: 3 + l1_tx_sending_max_attempts: 3 + l1_tx_sending_sleep_ms: 30000 + halt_on_error: false + price_fetching_max_attempts: 3 + price_fetching_sleep_ms: 5000 + l1_update_deviation_percentage: 10 +basic_witness_input_producer: + db_path: /Users/kalmanlajko/programming/zksync/tmp2/zksync-era/./chains/second/db/main/basic_witness_input_producer + window_size: 3 + first_processed_batch: 0 +external_price_api_client: + source: forced + client_timeout_ms: 10000 + forced_numerator: 3 + forced_denominator: 2 +consensus: + server_addr: 127.0.0.1:3254 + public_addr: 0.0.0.0:3254 + max_payload_size: 2500000 + gossip_dynamic_inbound_limit: 100 + genesis_spec: + chain_id: 505 + protocol_version: 1 + validators: + - key: validator:public:bls12_381:91a0c9c839681eff16d0a9d249e7fd04a424283b53e7f64488585116797bf376b1f6437ede53d9af1c092123c9d260c9053b6ced6eb4fe2c32d7943628cdc4de0386fc0f40fe444a3162a21dd32addc6345b747b1bd36fee23786ca306765715 + weight: 1 + leader: validator:public:bls12_381:91a0c9c839681eff16d0a9d249e7fd04a424283b53e7f64488585116797bf376b1f6437ede53d9af1c092123c9d260c9053b6ced6eb4fe2c32d7943628cdc4de0386fc0f40fe444a3162a21dd32addc6345b747b1bd36fee23786ca306765715 + attesters: + - key: attester:public:secp256k1:0248a833b9131724b57dda7b6cc47b9c5fd6b719577c61c3eed2697ff158870c49 + weight: 1 + max_batch_size: 12500001024 +external_proof_integration_api: + http_port: 3073 +experimental_vm: + playground: + fast_vm_mode: SHADOW + db_path: ./db/main/vm_playground + first_processed_batch: 0 + reset: false + window_size: 1 + state_keeper_fast_vm_mode: OLD +prover_job_monitor: + prometheus_port: 3317 + max_db_connections: 9 + graceful_shutdown_timeout_ms: 5000 + gpu_prover_archiver_run_interval_ms: 86400000 + gpu_prover_archiver_archive_prover_after_ms: 172800000 + prover_jobs_archiver_run_interval_ms: 1800000 + prover_jobs_archiver_archive_jobs_after_ms: 172800000 + proof_compressor_job_requeuer_run_interval_ms: 10000 + prover_job_requeuer_run_interval_ms: 10000 + witness_generator_job_requeuer_run_interval_ms: 10000 + proof_compressor_queue_reporter_run_interval_ms: 10000 + prover_queue_reporter_run_interval_ms: 10000 + witness_generator_queue_reporter_run_interval_ms: 10000 + witness_job_queuer_run_interval_ms: 10000 + http_port: 3074 diff --git a/chains/second/configs/genesis.yaml b/chains/second/configs/genesis.yaml new file mode 100644 index 000000000000..347351e0b718 --- /dev/null +++ b/chains/second/configs/genesis.yaml @@ -0,0 +1,14 @@ +genesis_root: 0x1913ab06c329da26d18545ceac42082071eeb1038d43a71d5210b637e3d07d1b +genesis_rollup_leaf_index: 66 +genesis_batch_commitment: 0x8492ade706f6e7c826e8ba07d85daf6a90b3596e44547ce3234b4cf92761380d +genesis_protocol_version: 25 +default_aa_hash: 0x0100055dbd629567931421dcebb4b38da3dab317ac5e0abacb7dedc14e3d033c +bootloader_hash: 0x0100098504c365264e12aa9fdf10652e73dd7c8cbe9c3a3a045070f0277af80d +l1_chain_id: 9 +l2_chain_id: 505 +fee_account: '0x0000000000000000000000000000000000000001' +prover: + dummy_verifier: true + snark_wrapper_vk_hash: 0x14f97b81e54b35fe673d8708cc1a19e1ea5b5e348e12d31e39824ed4f42bbca2 +genesis_protocol_semantic_version: 0.25.0 +l1_batch_commit_data_generator_mode: Rollup diff --git a/chains/second/configs/secrets.yaml b/chains/second/configs/secrets.yaml new file mode 100644 index 000000000000..7c0d48ffdd92 --- /dev/null +++ b/chains/second/configs/secrets.yaml @@ -0,0 +1,9 @@ +database: + server_url: postgres://postgres:notsecurepassword@localhost:5432/zksync_server_localhost_gateway + prover_url: postgres://postgres:notsecurepassword@localhost:5432/zksync_prover_localhost_gateway +l1: + l1_rpc_url: http://localhost:8545/ +consensus: + validator_key: validator:secret:bls12_381:51150688c4356f9b521ed70b1e0b01001f622a57a144b382bf6c8a8fc4ea78e8 + node_key: node:secret:ed25519:0b0808172c45942b36160084016125dbcd81d27e1a96e6a9e15910893d866bac + attester_key: attester:secret:secp256k1:d246398d71baecc7bb0b2e7e98e275034a0d547cdc5334ac7ba8ddd03c8324eb diff --git a/chains/second/configs/wallets.yaml b/chains/second/configs/wallets.yaml new file mode 100644 index 000000000000..54f051212a77 --- /dev/null +++ b/chains/second/configs/wallets.yaml @@ -0,0 +1,18 @@ +deployer: + address: 0xd908cce334fbb4540e33e15f1a21edbe35648a6c + private_key: 0xfac90a4f2103d6c809d829e9a692432af8b4e0ac32e86528fbe3413c6f147a8b +operator: + address: 0x708a24a60a30f7d29f3bac9ba2f9a230d8f15c8b + private_key: 0xff36d32f2ee61d1f29a5e5114676940585b5ee9cd05b9b283526e37cc7f16a17 +blob_operator: + address: 0x3a27f236e130f311abcecebf4183150d0f421d06 + private_key: 0x10f07addd35133597420ca9a4188604ce022c5f69e39e32b666f54adae55392d +fee_account: + address: 0xe83d3fd8b0cb021fc66ebe01897aff774ae550ad + private_key: 0x1b8235e964a766ce5dd91c534d9a8a7253b9ba30e84690435293e110037cf829 +governor: + address: 0x8d8f4b07afdf9c27a0e691f646053535a327701b + private_key: 0x45135f91ac3455147581d5a0437da5b930584a67a2ca46a3c5d128acdf4a4b23 +token_multiplier_setter: + address: 0x52cc79db3a70a8bd4b33f4b60dd3b2782cd27a61 + private_key: 0x8c2dbaf41f1c51cf04106118c9db611578923ad89143b268de22259104f15133 diff --git a/contracts b/contracts index 53b0283f82f4..527db0d45e19 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 53b0283f82f4262c973eb3faed56ee8f6cda47b9 +Subproject commit 527db0d45e19a89e29dcba5c43b68ea6569671d1 diff --git a/core/lib/constants/src/contracts.rs b/core/lib/constants/src/contracts.rs index 1518d2d9f776..695d7f978de5 100644 --- a/core/lib/constants/src/contracts.rs +++ b/core/lib/constants/src/contracts.rs @@ -156,6 +156,19 @@ pub const L2_MESSAGE_ROOT_ADDRESS: Address = H160([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, ]); +pub const L2_INTEROP_CENTER_ADDRESS: Address = H160([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x08, +]); +pub const L2_INTEROP_HANDLER_ADDRESS: Address = H160([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x09, +]); + +pub const INTEROP_ACCOUNT_ADDRESS: Address = H160([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x0a, // to do delete this. For now we predeploy to have the bytecode. +]); pub const ERC20_TRANSFER_TOPIC: H256 = H256([ 221, 242, 82, 173, 27, 226, 200, 155, 105, 194, 176, 104, 252, 55, 141, 170, 149, 43, 167, 241, diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index 4caf81fd0cf4..f7ab7ed36e28 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -14,9 +14,10 @@ use crate::{ block::DeployedContract, ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS, COMPLEX_UPGRADER_ADDRESS, CONTRACT_DEPLOYER_ADDRESS, ECRECOVER_PRECOMPILE_ADDRESS, EC_ADD_PRECOMPILE_ADDRESS, EC_MUL_PRECOMPILE_ADDRESS, EC_PAIRING_PRECOMPILE_ADDRESS, - IMMUTABLE_SIMULATOR_STORAGE_ADDRESS, KECCAK256_PRECOMPILE_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS, - L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, MSG_VALUE_SIMULATOR_ADDRESS, NONCE_HOLDER_ADDRESS, - SHA256_PRECOMPILE_ADDRESS, SYSTEM_CONTEXT_ADDRESS, + IMMUTABLE_SIMULATOR_STORAGE_ADDRESS, INTEROP_ACCOUNT_ADDRESS, KECCAK256_PRECOMPILE_ADDRESS, + KNOWN_CODES_STORAGE_ADDRESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, + L2_INTEROP_CENTER_ADDRESS, L2_INTEROP_HANDLER_ADDRESS, MSG_VALUE_SIMULATOR_ADDRESS, + NONCE_HOLDER_ADDRESS, SHA256_PRECOMPILE_ADDRESS, SYSTEM_CONTEXT_ADDRESS, }; // Note, that in the `NONCE_HOLDER_ADDRESS` storage the nonces of accounts @@ -27,7 +28,7 @@ use crate::{ pub const TX_NONCE_INCREMENT: U256 = U256([1, 0, 0, 0]); // 1 pub const DEPLOYMENT_NONCE_INCREMENT: U256 = U256([0, 0, 1, 0]); // 2^128 -static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 30] = [ +static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 33] = [ ( "", "AccountCodeStorage", @@ -200,6 +201,24 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 30] = [ L2_NATIVE_TOKEN_VAULT_ADDRESS, ContractLanguage::Sol, ), + ( + "../../../l1-contracts/artifacts-zk/contracts/bridgehub/", + "InteropHandler", + L2_INTEROP_HANDLER_ADDRESS, + ContractLanguage::Sol, + ), + ( + "../../../l1-contracts/artifacts-zk/contracts/bridgehub/", + "InteropCenter", + L2_INTEROP_CENTER_ADDRESS, + ContractLanguage::Sol, + ), + ( + "../../../l1-contracts/artifacts-zk/contracts/bridgehub/", + "InteropAccount", + INTEROP_ACCOUNT_ADDRESS, + ContractLanguage::Sol, + ), ]; static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index ad8e38ef3cc2..cc0264fdfcad 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -18,6 +18,7 @@ use zksync_state_keeper::{ seal_criteria::{ConditionalSealer, NoopSealer, SealData}, SequencerSealer, }; +use zksync_system_constants::L2_INTEROP_HANDLER_ADDRESS; use zksync_types::{ api::state_override::StateOverride, fee_model::BatchFeeInput, @@ -521,6 +522,9 @@ impl TxSender { if paymaster != Address::default() { return Ok(()); } + if tx.execute.contract_address == Some(L2_INTEROP_HANDLER_ADDRESS) { + return Ok(()); + } let balance = self.get_balance(&tx.common_data.initiator_address).await?; // Estimate the minimum fee price user will agree to. diff --git a/core/tests/ts-integration/contracts/Swap/Swap.sol b/core/tests/ts-integration/contracts/Swap/Swap.sol new file mode 100644 index 000000000000..f53e9f0260d4 --- /dev/null +++ b/core/tests/ts-integration/contracts/Swap/Swap.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IERC20 { + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); +} + +contract Swap { + + address public token1Address; + address public token2Address; + + constructor(address _token1Address, address _token2Address) { + token1Address = _token1Address; + token2Address = _token2Address; + } + + function swap(uint256 amount) public payable { + IERC20(token1Address).transferFrom(msg.sender, address(this), amount); + IERC20(token2Address).transfer(msg.sender, amount); + } +} \ No newline at end of file diff --git a/core/tests/ts-integration/package.json b/core/tests/ts-integration/package.json index 24e564504f44..a2b955065f61 100644 --- a/core/tests/ts-integration/package.json +++ b/core/tests/ts-integration/package.json @@ -32,6 +32,7 @@ "ts-node": "^10.1.0", "typescript": "^4.3.5", "zksync-ethers": "git+https://github.com/zksync-sdk/zksync-ethers#ra/fix-l2-l1-bridging", + "zksync-ethers-interop-support": "git+https://github.com/zksync-sdk/zksync-ethers#kl/interop-ethers-support", "zksync-ethers-gw": "https://github.com/zksync-sdk/zksync-ethers#kl/gateway-support", "elliptic": "^6.5.5", "yaml": "^2.4.2" diff --git a/core/tests/ts-integration/src/constants.ts b/core/tests/ts-integration/src/constants.ts new file mode 100644 index 000000000000..eb056299eb16 --- /dev/null +++ b/core/tests/ts-integration/src/constants.ts @@ -0,0 +1,58 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +export const REQUIRED_L2_GAS_PRICE_PER_PUBDATA = 800; + +export const SYSTEM_UPGRADE_L2_TX_TYPE = 254; +export const ADDRESS_ONE = '0x0000000000000000000000000000000000000001'; +export const ETH_ADDRESS_IN_CONTRACTS = ADDRESS_ONE; +export const L1_TO_L2_ALIAS_OFFSET = '0x1111000000000000000000000000000000001111'; +export const L2_BRIDGEHUB_ADDRESS = '0x0000000000000000000000000000000000010002'; +export const L2_ASSET_ROUTER_ADDRESS = '0x0000000000000000000000000000000000010003'; +export const L2_NATIVE_TOKEN_VAULT_ADDRESS = '0x0000000000000000000000000000000000010004'; +export const L2_MESSAGE_ROOT_ADDRESS = '0x0000000000000000000000000000000000010005'; +// export const L2_NULLIFIER_ADDRESS = '0x0000000000000000000000000000000000010008'; +export const L2_INTEROP_CENTER_ADDRESS = '0x0000000000000000000000000000000000010008'; +export const L2_INTEROP_HANDLER_ADDRESS = '0x0000000000000000000000000000000000010009'; +export const DEPLOYER_SYSTEM_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000008006'; +export const L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR = '0x0000000000000000000000000000000000008008'; +export const EMPTY_STRING_KECCAK = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; +export const BRIDGEHUB_L2_CANONICAL_TRANSACTION_ABI = + 'tuple(uint256 txType, uint256 from, uint256 to, uint256 gasLimit, uint256 gasPerPubdataByteLimit, uint256 maxFeePerGas, uint256 maxPriorityFeePerGas, uint256 paymaster, uint256 nonce, uint256 value, uint256[4] reserved, bytes data, bytes signature, uint256[] factoryDeps, bytes paymasterInput, bytes reservedDynamic)'; +export const BRIDGEHUB_L2_TRANSACTION_REQUEST_ABI = + 'tuple(address sender, address contractL2, uint256 mintValue, uint256 l2Value, bytes l2Calldata, uint256 l2GasLimit, uint256 l2GasPerPubdataByteLimit, bytes[] factoryDeps, address refundRecipient)'; +export const L2_LOG_STRING = + 'tuple(uint8 l2ShardId,bool isService,uint16 txNumberInBatch,address sender,bytes32 key,bytes32 value)'; +export const ARTIFACTS_PATH = '../../../contracts/l1-contracts/artifacts/contracts/'; + +// struct InteropTrigger { +// uint256 destinationChainId; +// address sender; +// bytes32 feeBundleHash; +// bytes32 executionBundleHash; +// GasFields gasFields; +// } +// struct GasFields { +// uint256 gasLimit; +// uint256 gasPerPubdataByteLimit; +// address refundRecipient; +// } +export const INTEROP_TRIGGER_ABI = + 'tuple(uint256 destinationChainId, address from, bytes32 feeBundleHash, bytes32 executionBundleHash, tuple(uint256 gasLimit, uint256 gasPerPubdataByteLimit, address refundRecipient) gasFields)'; + +// struct InteropBundle { +// uint256 destinationChainId; +// InteropCall[] calls; +// // If not set - anyone can execute it. +// address[] executionAddresses; +// // Who can 'cancel' this bundle. +// address cancellationAddress; +// } + +// struct InteropCall { +// address to; +// address from; +// uint256 value; +// bytes data; +// } +export const INTEROP_CALL_ABI = 'tuple(address to, address from, uint256 value, bytes data)'; +export const INTEROP_BUNDLE_ABI = + 'tuple(uint256 destinationChainId, tuple(address to, address from, uint256 value, bytes data)[] calls, address[] executionAddresses, address cancellationAddress)'; diff --git a/core/tests/ts-integration/src/context-owner.ts b/core/tests/ts-integration/src/context-owner.ts index 2c72875313e2..07f59e39a731 100644 --- a/core/tests/ts-integration/src/context-owner.ts +++ b/core/tests/ts-integration/src/context-owner.ts @@ -1,4 +1,5 @@ -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { BigNumberish } from 'ethers'; diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 9a7041899ed4..1171a5d3a087 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -1,7 +1,8 @@ import * as path from 'path'; import * as fs from 'fs'; import * as ethers from 'ethers'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import { DataAvailabityMode, NodeMode, TestEnvironment } from './types'; import { Reporter } from './reporter'; import * as yaml from 'yaml'; diff --git a/core/tests/ts-integration/src/helpers.ts b/core/tests/ts-integration/src/helpers.ts index 354dfe64fdf0..278e7e4031f4 100644 --- a/core/tests/ts-integration/src/helpers.ts +++ b/core/tests/ts-integration/src/helpers.ts @@ -1,5 +1,6 @@ import * as fs from 'fs'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import * as hre from 'hardhat'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-solc/dist/src/types'; diff --git a/core/tests/ts-integration/src/matchers/transaction.ts b/core/tests/ts-integration/src/matchers/transaction.ts index ac5bf8e77eaf..9c8721c84380 100644 --- a/core/tests/ts-integration/src/matchers/transaction.ts +++ b/core/tests/ts-integration/src/matchers/transaction.ts @@ -1,6 +1,7 @@ import { TestMessage } from './matcher-helpers'; import { MatcherModifier } from '../modifiers'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import { AugmentedTransactionResponse } from '../transaction-response'; import { ethers } from 'ethers'; diff --git a/core/tests/ts-integration/src/modifiers/balance-checker.ts b/core/tests/ts-integration/src/modifiers/balance-checker.ts index 12e2c70c53de..d4afe4a4dd9f 100644 --- a/core/tests/ts-integration/src/modifiers/balance-checker.ts +++ b/core/tests/ts-integration/src/modifiers/balance-checker.ts @@ -2,7 +2,8 @@ * Collection of modifiers to check token balance changes caused by a transaction. */ -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { TestMessage } from '../matchers/matcher-helpers'; import { MatcherModifier, MatcherMessage } from '.'; diff --git a/core/tests/ts-integration/src/modifiers/index.ts b/core/tests/ts-integration/src/modifiers/index.ts index 840c7b654930..05c4b3ab7467 100644 --- a/core/tests/ts-integration/src/modifiers/index.ts +++ b/core/tests/ts-integration/src/modifiers/index.ts @@ -2,7 +2,8 @@ * Base interface for custom transaction matcher modifiers. */ -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; /** * Base class for custom transaction matcher modifiers. diff --git a/core/tests/ts-integration/src/modifiers/receipt-check.ts b/core/tests/ts-integration/src/modifiers/receipt-check.ts index 12d54e1b8ed6..a1111acb9121 100644 --- a/core/tests/ts-integration/src/modifiers/receipt-check.ts +++ b/core/tests/ts-integration/src/modifiers/receipt-check.ts @@ -1,5 +1,6 @@ import { MatcherModifier, MatcherMessage } from '.'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; /** * Creates a custom checker for the transaction receipt. diff --git a/core/tests/ts-integration/src/retry-provider.ts b/core/tests/ts-integration/src/retry-provider.ts index 51d88357c6c3..a51472d546ac 100644 --- a/core/tests/ts-integration/src/retry-provider.ts +++ b/core/tests/ts-integration/src/retry-provider.ts @@ -1,4 +1,5 @@ -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { Reporter } from './reporter'; import { AugmentedTransactionResponse } from './transaction-response'; diff --git a/core/tests/ts-integration/src/temp-sdk.ts b/core/tests/ts-integration/src/temp-sdk.ts new file mode 100644 index 000000000000..1d65ac7d2c84 --- /dev/null +++ b/core/tests/ts-integration/src/temp-sdk.ts @@ -0,0 +1,282 @@ +import * as zksync from 'zksync-ethers-interop-support'; +import * as ethers from 'ethers'; +import { BytesLike } from 'ethers'; +import { + L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, + BRIDGEHUB_L2_CANONICAL_TRANSACTION_ABI, + INTEROP_BUNDLE_ABI, + INTEROP_TRIGGER_ABI +} from './constants'; + +const L1_MESSENGER_ADDRESS = L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR; + +export interface Output { + output: any; + rawData: any; + l1BatchNumber: number; + l2TxNumberInBlock: number; +} + +export async function getInteropBundleData( + provider: zksync.Provider, + withdrawalHash: BytesLike, + index = 0 +): Promise { + const response = await tryGetMessageData(provider, withdrawalHash, index); + if (!response) return { rawData: null, output: null, l1BatchNumber: 0, l2TxNumberInBlock: 0 }; + const { message } = response!; + + // Decode the interop message + const decodedRequest = ethers.AbiCoder.defaultAbiCoder().decode([INTEROP_BUNDLE_ABI], '0x' + message.slice(2)); + let calls = []; + for (let i = 0; i < decodedRequest[0][1].length; i++) { + calls.push({ + to: decodedRequest[0][1][i][0], + from: decodedRequest[0][1][i][1], + value: decodedRequest[0][1][i][2], + data: decodedRequest[0][1][i][3] + }); + } + + let executionAddresses = []; + for (let i = 0; i < decodedRequest[0][2].length; i++) { + executionAddresses.push(decodedRequest[0][2][i]); + } + + const xl2Input = { + destinationChainId: decodedRequest[0][0], + calls: calls, + executionAddresses: executionAddresses, + cancellationAddress: decodedRequest[0][3] + }; + let output: Output = { + rawData: ethers.AbiCoder.defaultAbiCoder().encode([INTEROP_BUNDLE_ABI], [xl2Input]), + output: xl2Input, + l1BatchNumber: response.l1BatchNumber, + l2TxNumberInBlock: response.l2TxNumberInBlock + }; + return output; +} + +export async function getInteropTriggerData( + provider: zksync.Provider, + withdrawalHash: BytesLike, + index = 0 +): Promise { + // console.log("index", index) + const response = await tryGetMessageData(provider, withdrawalHash, index); + if (!response) return { rawData: null, output: null, l1BatchNumber: 0, l2TxNumberInBlock: 0 }; + const { message } = response!; + + // Decode the interop message + // console.log("trigger message", message) + // console.log("withdrawalHash", withdrawalHash) + + let decodedRequest = ethers.AbiCoder.defaultAbiCoder().decode([INTEROP_TRIGGER_ABI], '0x' + message.slice(2)); + + // console.log("decodedRequest", decodedRequest) + + let trigger = false; + if (decodedRequest[0][4]) { + if (decodedRequest[0][4][1] == 800n) { + trigger = true; + } + } + if (!trigger) { + throw new Error('Trigger is not found'); + } + + // let decodedCallRequest = ethers.AbiCoder.defaultAbiCoder().decode( + // [INTEROP_BUNDLE_ABI], + // '0x' + message.slice(2) + // ) + // console.log("trigger", trigger) + // console.log("decodedCallRequest", decodedRequest) + // console.log("decodedCallRequest[0][0]", decodedRequest[0][2]) + let output = { + destinationChainId: decodedRequest[0][0], + from: decodedRequest[0][1], + feeBundleHash: decodedRequest[0][2], + executionBundleHash: decodedRequest[0][3], + gasFields: { + gasLimit: decodedRequest[0][4][0], + gasPerPubdataByteLimit: decodedRequest[0][4][1], + refundRecipient: decodedRequest[0][4][2] + } + }; + // console.log("output", output) + + return { + rawData: ethers.AbiCoder.defaultAbiCoder().encode([INTEROP_TRIGGER_ABI], [output]), + output: output, + l1BatchNumber: response.l1BatchNumber, + l2TxNumberInBlock: response.l2TxNumberInBlock + }; +} + +// export async function getL2CanonicalTransactionData( +// provider: zksync.Provider, +// withdrawalHash: BytesLike, +// index = 0 +// ){ +// const response = await tryGetMessageData(provider, withdrawalHash, index); +// if (!response) return; +// const { message } = response!; + +// // Decode the interop message +// const decodedRequest = ethers.AbiCoder.defaultAbiCoder().decode( +// [BRIDGEHUB_L2_CANONICAL_TRANSACTION_ABI], +// '0x' + message.slice(2) +// ); + +// const xl2Input = { +// txType: decodedRequest[0][0], +// from: decodedRequest[0][1], +// to: decodedRequest[0][2], +// gasLimit: decodedRequest[0][3], +// gasPerPubdataByteLimit: decodedRequest[0][4], +// maxFeePerGas: decodedRequest[0][5], +// maxPriorityFeePerGas: decodedRequest[0][6], +// paymaster: decodedRequest[0][7], +// nonce: decodedRequest[0][8], +// value: decodedRequest[0][9], +// reserved: [ +// decodedRequest[0][10][0], +// decodedRequest[0][10][1], +// decodedRequest[0][10][2], +// decodedRequest[0][10][3] +// ], +// data: decodedRequest[0][11], +// signature: decodedRequest[0][12], +// factoryDeps: decodedRequest[0][13], +// paymasterInput: decodedRequest[0][14], +// reservedDynamic: decodedRequest[0][15] +// }; +// return { output: xl2Input, l1BatchNumber: response.l1BatchNumber, l2TxNumberInBlock: response.l2TxNumberInBlock }; +// } + +async function tryGetMessageData(provider: zksync.Provider, withdrawalHash: BytesLike, index = 0) { + let { l1BatchNumber, l2TxNumberInBlock, message } = { l1BatchNumber: 0, l2TxNumberInBlock: 0, message: '' }; + + try { + // console.log("Reading interop message"); + // `getFinalizeWithdrawalParamsWithoutProof` is only available for wallet instance but not provider + const sender_chain_utilityWallet = new zksync.Wallet(zksync.Wallet.createRandom().privateKey, provider); + const { + l1BatchNumber: l1BatchNumberRead, + l2TxNumberInBlock: l2TxNumberInBlockRead, + message: messageRead + } = await getFinalizeWithdrawalParamsWithoutProof(provider, withdrawalHash, index); + // console.log("Finished reading interop message"); + + l1BatchNumber = l1BatchNumberRead || 0; + l2TxNumberInBlock = l2TxNumberInBlockRead || 0; + message = messageRead || ''; + + if (!message) return; + } catch (e) { + console.log('Error reading interop message:', e); // note no error here, since we run out of txs sometime + return; + } + return { l1BatchNumber, l2TxNumberInBlock, message }; +} + +async function getFinalizeWithdrawalParamsWithoutProof( + provider: zksync.Provider, + withdrawalHash: BytesLike, + index = 0 +): Promise { + const { log, l1BatchTxId } = await getWithdrawalLog(provider, withdrawalHash, index); + // const {l2ToL1LogIndex} = await this._getWithdrawalL2ToL1Log( + // withdrawalHash, + // index + // ); + const sender = ethers.dataSlice(log.topics[1], 12); + + const message = ethers.AbiCoder.defaultAbiCoder().decode(['bytes'], log.data)[0]; + return { + l1BatchNumber: log.l1BatchNumber, + l2TxNumberInBlock: l1BatchTxId, + message, + sender + }; +} + +async function getWithdrawalLog(provider: zksync.Provider, withdrawalHash: BytesLike, index = 0) { + const hash = ethers.hexlify(withdrawalHash); + const receipt = await provider.getTransactionReceipt(hash); + if (!receipt) { + throw new Error('Transaction is not mined!'); + } + const log = receipt.logs.filter( + (log) => + zksync.utils.isAddressEq(log.address, L1_MESSENGER_ADDRESS) && + log.topics[0] === ethers.id('L1MessageSent(address,bytes32,bytes)') + )[index]; + + return { + log, + l1BatchTxId: receipt.l1BatchTxIndex + }; +} + +export interface FinalizeWithdrawalParamsWithoutProof { + /** The L2 batch number where the withdrawal was processed. */ + l1BatchNumber: number | null; + // /** The position in the L2 logs Merkle tree of the l2Log that was sent with the message. */ + // l2MessageIndex: number; + /** The L2 transaction number in the batch, in which the log was sent. */ + l2TxNumberInBlock: number | null; + /** The L2 withdraw data, stored in an L2 -> L1 message. */ + message: any; + /** The L2 address which sent the log. */ + sender: string; + // /** The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization. */ + // proof: string[]; +} + +// // Construct log for Merkle proof +// const log = { +// l2ShardId: 0, +// isService: true, +// txNumberInBatch: l2TxNumberInBlock, +// sender: L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, +// key: ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['address'], [interop1_wallet.address])), +// value: ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode(['bytes'], [message])) +// }; + +// const leafHash = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode([L2_LOG_STRING], [log])); + +// const proof1 = +// ethers.ZeroHash + +// ethers.AbiCoder.defaultAbiCoder() +// .encode( +// ['uint256', 'uint256', 'uint256', 'bytes32'], +// [(await sender_chain_provider.getNetwork()).chainId, l1BatchNumber, l2TxNumberInBlock, leafHash] +// ) +// .slice(2); + +// const interopTxAsCanonicalTx = { +// txType: 253n, +// from: interopTx.from, +// to: interopTx.to, +// gasLimit: interopTx.gasLimit, +// gasPerPubdataByteLimit: 50000n, +// maxFeePerGas: interopTx.maxFeePerGas, +// maxPriorityFeePerGas: 0, +// paymaster: interopTx.customData.paymaster_params.paymaster, +// nonce: interopTx.nonce, +// value: interopTx.value, +// reserved: [interopTx.customData.toMint, interopTx.customData.refundRecipient, '0x00', '0x00'], +// data: interopTx.data, +// signature: '0x', +// factoryDeps: [], +// paymasterInput: '0x', +// reservedDynamic: proof1 +// }; +// const encodedTx = ethers.AbiCoder.defaultAbiCoder().encode( +// [BRIDGEHUB_L2_CANONICAL_TRANSACTION_ABI], +// [interopTxAsCanonicalTx] +// ); +// const interopTxHash = ethers.keccak256(ethers.getBytes(encodedTx)); +// console.log('interopTxHash', interopTxHash); diff --git a/core/tests/ts-integration/src/test-master.ts b/core/tests/ts-integration/src/test-master.ts index d2be3237a7fa..06360bafa3b3 100644 --- a/core/tests/ts-integration/src/test-master.ts +++ b/core/tests/ts-integration/src/test-master.ts @@ -1,4 +1,5 @@ -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { TestEnvironment, TestContext } from './types'; import { claimEtherBack } from './context-owner'; diff --git a/core/tests/ts-integration/src/types.ts b/core/tests/ts-integration/src/types.ts index c513480c1b41..1ee2cca93887 100644 --- a/core/tests/ts-integration/src/types.ts +++ b/core/tests/ts-integration/src/types.ts @@ -17,6 +17,8 @@ export interface Token { decimals: bigint; l1Address: string; l2Address: string; + l2AddressSecondChain?: string; + assetId?: string; } /** diff --git a/core/tests/ts-integration/tests/api/contract-verification.test.ts b/core/tests/ts-integration/tests/api/contract-verification.test.ts index 519991ea9dca..f136c73cbb0a 100644 --- a/core/tests/ts-integration/tests/api/contract-verification.test.ts +++ b/core/tests/ts-integration/tests/api/contract-verification.test.ts @@ -1,5 +1,6 @@ import { TestMaster } from '../../src'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import fetch from 'node-fetch'; import fs from 'fs'; diff --git a/core/tests/ts-integration/tests/api/debug.test.ts b/core/tests/ts-integration/tests/api/debug.test.ts index 2af18c8438b8..094c0efd4238 100644 --- a/core/tests/ts-integration/tests/api/debug.test.ts +++ b/core/tests/ts-integration/tests/api/debug.test.ts @@ -5,7 +5,8 @@ import { TestMaster } from '../../src'; import { Token } from '../../src/types'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import { ethers } from 'ethers'; import { BOOTLOADER_FORMAL_ADDRESS } from 'zksync-ethers/build/utils'; import fs from 'fs'; diff --git a/core/tests/ts-integration/tests/api/web3.test.ts b/core/tests/ts-integration/tests/api/web3.test.ts index 00b856cea124..7e31cee891b4 100644 --- a/core/tests/ts-integration/tests/api/web3.test.ts +++ b/core/tests/ts-integration/tests/api/web3.test.ts @@ -2,7 +2,8 @@ * This suite contains tests for the Web3 API compatibility and ZKsync-specific extensions. */ import { TestMaster } from '../../src'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import { types } from 'zksync-ethers'; import * as ethers from 'ethers'; import { anyTransaction, deployContract, getTestContract, waitForNewL1Batch } from '../../src/helpers'; diff --git a/core/tests/ts-integration/tests/base-token.test.ts b/core/tests/ts-integration/tests/base-token.test.ts index 7f7974205dcd..b8c7e464afad 100644 --- a/core/tests/ts-integration/tests/base-token.test.ts +++ b/core/tests/ts-integration/tests/base-token.test.ts @@ -5,7 +5,8 @@ import { TestMaster } from '../src'; import { Token } from '../src/types'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { scaledGasPrice, waitForBlockToBeFinalizedOnL1 } from '../src/helpers'; diff --git a/core/tests/ts-integration/tests/contracts.test.ts b/core/tests/ts-integration/tests/contracts.test.ts index b6b9672750b2..544b3f3b7530 100644 --- a/core/tests/ts-integration/tests/contracts.test.ts +++ b/core/tests/ts-integration/tests/contracts.test.ts @@ -11,7 +11,8 @@ import { deployContract, getTestContract, scaledGasPrice, waitForNewL1Batch } fr import { shouldOnlyTakeFee } from '../src/modifiers/balance-checker'; import * as ethers from 'ethers'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as elliptic from 'elliptic'; import { RetryProvider } from '../src/retry-provider'; diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 46ddba95323a..717c6e908c1c 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -4,7 +4,8 @@ import { TestMaster } from '../src'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { deployContract, getTestContract } from '../src/helpers'; import { ERC20_PER_ACCOUNT, L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; diff --git a/core/tests/ts-integration/tests/erc20.test.ts b/core/tests/ts-integration/tests/erc20.test.ts index 382c625ac700..8c2a3a82d0ff 100644 --- a/core/tests/ts-integration/tests/erc20.test.ts +++ b/core/tests/ts-integration/tests/erc20.test.ts @@ -6,7 +6,8 @@ import { TestMaster } from '../src'; import { Token } from '../src/types'; import { shouldChangeTokenBalances, shouldOnlyTakeFee } from '../src/modifiers/balance-checker'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { scaledGasPrice, waitForBlockToBeFinalizedOnL1 } from '../src/helpers'; import { L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; diff --git a/core/tests/ts-integration/tests/ether.test.ts b/core/tests/ts-integration/tests/ether.test.ts index abc9237025ab..45c4919f5954 100644 --- a/core/tests/ts-integration/tests/ether.test.ts +++ b/core/tests/ts-integration/tests/ether.test.ts @@ -10,7 +10,8 @@ import { } from '../src/modifiers/balance-checker'; import { checkReceipt } from '../src/modifiers/receipt-check'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import { scaledGasPrice, waitForBlockToBeFinalizedOnL1 } from '../src/helpers'; import { ethers } from 'ethers'; diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 92bbfff1965c..9bde0e2ba9a7 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -12,7 +12,8 @@ import fs from 'node:fs/promises'; import { TestContextOwner, TestMaster } from '../src'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; diff --git a/core/tests/ts-integration/tests/interop.test.ts b/core/tests/ts-integration/tests/interop.test.ts new file mode 100644 index 000000000000..1b07ab77010e --- /dev/null +++ b/core/tests/ts-integration/tests/interop.test.ts @@ -0,0 +1,1030 @@ +/** + * This suite contains tests checking interop behavior. + */ + +import * as fs from 'fs'; + +import { TestMaster } from '../src/index'; +import { Token } from '../src/types'; + +import * as zksync from 'zksync-ethers-interop-support'; +import * as ethers from 'ethers'; +import { Wallet } from 'ethers'; +import { scaledGasPrice, deployContract, waitForBlockToBeFinalizedOnL1 } from '../src/helpers'; + +import { + L2_ASSET_ROUTER_ADDRESS, + L2_BRIDGEHUB_ADDRESS, + L2_NATIVE_TOKEN_VAULT_ADDRESS, + L2_INTEROP_HANDLER_ADDRESS, + L2_INTEROP_CENTER_ADDRESS, + REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, + BRIDGEHUB_L2_CANONICAL_TRANSACTION_ABI, + ETH_ADDRESS_IN_CONTRACTS, + L2_LOG_STRING, + ARTIFACTS_PATH, + INTEROP_CALL_ABI +} from '../src/constants'; +import { RetryProvider } from '../src/retry-provider'; + +import { getInteropTriggerData, getInteropBundleData } from '../src/temp-sdk'; + +// Read contract artifacts +function readContract(path: string, fileName: string, contractName?: string) { + contractName = contractName || fileName; + return JSON.parse(fs.readFileSync(`${path}/${fileName}.sol/${contractName}.json`, { encoding: 'utf-8' })); +} + +const ArtifactBridgeHub = readContract(`${ARTIFACTS_PATH}bridgehub`, 'Bridgehub'); +const ArtifactInteropCenter = readContract(`${ARTIFACTS_PATH}bridgehub`, 'InteropCenter'); +const ArtifactInteropHandler = readContract(`${ARTIFACTS_PATH}bridgehub`, 'InteropHandler'); +const ArtifactNativeTokenVault = readContract(`${ARTIFACTS_PATH}bridge/ntv`, 'L2NativeTokenVault'); +const ArtifactMintableERC20 = readContract( + '../../../contracts/l1-contracts/artifacts-zk/contracts/dev-contracts', + 'TestnetERC20Token' +); +const l1AssetRouterInterface = readContract(`${ARTIFACTS_PATH}/bridge/asset-router`, 'L1AssetRouter').abi; +const ArtifactSwap = readContract('./artifacts-zk/contracts/Swap', 'Swap'); + +const richPk = '0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110'; + +// Constants +const INTEROP_TX_TYPE = 253; + +describe('Interop checks', () => { + let testMaster: TestMaster; + + // L1 Variables + let l1_provider: ethers.Provider; + let l1_wallet: zksync.Wallet; + let l1EthersWallet: Wallet; + let veryRichWallet: zksync.Wallet; + + let tokenA_details: Token = { + name: 'Token A', + symbol: 'AA', + decimals: 18n, + l1Address: '', + l2Address: '', + l2AddressSecondChain: '' + }; + let tokenB_details: Token = { + name: 'Token B', + symbol: 'BB', + decimals: 18n, + l1Address: '', + l2Address: '', + l2AddressSecondChain: '' + }; + + // Common Variables + const timeout = 10000; + + // Interop1 (Main Chain) Variables + let interop1_provider: zksync.Provider; + let interop1_wallet: zksync.Wallet; + let interop1_rich_wallet: zksync.Wallet; + let interop1_bridgehub_contract: zksync.Contract; + let interop1_interop_center_contract: zksync.Contract; + let interop2_interop_handler: zksync.Contract; + let interop1_nativeTokenVault_contract: zksync.Contract; + let interop1_tokenA_contract: zksync.Contract; + let aliased_interop1_wallet_address: string; + + // Interop2 (Second Chain) Variables + let interop2_provider: zksync.Provider; + let interop2_wallet: zksync.Wallet; + let interop2_rich_wallet: zksync.Wallet; + let interop2_nativeTokenVault_contract: zksync.Contract; + let interop2_swap_contract: zksync.Contract; + let interop2_tokenB_contract: zksync.Contract; + + const swapAmount = ethers.parseEther('0.1'); + const mintValue = ethers.parseEther('0.2'); + const bridgeBackAmount = ethers.parseEther('0.2'); + + beforeAll(async () => { + testMaster = TestMaster.getInstance(__filename); + const test_wallet_pk = testMaster.newEmptyAccount().privateKey; + const mainAccount = testMaster.mainAccount(); + + // Initialize the providers + l1_provider = mainAccount.providerL1!; + interop1_provider = mainAccount.provider; + // Setup Interop1 Provider and Wallet + l1_wallet = new zksync.Wallet(mainAccount.privateKey, interop1_provider, l1_provider); + veryRichWallet = new zksync.Wallet(richPk, interop1_provider, l1_provider); + l1EthersWallet = new Wallet(mainAccount.privateKey, l1_provider); + + // Initialize Test Master and L1 Wallet + interop1_wallet = new zksync.Wallet(test_wallet_pk, interop1_provider, l1_provider); + interop1_rich_wallet = new zksync.Wallet(mainAccount.privateKey, interop1_provider, l1_provider); + console.log('PK', test_wallet_pk); + + // Setup Interop2 Provider and Wallet + interop2_provider = new RetryProvider( + { url: 'http://localhost:3050', timeout: 1200 * 1000 }, + undefined, + testMaster.reporter + ); + interop2_wallet = new zksync.Wallet(test_wallet_pk, interop2_provider, l1_provider); + interop2_rich_wallet = new zksync.Wallet(mainAccount.privateKey, interop2_provider, l1_provider); + + // Initialize Contracts on Interop1 + interop1_bridgehub_contract = new zksync.Contract(L2_BRIDGEHUB_ADDRESS, ArtifactBridgeHub.abi, interop1_wallet); + interop1_interop_center_contract = new zksync.Contract( + L2_INTEROP_CENTER_ADDRESS, + ArtifactInteropCenter.abi, + interop1_wallet + ); + interop2_interop_handler = new zksync.Contract( + L2_INTEROP_HANDLER_ADDRESS, + ArtifactInteropHandler.abi, + interop2_wallet + ); + interop1_nativeTokenVault_contract = new zksync.Contract( + L2_NATIVE_TOKEN_VAULT_ADDRESS, + ArtifactNativeTokenVault.abi, + interop1_wallet + ); + + // Initialize Contracts on Interop2 + interop2_nativeTokenVault_contract = new zksync.Contract( + L2_NATIVE_TOKEN_VAULT_ADDRESS, + ArtifactNativeTokenVault.abi, + interop2_wallet + ); + + console.log(`Test wallet 1 address: ${interop1_wallet.address}`); + console.log(`Test wallet 2 address: ${interop1_wallet.address}`); + console.log( + `[rich wallet] l1_wallet address: ${l1_wallet.address} with ${ethers.formatEther( + await l1_provider.getBalance(l1_wallet.address) + )} ETH` + ); + console.log('--------------------'); + + await ( + await veryRichWallet._signerL1!().sendTransaction({ + to: interop1_rich_wallet.address, + value: ethers.parseEther('100') //amount*10n + }) + ).wait(); + + await ( + await veryRichWallet._signerL1!().sendTransaction({ + to: interop2_rich_wallet.address, + value: ethers.parseEther('100') //amount*10n + }) + ).wait(); + + await ( + await veryRichWallet._signerL1!().sendTransaction({ + to: interop1_wallet.address, + value: ethers.parseEther('100') //amount*10n + }) + ).wait(); + + await ( + await veryRichWallet._signerL1!().sendTransaction({ + to: interop2_wallet.address, + value: ethers.parseEther('100') //amount*10n + }) + ).wait(); + + aliased_interop1_wallet_address = await interop2_interop_handler.aliasAccount(interop1_wallet.address); + console.log('aliased address', aliased_interop1_wallet_address); + }); + + test('Can perform an ETH deposit', async () => { + // Fund accounts + const gasPrice = await scaledGasPrice(interop1_rich_wallet); + const fundAmount = ethers.parseEther('10'); + console.log('Funding test wallet at interop1'); + await ( + await interop1_rich_wallet.deposit({ + token: ETH_ADDRESS_IN_CONTRACTS, + amount: fundAmount * 10n, + to: interop1_wallet.address, + approveERC20: true, + approveBaseERC20: true, + approveOverrides: { gasPrice }, + overrides: { gasPrice } + }) + ).wait(); + console.log('Funding test wallet at interop2'); + await ( + await interop2_rich_wallet.deposit({ + token: ETH_ADDRESS_IN_CONTRACTS, + amount: fundAmount * 10n, + to: interop2_wallet.address, + approveERC20: true, + approveBaseERC20: true, + approveOverrides: { gasPrice }, + overrides: { gasPrice } + }) + ).wait(); + console.log('Test wallet funded'); + }); + + test.skip('Can perform an ETH interop', async () => { + // Fund accounts + const gasPrice = await scaledGasPrice(interop1_rich_wallet); + const fundAmount = ethers.parseEther('10'); + console.log('Funding test wallet at interop1'); + printBalances('before eth value interop'); + + // Send Transfer Transaction + console.log('interop1_wallet.privateKey', interop1_wallet.privateKey); + const tx = await from_interop1_requestInterop( + [ + { + directCall: true, + to: interop1_wallet.address, + from: ethers.ZeroAddress, + data: '0x', + value: '0x' + mintValue.toString(16), + requestedInteropCallValue: '0x' + mintValue.toString(16) + } + ], + //feeStarters + [ + // getL2TokenTransferIndirectStarter(), + { + directCall: false, + to: ethers.ZeroAddress, + from: L2_ASSET_ROUTER_ADDRESS, + data: getTokenTransferSecondBridgeData( + tokenA_details.assetId!, + swapAmount, + interop1_wallet.address + ), + value: '0x0', + requestedInteropCallValue: '0x0' + } + ], + { + gasLimit: 30000000, + gasPerPubdataByteLimit: 1000, + refundRecipient: interop1_wallet.address + } + ); + + console.log('tx', tx); + await tx.wait(); + + await delay(timeout); + + // Read and broadcast the interop transaction from Interop1 to Interop2 + await readAndBroadcastInteropTx(tx.hash, interop1_provider, interop2_provider); + await delay(timeout); + + printBalances('after eth value interop'); + + console.log('Test wallet funded'); + }); + + test('Can deploy token contracts', async () => { + // Deploy token A on interop1 and register + console.log('Deploying token A on Interop1'); + const interop1_tokenA_contract_deployment = await deployContract(interop1_wallet, ArtifactMintableERC20, [ + tokenA_details.name, + tokenA_details.symbol, + tokenA_details.decimals + ]); + tokenA_details.l2Address = await interop1_tokenA_contract_deployment.getAddress(); + console.log('Registering token A on Interop1'); + await (await interop1_nativeTokenVault_contract.registerToken(tokenA_details.l2Address)).wait(); + await (await interop1_tokenA_contract_deployment.mint(await interop1_wallet.getAddress(), 1000)).wait(); + await (await interop1_tokenA_contract_deployment.approve(L2_NATIVE_TOKEN_VAULT_ADDRESS, 1000)).wait(); + console.log('Token A registered on Interop1'); + tokenA_details.assetId = await interop1_nativeTokenVault_contract.assetId(tokenA_details.l2Address); + tokenA_details.l2AddressSecondChain = await interop2_nativeTokenVault_contract.tokenAddress( + tokenA_details.assetId + ); + interop1_tokenA_contract = new zksync.Contract( + tokenA_details.l2Address, + ArtifactMintableERC20.abi, + interop1_wallet + ); + console.log('Token A info:', tokenA_details); + + // Deploy token B on interop2 and register + console.log('Deploying token B on Interop2'); + const interop2_tokenB_contract_deployment = await deployContract(interop2_wallet, ArtifactMintableERC20, [ + tokenB_details.name, + tokenB_details.symbol, + tokenB_details.decimals + ]); + tokenB_details.l2AddressSecondChain = await interop2_tokenB_contract_deployment.getAddress(); + await ( + await interop2_tokenB_contract_deployment.mint(await interop1_wallet.getAddress(), ethers.parseEther('100')) + ).wait(); + await ( + await interop2_tokenB_contract_deployment.approve(L2_NATIVE_TOKEN_VAULT_ADDRESS, ethers.parseEther('100')) + ).wait(); + console.log('Registering token B on Interop2'); + await (await interop2_nativeTokenVault_contract.registerToken(tokenB_details.l2AddressSecondChain)).wait(); + console.log('Token B registered on Interop2'); + // await delay(timeout); + tokenB_details.assetId = await interop2_nativeTokenVault_contract.assetId(tokenB_details.l2AddressSecondChain); + tokenB_details.l2Address = await interop1_nativeTokenVault_contract.tokenAddress(tokenB_details.assetId); + interop2_tokenB_contract = new zksync.Contract( + tokenB_details.l2AddressSecondChain, + ArtifactMintableERC20.abi, + interop2_wallet + ); + console.log('Token B info:', tokenB_details); + }); + + test('Withdraw and deposit tokens via L1', async () => { + const bridgeContracts = await interop1_wallet.getL1BridgeContracts(); + const assetRouter = bridgeContracts.shared; + // console.log("assetRouter", assetRouter) + const l1AssetRouter = new ethers.Contract( + await assetRouter.getAddress(), + l1AssetRouterInterface, + l1EthersWallet + ); + // console.log("ntv", await l1AssetRouter.) + const l1NativeTokenVault = new ethers.Contract( + await l1AssetRouter.nativeTokenVault(), + ArtifactNativeTokenVault.abi, + l1EthersWallet + ); + + const withdrawA = interop1_wallet.withdraw({ + token: tokenA_details.l2Address, + amount: 100 + }); + await expect(withdrawA).toBeAccepted(); + const withdrawalATx = await withdrawA; + const l2TxAReceipt = await interop1_wallet.provider.getTransactionReceipt(withdrawalATx.hash); + await withdrawalATx.waitFinalize(); + await waitForBlockToBeFinalizedOnL1(interop1_wallet, l2TxAReceipt!.blockNumber); + + await interop1_wallet.finalizeWithdrawalParams(withdrawalATx.hash); // kl todo finalize the Withdrawals with the params here. Alternatively do in the SDK. + await expect(interop1_rich_wallet.finalizeWithdrawal(withdrawalATx.hash)).toBeAccepted(); + + const withdrawB = interop2_wallet.withdraw({ + token: tokenB_details.l2AddressSecondChain!, + amount: 100 + }); + + await expect(withdrawB).toBeAccepted(); + const withdrawBTx = await withdrawB; + const l2TxBReceipt = await interop2_wallet.provider.getTransactionReceipt(withdrawBTx.hash); + await withdrawBTx.waitFinalize(); + await waitForBlockToBeFinalizedOnL1(interop2_wallet, l2TxBReceipt!.blockNumber); + + await interop2_wallet.finalizeWithdrawalParams(withdrawBTx.hash); // kl todo finalize the Withdrawals with the params here. Alternatively do in the SDK. + await expect(interop2_rich_wallet.finalizeWithdrawal(withdrawBTx.hash)).toBeAccepted(); + + tokenA_details.l1Address = await l1NativeTokenVault.tokenAddress(tokenA_details.assetId); + tokenB_details.l1Address = await l1NativeTokenVault.tokenAddress(tokenB_details.assetId); + + await expect( + interop1_wallet.deposit({ + token: tokenB_details.l1Address, + amount: 50, + approveERC20: true + }) + ).toBeAccepted(); + + await expect( + interop2_wallet.deposit({ + token: tokenA_details.l1Address, + amount: 50, + approveERC20: true + }) + ).toBeAccepted(); + + tokenA_details.l2AddressSecondChain = await interop2_nativeTokenVault_contract.tokenAddress( + tokenA_details.assetId + ); + tokenB_details.l2Address = await interop1_nativeTokenVault_contract.tokenAddress(tokenB_details.assetId); + + console.log(tokenA_details); + console.log(tokenB_details); + }); + + test('Deploy swap contract', async () => { + // Deploy Swap Contracts on Interop2 + console.log('Deploying Swap Contract on Interop2'); + const interop2_swap_contract_deployment = await deployContract(interop2_wallet, ArtifactSwap, [ + tokenA_details.l2AddressSecondChain!, + tokenB_details.l2AddressSecondChain! + ]); + const interop2_swap_contract_address = await interop2_swap_contract_deployment.getAddress(); + interop2_swap_contract = new zksync.Contract(interop2_swap_contract_address, ArtifactSwap.abi, interop2_wallet); + console.log(`Swap Contract deployed to: ${interop2_swap_contract_address}`); + + // Mint token B on Interop2 for swap contract + console.log('Minting token B on Interop2 for Swap Contract...'); + await ( + await interop2_tokenB_contract.mint(await interop2_swap_contract.getAddress(), ethers.parseEther('1000')) + ).wait(); + console.log( + `Swap contract token B balance: ${ethers.formatEther( + await getTokenBalance({ + provider: interop2_provider, + tokenAddress: tokenB_details.l2AddressSecondChain!, + address: interop2_swap_contract_address + }) + )} BB` + ); + + // Mint token A on Interop1 for test wallet + console.log('Minting token A on Interop1 for test wallet...'); + await (await interop1_tokenA_contract.mint(interop1_wallet.address, ethers.parseEther('500'))).wait(); + console.log('[SETUP COMPLETED]'); + }); + + // test('Can transfer token A from Interop1 to Interop2', async () => { + // await printBalances('before token transfer'); + // // Send Transfer Transaction + // await from_interop1_transfer_tokenA(); + // await delay(timeout); + // await printBalances('after token transfer'); + // // await delay(1); + // }); + + test('Can perform request interop new interface', async () => { + // Fund accounts + const gasPrice = await scaledGasPrice(interop1_rich_wallet); + const fundAmount = ethers.parseEther('10'); + console.log('Cross chain swap and additional calls...'); + await printBalances('before request interop'); + + await (await interop1_tokenA_contract.approve(L2_NATIVE_TOKEN_VAULT_ADDRESS, swapAmount)).wait(); + + // Send Transfer Transaction + console.log('fundAmount', fundAmount); + console.log('interop1_wallet.privateKey', interop1_wallet.privateKey); + const tx = await from_interop1_requestInterop( + [ + { + directCall: true, + to: aliased_interop1_wallet_address, + from: ethers.ZeroAddress, + data: '0x', + value: '0x' + mintValue.toString(16), + requestedInteropCallValue: '0x' + mintValue.toString(16) + } + ], + //feeStarters + [ + // getL2TokenTransferIndirectStarter(), + { + directCall: false, + to: ethers.ZeroAddress, + from: L2_ASSET_ROUTER_ADDRESS, + data: getTokenTransferSecondBridgeData( + tokenA_details.assetId!, + swapAmount, + aliased_interop1_wallet_address + ), + value: '0x0', + requestedInteropCallValue: '0x0' + }, + // getCrossChainSwapApprovalDirectStarter(), + { + directCall: true, + to: tokenA_details.l2AddressSecondChain!, + from: ethers.ZeroAddress, + data: interop1_tokenA_contract.interface.encodeFunctionData('approve', [ + await interop2_swap_contract.getAddress(), + swapAmount + ]), + value: '0x0', + requestedInteropCallValue: '0x0' + }, + // getCrossChainSwapDirectStarter(), + { + directCall: true, + to: await interop2_swap_contract.getAddress(), + from: ethers.ZeroAddress, + data: interop2_swap_contract.interface.encodeFunctionData('swap', [swapAmount]), + value: '0x0', + requestedInteropCallValue: '0x0' + }, + // getCrossChainNtvApprovalDirectStarter(), + { + directCall: true, + to: tokenB_details.l2AddressSecondChain!, + from: ethers.ZeroAddress, + data: interop1_tokenA_contract.interface.encodeFunctionData('approve', [ + L2_NATIVE_TOKEN_VAULT_ADDRESS, + swapAmount * 2n + ]), + value: '0x0', + requestedInteropCallValue: '0x0' + }, + // getTransferBackTokenDirectStarter() + { + directCall: true, + to: L2_BRIDGEHUB_ADDRESS, + from: ethers.ZeroAddress, + data: await getRequestL2TransactionTwoBridgesData( + ( + await interop1_wallet.provider.getNetwork() + ).chainId, + mintValue, + 0n, + getTokenTransferSecondBridgeData(tokenB_details.assetId!, swapAmount, interop1_wallet.address), + interop1_wallet.address + ), + value: '0x' + mintValue.toString(16), // note in two bridges this is * 2n , because we pay for gas as well. This cleans it up. + requestedInteropCallValue: '0x' + mintValue.toString(16) + } + ], + { + gasLimit: 30000000, + gasPerPubdataByteLimit: 1000, + refundRecipient: interop1_wallet.address + } + ); + + // console.log("tx", tx) + await tx.wait(); + + await delay(timeout); + + // Read and broadcast the interop transaction from Interop1 to Interop2 + await readAndBroadcastInteropTx(tx.hash, interop1_provider, interop2_provider); + await delay(timeout); + + await printBalances('after request interop'); + }); + + /** + * Sends a transfer transaction from Interop1 to Interop2. + */ + async function from_interop1_transfer_tokenA() { + const amount = ethers.parseEther('0.1'); + const mintValue = ethers.parseEther('0.2'); + const bridgeCalldata = getTokenTransferSecondBridgeData( + tokenA_details.assetId!, + amount, + interop1_wallet.address + ); + + await (await interop1_tokenA_contract.approve(L2_NATIVE_TOKEN_VAULT_ADDRESS, amount)).wait(); + const tx = await from_interop1_requestL2TransactionTwoBridges(mintValue, bridgeCalldata); + await tx.wait(); + + await delay(timeout); + + await readAndBroadcastInteropTx(tx.hash, interop1_provider, interop2_provider); + } + + // /** + // * Sends an approve transaction from Interop1 to Interop2. + // */ + // async function from_interop1_approveSwapAllowance() { + // const amount = ethers.parseEther('0.1'); + // const mintValue = ethers.parseEther('0.2'); + + // // Use the token contract on Interop2 (Second Chain) + // const l2Calldata = interop1_tokenA_contract.interface.encodeFunctionData('approve', [ + // await interop2_swap_contract.getAddress(), + // amount + // ]); + + // // Create an interop transaction from Interop1 to Interop2 + // const tx = await from_interop1_requestL2TransactionDirect( + // mintValue, + // tokenA_details.l2AddressSecondChain!, + // BigInt(0), + // l2Calldata + // ); + // await tx.wait(); + + // await delay(timeout); + + // // Read and broadcast the interop transaction from Interop1 to Interop2 + // await readAndBroadcastInteropTx(tx.hash, interop1_provider, interop2_provider); + // } + + // /** + // * Sends a swap transaction from Interop1 to Interop2. + // */ + // async function from_interop1_swap_a_to_b() { + // const amount = ethers.parseEther('0.1'); + // const mintValue = ethers.parseEther('0.2'); + + // // Prepare calldata using the Swap contract on Interop2 + // const l2Calldata = interop2_swap_contract.interface.encodeFunctionData('swap', [amount]); + + // // Create interop transaction from Interop1 to Interop2 + // const tx = await from_interop1_requestL2TransactionDirect( + // mintValue, + // await interop2_swap_contract.getAddress(), + // BigInt(0), + // l2Calldata + // ); + // await readAndBroadcastInteropTx(tx.hash, interop1_provider, interop2_provider); + // } + + // /** + // * Sends a transfer transaction from Interop2 to Interop1. + // */ + // async function from_interop2_transfer_tokenB() { + // const amount = ethers.parseEther('0.2'); // swap ratio is 1:2 (A:B) + // const mintValue = ethers.parseEther('0.2'); + // const bridgeCalldata = getTokenTransferSecondBridgeData(tokenB_details.assetId!, amount, interop1_wallet.address); + + // const input = { + // chainId: (await interop1_provider.getNetwork()).chainId, + // mintValue, + // l2Value: 0, + // l2GasLimit: 30000000, + // l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + // refundRecipient: interop1_wallet.address, + // secondBridgeAddress: L2_ASSET_ROUTER_ADDRESS, + // secondBridgeValue: 0, + // secondBridgeCalldata: bridgeCalldata + // }; + // const l2Calldata = interop1_bridgehub_contract.interface.encodeFunctionData('requestL2TransactionTwoBridges', [input]); + + // // Create interop transaction from Interop1 to Interop2 + // const tx = await from_interop1_requestL2TransactionDirect( + // mintValue * 2n, + // L2_BRIDGEHUB_ADDRESS, + // mintValue, + // l2Calldata + // ); + // await readAndBroadcastInteropTx(tx.hash, interop1_provider, interop2_provider); + // } + + /** + * Requests an L2 transaction involving two bridges on Interop1. + * @param mintValue - The value to mint. + * @param secondBridgeCalldata - The calldata for the second bridge. + * @returns The transaction response. + */ + async function from_interop1_requestL2TransactionTwoBridges(mintValue: bigint, secondBridgeCalldata: string) { + console.log('requestL2TransactionTwoBridges from Interop1 to Interop2'); + const input = { + chainId: (await interop2_provider.getNetwork()).chainId, + mintValue, + l2Value: 0, + l2GasLimit: 30000000, + l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + refundRecipient: interop1_wallet.address, + secondBridgeAddress: L2_ASSET_ROUTER_ADDRESS, + secondBridgeValue: 0, + secondBridgeCalldata + }; + + const request = await interop1_bridgehub_contract.requestL2TransactionTwoBridges.populateTransaction(input); + request.value = mintValue; + request.from = interop1_wallet.address; + + const tx = await interop1_bridgehub_contract.requestL2TransactionTwoBridges(input, { + value: request.value, + gasLimit: 30000000 + }); + await tx.wait(); + return tx; + } + + /** + * Requests a direct L2 transaction on Interop1. + * @param mintValue - The value to mint. + * @param l2Contract - The target L2 contract address. + * @param l2Value - The value to send with the transaction. + * @param l2Calldata - The calldata for the transaction. + * @returns The transaction response. + */ + async function from_interop1_requestL2TransactionDirect( + mintValue: bigint, + l2Contract: string, + l2Value: bigint, + l2Calldata: string + ) { + const input = { + chainId: (await interop2_provider.getNetwork()).chainId, + mintValue, + l2Contract, + l2Value, + l2Calldata, + l2GasLimit: 600000000, + l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + factoryDeps: [], + refundRecipient: interop1_wallet.address + }; + + const request = await interop1_bridgehub_contract.requestL2TransactionDirect.populateTransaction(input); + request.value = mintValue; + request.from = interop1_wallet.address; + + const tx = await interop1_bridgehub_contract.requestL2TransactionDirect(input, { + value: request.value, + gasLimit: 30000000 + }); + + await tx.wait(); + return tx; + } + + interface InteropCallStarter { + directCall: boolean; + to: string; + from: string; + data: string; + value: string; + // The value that is requested for the interop call. + // This has to be known beforehand, as the funds in the interop call belong to the user. + // This is because we cannot guarantee atomicity of xL2 txs (just the atomicity of calls on the destination chain) + // So contracts cannot send their own value, only stamp the value that belongs to the user. + requestedInteropCallValue: string; + } + + interface GasFields { + gasLimit: number; + gasPerPubdataByteLimit: number; + refundRecipient: string; + } + + /** + * Requests a direct L2 transaction on Interop1. + * @param mintValue - The value to mint. + * @param l2Contract - The target L2 contract address. + * @param l2Value - The value to send with the transaction. + * @param l2Calldata - The calldata for the transaction. + * @returns The transaction response. + */ + async function from_interop1_requestInterop( + feePaymentCallStarters: InteropCallStarter[], + executionCallStarters: InteropCallStarter[], + gasFields: GasFields + ) { + const input = [ + // destinationChainId: + (await interop2_provider.getNetwork()).chainId.toString(), + // feePaymentCallStarters: + feePaymentCallStarters, + // executionCallStarters: + executionCallStarters, + // gasFields: + { + gasLimit: 600000000, + gasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + refundRecipient: interop1_wallet.address + } + // refundRecipient: interop1_wallet.address + ]; + + // console.log("input", input) + // console.log("interop1_interop_center_contract", interop1_interop_center_contract.interface.fragments[32]) + const request = await interop1_interop_center_contract.requestInterop.populateTransaction(...input); + request.value = + mintValue + + BigInt( + executionCallStarters.reduce( + (acc: bigint, curr: InteropCallStarter) => acc + BigInt(curr.requestedInteropCallValue), + 0n + ) + ); + request.from = interop1_wallet.address; + // console.log("request", request) + + const tx = await interop1_interop_center_contract.requestInterop(...input, { + value: '0x' + request.value.toString(16), + gasLimit: 30000000 + }); + + await tx.wait(); + return tx; + } + + function getTokenTransferSecondBridgeData(assetId: string, amount: bigint, recipient: string) { + return ethers.concat([ + '0x01', + new ethers.AbiCoder().encode( + ['bytes32', 'bytes'], + [assetId, new ethers.AbiCoder().encode(['uint256', 'address'], [amount, recipient])] + ) + ]); + } + + function getRequestL2TransactionTwoBridgesData( + chainId: bigint, + mintValue: bigint, + l2Value: bigint, + secondBridgeCalldata: string, + refundRecipient: string + ) { + return interop1_bridgehub_contract.interface.encodeFunctionData('requestL2TransactionTwoBridges', [ + { + chainId: chainId.toString(), + mintValue, + l2Value, + l2GasLimit: 30000000, + l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + refundRecipient: refundRecipient, + secondBridgeAddress: L2_ASSET_ROUTER_ADDRESS, + secondBridgeValue: 0, + secondBridgeCalldata + } + ]); + } + + // function getRequestL2TransactionDirectData( + // mintValue: bigint, + // l2Contract: string, + // l2Value: bigint, + // l2Calldata: string, + + // ) { + // return interop1_bridgehub_contract.interface.encodeFunctionData("requestL2TransactionDirect", [{ + // chainId: interop2_chain.id.toString(), + // mintValue, + // l2Contract, + // l2Value, + // l2Calldata, + // l2GasLimit: 30000000, + // l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + // factoryDeps: [], + // refundRecipient: interop1_zkAccount.address, + // }]); + // } + + /** + * Reads and broadcasts an interop transaction between Interop1 and Interop2. + * @param tx - The original transaction response. + * @param sender_chain_provider - The sender wallet (Interop1). + * @param receiver_chain_provider - The receiver wallet (Interop2). + */ + async function readAndBroadcastInteropTx( + txHash: string, + sender_chain_provider: zksync.Provider, + receiver_chain_provider: zksync.Provider + ) { + console.log('*Reading and broadcasting interop tx*'); + console.log('txHash', txHash); + // await getInteropTriggerData(sender_chain_provider, txHash, 0); + // await getInteropTriggerData(sender_chain_provider, txHash, 1); + // await getInteropTriggerData(sender_chain_provider, txHash, 2); + // await getInteropTriggerData(sender_chain_provider, txHash, 3); + // await getInteropTriggerData(sender_chain_provider, txHash, 4); + // await getInteropTriggerData(sender_chain_provider, txHash, 5); + + const { + l1BatchNumber: l1BatchNumber_trigger, + l2TxNumberInBlock: l2TxNumberInBlock_trigger, + output: triggerData, + rawData: rawData_trigger + } = await getInteropTriggerData(sender_chain_provider, txHash, 2); + const { + l1BatchNumber: l1BatchNumber_fee, + l2TxNumberInBlock: l2TxNumberInBlock_fee, + output: feeBundleData, + rawData: rawData_fee + } = await getInteropBundleData(sender_chain_provider, txHash, 0); + const { + l1BatchNumber: l1BatchNumber_execution, + l2TxNumberInBlock: l2TxNumberInBlock_execution, + output: executionBundleData, + rawData: rawData_execution + } = await getInteropBundleData(sender_chain_provider, txHash, 1); + const xl2Input = triggerData; + if (triggerData == null) { + return; + } + + // console.log("trigger message", rawData_trigger) + + console.log('triggerData', triggerData); + console.log('feeBundleData', feeBundleData); + console.log('executionBundleData', executionBundleData); + // throw new Error('stop here'); + + const fromFormatted = `0x${xl2Input.from.toString(16).padStart(40, '0')}`; + // const toFormatted = `0x${xl2Input.to.toString(16).padStart(40, '0')}`; + + const txData = ethers.AbiCoder.defaultAbiCoder().encode(['bytes', 'bytes'], [rawData_fee, rawData_execution]); + // Construct the interop transaction + const nonce = await receiver_chain_provider.getTransactionCount(xl2Input.from); + const feeData = await receiver_chain_provider.getFeeData(); + const interopTx = { + // type: INTEROP_TX_TYPE, + from: xl2Input.from, + to: L2_INTEROP_HANDLER_ADDRESS, + chainId: (await receiver_chain_provider.getNetwork()).chainId.toString(), + data: txData, + nonce: nonce, + customData: { + paymasterParams: { paymaster: ethers.ZeroAddress, paymasterInput: '0x' } + // merkleProof: proof1, + // fullFee: '0xf000000000000000', + // toMint: + // (xl2Input.reserved[0].toString(16).length % 2 == 0 ? '0x' : '0x0') + + // xl2Input.reserved[0].toString(16), + // refundRecipient: await interop1_wallet.getAddress() + }, + maxFeePerGas: feeData.maxFeePerGas, + maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, + gasLimit: 30000000, + value: 0 + }; + + console.log('interopTx', interopTx); + const sig = ethers.Signature.from({ + v: 27, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000' + }); + const hexTx = zksync.utils.serializeEip712(interopTx, sig); + // console.log("interopTx fail", xl2Input.unimplemented[0]) + const receiverChainId = (await receiver_chain_provider.getNetwork()).chainId; + const interop1ChainId = (await interop1_provider.getNetwork()).chainId; + // console.log("kl tod inteorp tx", interopTx) + console.log(`Broadcasting interop tx to ${receiverChainId === interop1ChainId ? 'Interop1' : 'Interop2'}`); + const broadcastTx = await receiver_chain_provider.broadcastTransaction(hexTx); + + console.log('Resolved hash', broadcastTx.realInteropHash); + // console.log('broadcastTx hash', broadcastTx.hash); + await delay(timeout * 3); + + // Recursively read and broadcast + await readAndBroadcastInteropTx(broadcastTx.realInteropHash!, receiver_chain_provider, sender_chain_provider); + } + + async function printBalances(balanceTime: string) { + console.log( + `Test wallet Eth Interop 1 balance ${balanceTime}: ${ethers.formatEther( + await interop1_provider.getBalance(interop1_wallet.address) + )} ETH, \n`, + `Test wallet Eth Interop 2 balance ${balanceTime}: ${ethers.formatEther( + await interop2_provider.getBalance(interop1_wallet.address) + )} ETH, \n`, + `Test wallet token A Interop 1 balance ${balanceTime}: ${ethers.formatEther( + await getTokenBalance({ + provider: interop1_provider, + tokenAddress: tokenA_details.l2Address, + address: interop1_wallet.address + }) + )} AA, \n`, + `Aliased Test wallet token A Interop 2 balance ${balanceTime}: ${ethers.formatEther( + await getTokenBalance({ + provider: interop2_provider, + tokenAddress: tokenA_details.l2AddressSecondChain!, + address: aliased_interop1_wallet_address + }) + )} AA, \n`, + `Test wallet token B Interop 1 balance ${balanceTime}: ${ethers.formatEther( + await getTokenBalance({ + provider: interop1_provider, + tokenAddress: tokenB_details.l2Address, + address: interop1_wallet.address + }) + )} BB, \n`, + `Test wallet token B Interop 2 balance ${balanceTime}: ${ethers.formatEther( + await getTokenBalance({ + provider: interop2_provider, + tokenAddress: tokenB_details.l2AddressSecondChain!, + address: aliased_interop1_wallet_address + }) + )} BB` + ); + } + + async function getTokenBalance({ + provider, + tokenAddress, + address + }: { + provider: zksync.Provider; + tokenAddress: string; + address: string; + }) { + const tokenContract = new zksync.Contract(tokenAddress, ArtifactMintableERC20.abi, provider); + return await tokenContract.balanceOf(address); + } + + async function getTokenAllowance({ + provider, + tokenAddress, + fromAddress, + toAddress + }: { + provider: zksync.Provider; + tokenAddress: string; + fromAddress: string; + toAddress: string; + }) { + const tokenContract = new zksync.Contract(tokenAddress, ArtifactMintableERC20.abi, provider); + return await tokenContract.allowance(fromAddress, toAddress); + } + + /** + * Utility function to delay execution for a specified time. + * @param ms - Milliseconds to delay. + */ + function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } +}); diff --git a/core/tests/ts-integration/tests/l1.test.ts b/core/tests/ts-integration/tests/l1.test.ts index 5992b1d18430..04e4562f7cf6 100644 --- a/core/tests/ts-integration/tests/l1.test.ts +++ b/core/tests/ts-integration/tests/l1.test.ts @@ -6,7 +6,8 @@ * and waiting for the block finalization). */ import { TestMaster } from '../src'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { bigIntMax, deployContract, getTestContract, scaledGasPrice, waitForNewL1Batch } from '../src/helpers'; import { diff --git a/core/tests/ts-integration/tests/l2-erc20.test.ts b/core/tests/ts-integration/tests/l2-erc20.test.ts index cc07ebb9c47a..7e3a5b5f7969 100644 --- a/core/tests/ts-integration/tests/l2-erc20.test.ts +++ b/core/tests/ts-integration/tests/l2-erc20.test.ts @@ -6,10 +6,11 @@ import { TestMaster } from '../src'; import { Token } from '../src/types'; import { shouldChangeTokenBalances, shouldOnlyTakeFee } from '../src/modifiers/balance-checker'; -import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { Provider, Wallet } from 'ethers'; import { scaledGasPrice, deployContract, readContract, waitForBlockToBeFinalizedOnL1 } from '../src/helpers'; +import { ARTIFACTS_PATH } from '../src/constants'; describe('L2 native ERC20 contract checks', () => { let testMaster: TestMaster; @@ -35,7 +36,6 @@ describe('L2 native ERC20 contract checks', () => { l2Wallet = new Wallet(alice.privateKey, l2Provider); l1Wallet = new Wallet(alice.privateKey, l1Provider); const L2_NATIVE_TOKEN_VAULT_ADDRESS = '0x0000000000000000000000000000000000010004'; - const ARTIFACTS_PATH = '../../../contracts/l1-contracts/artifacts/contracts/'; const l2NtvInterface = readContract(`${ARTIFACTS_PATH}/bridge/ntv`, 'L2NativeTokenVault').abi; const l2NativeTokenVault = new ethers.Contract(L2_NATIVE_TOKEN_VAULT_ADDRESS, l2NtvInterface, l2Wallet); const l1AssetRouterInterface = readContract(`${ARTIFACTS_PATH}/bridge/asset-router`, 'L1AssetRouter').abi; diff --git a/core/tests/ts-integration/tests/mempool.test.ts b/core/tests/ts-integration/tests/mempool.test.ts index 367e6569e88c..25ff6a9c02df 100644 --- a/core/tests/ts-integration/tests/mempool.test.ts +++ b/core/tests/ts-integration/tests/mempool.test.ts @@ -3,7 +3,8 @@ * scheduled, processed and/or postponed. */ import { TestMaster } from '../src'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; describe('Tests for the mempool behavior', () => { let testMaster: TestMaster; diff --git a/core/tests/ts-integration/tests/paymaster.test.ts b/core/tests/ts-integration/tests/paymaster.test.ts index 8c9024dc4372..ade0e0671bae 100644 --- a/core/tests/ts-integration/tests/paymaster.test.ts +++ b/core/tests/ts-integration/tests/paymaster.test.ts @@ -2,8 +2,10 @@ * This suite contains tests checking the behavior of paymasters -- entities that can cover fees for users. */ import { TestMaster } from '../src'; -import * as zksync from 'zksync-ethers'; -import { Provider, Wallet, utils, Contract } from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; +// import { Provider, Wallet, utils, Contract } from 'zksync-ethers'; +import { Provider, Wallet, utils, Contract } from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { deployContract, getTestContract } from '../src/helpers'; import { L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; diff --git a/core/tests/ts-integration/tests/system.test.ts b/core/tests/ts-integration/tests/system.test.ts index b1508cccfaf2..3dcc5f309557 100644 --- a/core/tests/ts-integration/tests/system.test.ts +++ b/core/tests/ts-integration/tests/system.test.ts @@ -9,7 +9,8 @@ import { TestMaster } from '../src'; import { shouldChangeTokenBalances } from '../src/modifiers/balance-checker'; import { L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; -import * as zksync from 'zksync-ethers'; +// import * as zksync from 'zksync-ethers'; +import * as zksync from 'zksync-ethers-interop-support'; import * as ethers from 'ethers'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; import { DataAvailabityMode } from '../src/types'; diff --git a/etc/env/base/chain.toml b/etc/env/base/chain.toml index 7b632c3ae3a4..3b5a3cd561ea 100644 --- a/etc/env/base/chain.toml +++ b/etc/env/base/chain.toml @@ -90,7 +90,7 @@ fee_model_version = "V2" validation_computational_gas_limit = 300000 save_call_traces = true -bootloader_hash = "0x010008c753336bc8d1ddca235602b9f31d346412b2d463cd342899f7bfb73baf" +bootloader_hash = "0x010009110f0afb723b03f5d2e83eb17efd606171efe6a463de1915b1d829ee40" default_aa_hash = "0x0100055d760f11a3d737e7fd1816e600a4cd874a9f17f7a225d1f1c537c51a1e" protective_reads_persistence_enabled = false diff --git a/etc/env/base/contracts.toml b/etc/env/base/contracts.toml index bf69fd48e7bf..7827b7b22105 100644 --- a/etc/env/base/contracts.toml +++ b/etc/env/base/contracts.toml @@ -39,8 +39,8 @@ L2_WETH_TOKEN_IMPL_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" L2_WETH_TOKEN_PROXY_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" BLOB_VERSIONED_HASH_RETRIEVER_ADDR = "0x0000000000000000000000000000000000000000" -GENESIS_ROOT = "0x09e68951458b18c24ae5f4100160b53c4888c9b3c3c1859cc674bc02236675ad" -GENESIS_BATCH_COMMITMENT = "0x7238eab6a0e9f5bb84421feae6b6b9ae80816d490c875d29ff3ded375a3e078f" +GENESIS_ROOT = "0x44d7e2f5db76220ce198425d3f5fa772412801a6f8de4c43ff5a4d95479f0da3" +GENESIS_BATCH_COMMITMENT = "0x4bcdb3753b8eb027072d93b5bdd3929c7b2fa4b15701a34ac2bf8964c116237e" GENESIS_ROLLUP_LEAF_INDEX = "64" # Ecosystem-wide params diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index a4ba8c0201a6..e6f4e20e2af9 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -312,7 +312,7 @@ prometheus: observability: log_format: plain - log_directives: "zksync_node_test_utils=info,zksync_state_keeper=info,zksync_reorg_detector=info,zksync_consistency_checker=info,zksync_metadata_calculator=info,zksync_node_sync=info,zksync_node_consensus=info,zksync_contract_verification_server=info,zksync_node_api_server=info,zksync_tee_verifier_input_producer=info,zksync_node_framework=info,zksync_block_reverter=info,zksync_commitment_generator=debug,zksync_node_db_pruner=info,zksync_eth_sender=info,zksync_node_fee_model=info,zksync_node_genesis=info,zksync_house_keeper=info,zksync_proof_data_handler=info,zksync_shared_metrics=info,zksync_node_test_utils=info,zksync_vm_runner=info,zksync_consensus_bft=info,zksync_consensus_network=info,zksync_consensus_storage=info,zksync_core_leftovers=debug,zksync_server=debug,zksync_contract_verifier=debug,zksync_dal=info,zksync_db_connection=info,zksync_eth_client=info,zksync_eth_watch=debug,zksync_storage=info,zksync_db_manager=info,zksync_merkle_tree=info,zksync_state=debug,zksync_utils=debug,zksync_queued_job_processor=info,zksync_types=info,zksync_mempool=debug,loadnext=info,vm=info,zksync_object_store=info,zksync_external_node=info,zksync_witness_generator=info,zksync_prover_fri=info,zksync_witness_vector_generator=info,zksync_web3_decl=debug,zksync_health_check=debug,zksync_proof_fri_compressor=info,vise_exporter=error,snapshots_creator=debug,zksync_base_token_adjuster=debug,zksync_external_price_api=debug,zksync_external_proof_integration_api=info" + log_directives: "zksync_multivm=trace,zksync_node_test_utils=info,zksync_state_keeper=info,zksync_reorg_detector=info,zksync_consistency_checker=info,zksync_metadata_calculator=info,zksync_node_sync=info,zksync_node_consensus=info,zksync_contract_verification_server=info,zksync_node_api_server=info,zksync_tee_verifier_input_producer=info,zksync_node_framework=info,zksync_block_reverter=info,zksync_commitment_generator=debug,zksync_node_db_pruner=info,zksync_eth_sender=info,zksync_node_fee_model=info,zksync_node_genesis=info,zksync_house_keeper=info,zksync_proof_data_handler=info,zksync_shared_metrics=info,zksync_node_test_utils=info,zksync_vm_runner=info,zksync_consensus_bft=info,zksync_consensus_network=info,zksync_consensus_storage=info,zksync_core_leftovers=debug,zksync_server=debug,zksync_contract_verifier=debug,zksync_dal=info,zksync_db_connection=info,zksync_eth_client=info,zksync_eth_watch=debug,zksync_storage=info,zksync_db_manager=info,zksync_merkle_tree=info,zksync_state=debug,zksync_utils=debug,zksync_queued_job_processor=info,zksync_types=info,zksync_mempool=debug,loadnext=info,vm=info,zksync_object_store=info,zksync_external_node=info,zksync_witness_generator=info,zksync_prover_fri=info,zksync_witness_vector_generator=info,zksync_web3_decl=debug,zksync_health_check=debug,zksync_proof_fri_compressor=info,vise_exporter=error,snapshots_creator=debug,zksync_base_token_adjuster=debug,zksync_external_price_api=debug,zksync_external_proof_integration_api=info" # Uncomment only if needed # sentry: # url: unset diff --git a/etc/env/file_based/genesis.yaml b/etc/env/file_based/genesis.yaml index 33634c253ba5..470ff3bbc247 100644 --- a/etc/env/file_based/genesis.yaml +++ b/etc/env/file_based/genesis.yaml @@ -1,9 +1,9 @@ -genesis_root: 0x526a5d3e384ff95a976283c79a976e0a2fb749e4631233f29d3765201efd937d -genesis_batch_commitment: 0xb9794246425fd654cf6a4c2e9adfdd48aaaf97bf3b8ba6bdc88e1d141bcfa5b3 -genesis_rollup_leaf_index: 64 +genesis_root: 0x4451d0b2d8ff95bb17cc803c0e6b72e2daa0c29dd05bcadce7c5d5df774373e4 +genesis_batch_commitment: 0x10dcefe1094c10bb40eaea8a933b1ffce70a42be7705f87228fdfa5b880e56ab +genesis_rollup_leaf_index: 66 genesis_protocol_version: 25 -default_aa_hash: 0x0100055d3993e14104994ca4d8cfa91beb9b544ee86894b45708b4824d832ff2 -bootloader_hash: 0x010008c753336bc8d1ddca235602b9f31d346412b2d463cd342899f7bfb73baf +bootloader_hash: 0x010009819bf40a7ddbf8a1e86ad510b74f1966a3c4e51145595e71d293212c79 +default_aa_hash: 0x0100055dbd629567931421dcebb4b38da3dab317ac5e0abacb7dedc14e3d033c l1_chain_id: 9 l2_chain_id: 270 fee_account: '0x0000000000000000000000000000000000000001' diff --git a/zk_toolbox/crates/common/src/withdraw.rs b/zk_toolbox/crates/common/src/withdraw.rs index bdd1b426cc46..238a5fecb04a 100644 --- a/zk_toolbox/crates/common/src/withdraw.rs +++ b/zk_toolbox/crates/common/src/withdraw.rs @@ -132,7 +132,6 @@ where let (l2_to_l1_log_index, _) = self .get_withdrawal_l2_to_l1_log(withdrawal_hash, index) .await?; - let sender = H160::from_slice(&log.topics[1][12..]); let proof = ::get_l2_to_l1_log_proof( self, withdrawal_hash, @@ -144,13 +143,7 @@ where })? .ok_or_else(|| ProviderError::CustomError("Log proof not found!".into()))?; - let message = ethers::abi::decode(&[ethers::abi::ParamType::Bytes], &log.data.0) - .map_err(|e| ProviderError::CustomError(format!("Failed to decode log data: {}", e)))? - .remove(0) - .into_bytes() - .ok_or_else(|| { - ProviderError::CustomError("Failed to extract message from decoded data".into()) - })?; + let (sender, message) = get_message_from_log(&log)?; Ok(FinalizeWithdrawalParams { l2_batch_number: log.l1_batch_number.unwrap_or_default(), @@ -162,3 +155,15 @@ where }) } } + +pub fn get_message_from_log(log: &Log) -> Result<(H160, Bytes), ProviderError> { + let sender = H160::from_slice(&log.topics[1][12..]); + let message = ethers::abi::decode(&[ethers::abi::ParamType::Bytes], &log.data.0) + .map_err(|e| ProviderError::CustomError(format!("Failed to decode log data: {}", e)))? + .remove(0) + .into_bytes() + .ok_or_else(|| { + ProviderError::CustomError("Failed to extract message from decoded data".into()) + })?; + Ok((sender, message.into())) +} diff --git a/zk_toolbox/crates/zk_supervisor/Cargo.toml b/zk_toolbox/crates/zk_supervisor/Cargo.toml index 158abe4e2ec6..3c44f9c551c4 100644 --- a/zk_toolbox/crates/zk_supervisor/Cargo.toml +++ b/zk_toolbox/crates/zk_supervisor/Cargo.toml @@ -29,4 +29,4 @@ futures.workspace = true types.workspace = true serde_yaml.workspace = true zksync_basic_types.workspace = true -sqruff-lib = { git = "https://github.com/quarylabs/sqruff", version = "0.18.2" } +sqruff-lib = "0.19.0" diff --git a/zk_toolbox/crates/zk_supervisor/src/commands/test/integration.rs b/zk_toolbox/crates/zk_supervisor/src/commands/test/integration.rs index 8f76e56fe836..9e73dd7fb791 100644 --- a/zk_toolbox/crates/zk_supervisor/src/commands/test/integration.rs +++ b/zk_toolbox/crates/zk_supervisor/src/commands/test/integration.rs @@ -43,10 +43,11 @@ pub async fn run(shell: &Shell, args: IntegrationArgs) -> anyhow::Result<()> { let test_pattern = args.test_pattern; let mut command = cmd!( shell, - "yarn jest --forceExit --testTimeout 350000 -t {test_pattern...}" + "yarn jest --forceExit --testTimeout 800000 -t {test_pattern...}" ) .env("CHAIN_NAME", ecosystem_config.current_chain()) .env("MASTER_WALLET_PK", wallets.get_test_pk(&chain_config)?); + // .env("ZKSYNC_HOME", ecosystem_config.link_to_code); if args.external_node { command = command.env("EXTERNAL_NODE", format!("{:?}", args.external_node))