diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index da862c657..6fc1a6703 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -91,4 +91,6 @@ jobs: - name: Test env: SVM_TARGET_PLATFORM: ${{ matrix.svm_target_platform }} + HTTP_ARCHIVE_URLS: ${{ secrets.HTTP_ARCHIVE_URLS }} + WS_ARCHIVE_URLS: ${{ secrets.WS_ARCHIVE_URLS }} run: cargo nextest run ${{ matrix.flags }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 82922c5e9..5f22ce7e7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - "*upstream*" pull_request: branches: - main + - "*upstream*" concurrency: cancel-in-progress: true @@ -24,7 +26,7 @@ jobs: secrets: inherit doctest: - runs-on: ubuntu-22.04-github-hosted-16core + runs-on: ubuntu-22.04 timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -39,7 +41,7 @@ jobs: clippy: name: clippy - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -52,7 +54,7 @@ jobs: RUSTFLAGS: -Dwarnings rustfmt: - runs-on: ubuntu-22.04-github-hosted-16core + runs-on: ubuntu-22.04 timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -63,7 +65,7 @@ jobs: - run: cargo fmt --all --check forge-fmt: - runs-on: ubuntu-22.04-github-hosted-16core + runs-on: ubuntu-22.04 timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -78,7 +80,7 @@ jobs: run: ./.github/scripts/format.sh --check codespell: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - uses: actions/checkout@v4 @@ -87,6 +89,7 @@ jobs: skip: "*.json" crate-checks: + # ubuntu-22.04 runs out of disk space runs-on: ubuntu-22.04-github-hosted-16core timeout-minutes: 60 steps: @@ -102,7 +105,7 @@ jobs: run: cargo hack check zk-cargo-test: - runs-on: ubuntu-22.04-github-hosted-16core + runs-on: ubuntu-22.04 steps: - name: Checkout code @@ -128,18 +131,21 @@ jobs: logFilePath: era_test_node.log target: x86_64-unknown-linux-gnu releaseTag: v0.1.0-alpha.29 - + - name: Setup Git config + run: | + git config --global user.name "GitHub Actions Bot" + git config --global user.email "<>" + git config --global url."https://github.com/".insteadOf "git@github.com:" - name: Run zk tests env: RUST_BACKTRACE: full TEST_MAINNET_URL: http://localhost:8011 run: | - git config --global user.name "test-runner" ZK_DEBUG_HISTORICAL_BLOCK_HASHES=5 cargo nextest run --package '*' --lib --test '*' --filter-expr 'test(~zk)' check-ci-install: name: CI install - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Install foundry-zksync diff --git a/Cargo.lock b/Cargo.lock index e2e3ffbe0..d72b9c596 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,8 +96,9 @@ checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "alloy" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b524b8c28a7145d1fe4950f84360b5de3e307601679ff0558ddc20ea229399" dependencies = [ "alloy-consensus", "alloy-contract", @@ -132,8 +133,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae09ffd7c29062431dd86061deefe4e3c6f07fa0d674930095f8dcedb0baf02c" dependencies = [ "alloy-eips", "alloy-primitives", @@ -142,13 +144,15 @@ dependencies = [ "auto_impl", "c-kzg", "derive_more 1.0.0", + "k256 0.13.4", "serde", ] [[package]] name = "alloy-contract" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66430a72d5bf5edead101c8c2f0a24bada5ec9f3cf9909b3e08b6d6899b4803e" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -167,9 +171,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d22df68fa7d9744be0b1a9be3260e9aa089fbf41903ab182328333061ed186" +checksum = "9c8316d83e590f4163b221b8180008f302bda5cf5451202855cdd323e588849c" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -180,9 +184,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cf633ae9a1f0c82fdb9e559ed2be1c8e415c3e48fc47e1feaf32c6078ec0cdd" +checksum = "ef2364c782a245cf8725ea6dbfca5f530162702b5d685992ea03ce64529136cc" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -214,9 +218,9 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ffc577390ce50234e02d841214b3dc0bea6aaaae8e04bbf3cb82e9a45da9eb" +checksum = "5f6cee6a35793f3db8a5ffe60e86c695f321d081a567211245f503e8c498fce8" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -229,8 +233,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b6aa3961694b30ba53d41006131a2fca3bdab22e4c344e46db2c639e7c2dfdd" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -246,8 +251,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53f7877ded3921d18a0a9556d55bedf84535567198c9edab2aa23106da91855" dependencies = [ "alloy-primitives", "alloy-serde", @@ -256,9 +262,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a500037938085feed8a20dbfc8fce58c599db68c948cfae711147175dee392c" +checksum = "b84c506bf264110fa7e90d9924f742f40ef53c6572ea56a0b0bd714a567ed389" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -268,8 +274,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3694b7e480728c0b3e228384f223937f14c10caef5a4c766021190fc8f283d35" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -281,8 +288,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea94b8ceb5c75d7df0a93ba0acc53b55a22b47b532b600a800a87ef04eb5b0b4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -296,13 +304,16 @@ dependencies = [ "async-trait", "auto_impl", "futures-utils-wasm", + "serde", + "serde_json", "thiserror 1.0.69", ] [[package]] name = "alloy-network-primitives" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9f3e281005943944d15ee8491534a1c7b3cbf7a7de26f8c433b842b93eb5f9" dependencies = [ "alloy-consensus", "alloy-eips", @@ -313,9 +324,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aeeb5825c2fc8c2662167058347cd0cafc3cb15bcb5cdb1758a63c2dca0409e" +checksum = "9fce5dbd6a4f118eecc4719eaa9c7ffc31c315e6c5ccde3642db927802312425" dependencies = [ "alloy-rlp", "arbitrary", @@ -326,7 +337,7 @@ dependencies = [ "derive_more 1.0.0", "foldhash", "getrandom 0.2.15", - "hashbrown 0.15.2", + "hashbrown 0.15.1", "hex-literal", "indexmap 2.6.0", "itoa", @@ -345,8 +356,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c1f9eede27bf4c13c099e8e64d54efd7ce80ef6ea47478aa75d5d74e2dba3b" dependencies = [ "alloy-chains", "alloy-consensus", @@ -386,8 +398,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f1f34232f77341076541c405482e4ae12f0ee7153d8f9969fc1691201b2247" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -419,15 +432,16 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b09cae092c27b6f1bde952653a22708691802e57bfef4a2973b80bea21efd3f" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "alloy-rpc-client" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374dbe0dc3abdc2c964f36b3d3edf9cdb3db29d16bda34aa123f03d810bec1dd" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -451,8 +465,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c74832aa474b670309c20fffc2a869fa141edab7c79ff7963fad0a08de60bae1" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -466,18 +481,21 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca97963132f78ddfc60e43a017348e6d52eea983925c23652f5b330e8e02291" dependencies = [ "alloy-primitives", + "alloy-rpc-types-eth", "alloy-serde", "serde", ] [[package]] name = "alloy-rpc-types-engine" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56294dce86af23ad6ee8df46cf8b0d292eb5d1ff67dc88a0886051e32b1faf" dependencies = [ "alloy-consensus", "alloy-eips", @@ -493,8 +511,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a477281940d82d29315846c7216db45b15e90bcd52309da9f54bcf7ad94a11" dependencies = [ "alloy-consensus", "alloy-eips", @@ -511,8 +530,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd8b4877ef520c138af702097477cdd19504a8e1e4675ba37e92ba40f2d3c6f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -524,8 +544,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d4ab49acf90a71f7fb894dc5fd485f1f07a1e348966c714c4d1e0b7478850a8" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -535,8 +556,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dfa4a7ccf15b2492bb68088692481fd6b2604ccbee1d0d6c44c21427ae4df83" dependencies = [ "alloy-primitives", "serde", @@ -545,8 +567,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e10aec39d60dc27edcac447302c7803d2371946fb737245320a05b78eb2fafd" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -560,8 +583,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0109e5b18079aec2a022e4bc9db1d74bcc046f8b66274ffa8b0e4322b44b2b44" dependencies = [ "alloy-consensus", "alloy-network", @@ -577,8 +601,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558651eb0d76bcf2224de694481e421112fa2cbc6fe6a413cc76fd67e14cf0d7" dependencies = [ "alloy-consensus", "alloy-network", @@ -594,8 +619,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29781b6a064b6235de4ec3cc0810f59fe227b8d31258f23a077570fc9525d7a6" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -613,8 +639,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8396f6dff60700bc1d215ee03d86ff56de268af96e2bf833a14d0bafcab9882" dependencies = [ "alloy-consensus", "alloy-network", @@ -631,8 +658,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21267541177607141a5db6fd1abed5a46553b7a6d9363cf3d047721634705905" dependencies = [ "alloy-consensus", "alloy-network", @@ -647,23 +675,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0279d09463a4695788a3622fd95443625f7be307422deba4b55dd491a9c7a1" +checksum = "9343289b4a7461ed8bab8618504c995c049c082b70c7332efd7b32125633dc05" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feea540fc8233df2ad1156efd744b2075372f43a8f942a68b3b19c8a00e2c12" +checksum = "4222d70bec485ceccc5d8fd4f2909edd65b5d5e43d4aca0b5dcee65d519ae98f" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -671,35 +699,35 @@ dependencies = [ "heck", "indexmap 2.6.0", "proc-macro-error2", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "syn-solidity", "tiny-keccak 2.0.2", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0ad281f3d1b613af814b66977ee698e443d4644a1510962d0241f26e0e53ae" +checksum = "2e17f2677369571b976e51ea1430eb41c3690d344fef567b840bfc0b01b6f83a" dependencies = [ "alloy-json-abi", "const-hex", "dunce", "heck", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "serde_json", - "syn 2.0.89", + "syn 2.0.87", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eff16c797438add6c37bb335839d015b186c5421ee5626f5559a7bfeb38ef5" +checksum = "aa64d80ae58ffaafdff9d5d84f58d03775f66c84433916dc9a64ed16af5755da" dependencies = [ "serde", "winnow 0.6.20", @@ -707,9 +735,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff34e0682d6665da243a3e81da96f07a2dd50f7e64073e382b1a141f5a2a2f6" +checksum = "6520d427d4a8eb7aa803d852d7a52ceb0c519e784c292f64bb339e636918cf27" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -720,8 +748,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f99acddb34000d104961897dbb0240298e8b775a7efffb9fda2a1a3efedd65b3" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -739,8 +768,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc013132e34eeadaa0add7e74164c1503988bfba8bae885b32e0918ba85a8a6" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -753,8 +783,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063edc0660e81260653cc6a95777c29d54c2543a668aa5da2359fb450d25a1ba" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -773,14 +804,15 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.5.4" -source = "git+https://github.com/Karrq/alloy?branch=zksync-v0.5.4#21484592682f146ba8f50de0d90883a10e82d52f" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd170e600801116d5efe64f74a4fc073dbbb35c807013a7d0a388742aeebba0" dependencies = [ "alloy-pubsub", "alloy-transport", "futures 0.3.31", "http 1.1.0", - "rustls 0.23.18", + "rustls 0.23.17", "serde_json", "tokio", "tokio-tungstenite", @@ -805,9 +837,9 @@ dependencies = [ [[package]] name = "alloy-zksync" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f279833c27d8116f15d9a294c0529a716b3303ae1296063c71729a74c2e8b5" +checksum = "1188e7fd94560a363fb32c12fc37109a92989dae4e40eabe39ac76119aa7f670" dependencies = [ "alloy", "async-trait", @@ -850,6 +882,16 @@ dependencies = [ "libc", ] +[[package]] +name = "annotate-snippets" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" +dependencies = [ + "anstyle", + "unicode-width 0.1.14", +] + [[package]] name = "ansiterm" version = "0.12.2" @@ -955,7 +997,7 @@ dependencies = [ "foundry-evm", "foundry-test-utils", "futures 0.3.31", - "hyper 1.5.1", + "hyper 1.5.0", "itertools 0.13.0", "k256 0.13.4", "op-alloy-consensus", @@ -985,6 +1027,7 @@ dependencies = [ "alloy-consensus", "alloy-dyn-abi", "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rpc-types", @@ -1133,7 +1176,7 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint 0.4.6", "num-traits", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -1238,9 +1281,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.18" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" dependencies = [ "flate2", "futures-core", @@ -1264,9 +1307,9 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -1286,9 +1329,9 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -1297,9 +1340,9 @@ version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -1359,9 +1402,9 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -1414,20 +1457,21 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.11.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" +checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" dependencies = [ "aws-lc-sys", + "mirai-annotations", "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.23.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" +checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" dependencies = [ "bindgen 0.69.5", "cc", @@ -1729,7 +1773,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-util", "itoa", "matchit", @@ -1743,7 +1787,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "tokio", "tokio-tungstenite", "tower 0.5.1", @@ -1767,7 +1811,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -1875,9 +1919,9 @@ dependencies = [ [[package]] name = "bigdecimal" -version = "0.4.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f850665a0385e070b64c38d2354e6c104c8479c59868d1e48a0c13ee2c7a1c1" +checksum = "51d712318a27c7150326677b321a5fa91b55f6d9034ffd67f20319e147d40cee" dependencies = [ "autocfg", "libm", @@ -1914,12 +1958,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -1931,17 +1975,17 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.11.0", "lazy_static", "lazycell", "log", "prettyplease", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.89", + "syn 2.0.87", "which 4.4.2", ] @@ -2110,9 +2154,9 @@ checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" dependencies = [ "darling 0.20.10", "ident_case", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -2148,9 +2192,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "cfg_aliases 0.2.1", @@ -2158,15 +2202,16 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", "proc-macro-crate 3.2.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", + "syn_derive", ] [[package]] @@ -2225,7 +2270,7 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -2238,9 +2283,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.20.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -2403,7 +2448,7 @@ dependencies = [ "rayon", "regex", "rpassword", - "rustls 0.23.18", + "rustls 0.23.17", "semver 1.0.23", "serde", "serde_json", @@ -2742,9 +2787,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -2791,9 +2836,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.52" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] @@ -2997,9 +3042,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.13.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487981fa1af147182687064d0a2c336586d337a606595ced9ffb0c685c250c73" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -3029,7 +3074,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "unicode-xid 0.2.6", ] @@ -3065,16 +3110,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -3083,9 +3118,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -3247,12 +3282,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3296,9 +3331,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3329,7 +3364,7 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "strsim 0.10.0", "syn 1.0.109", @@ -3343,10 +3378,10 @@ checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "strsim 0.11.1", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3368,7 +3403,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3462,7 +3497,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -3473,9 +3508,9 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3494,9 +3529,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling 0.20.10", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3506,7 +3541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3516,10 +3551,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "rustc_version 0.4.1", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3538,9 +3573,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "convert_case 0.6.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "unicode-xid 0.2.6", ] @@ -3652,16 +3687,16 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "divan" -version = "0.1.16" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc40f214f0d9e897cfc72e2edfa5c225d3252f758c537f11ac0a80371c073a6" +checksum = "6e05d17bd4ff1c1e7998ed4623d2efd91f72f1e24141ac33aac9377974270e1f" dependencies = [ "cfg-if 1.0.0", "clap", @@ -3673,13 +3708,13 @@ dependencies = [ [[package]] name = "divan-macros" -version = "0.1.16" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bdb5411188f7f878a17964798c1264b6b0a9f915bd39b20bf99193c923e1b4e" +checksum = "1b4464d46ce68bfc7cb76389248c7c254def7baca8bece0693b02b83842c4c88" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3869,9 +3904,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.35" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if 1.0.0", ] @@ -3889,9 +3924,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -3900,9 +3935,9 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -4143,12 +4178,12 @@ dependencies = [ "ethers-core", "eyre", "prettyplease", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "regex", "serde", "serde_json", - "syn 2.0.89", + "syn 2.0.87", "toml 0.8.19", "walkdir", ] @@ -4176,7 +4211,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.89", + "syn 2.0.87", "tempfile", "thiserror 1.0.69", "tiny-keccak 2.0.2", @@ -4393,9 +4428,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", @@ -4484,7 +4519,7 @@ dependencies = [ "futures 0.3.31", "globset", "humantime-serde", - "hyper 1.5.1", + "hyper 1.5.0", "indicatif", "inferno", "itertools 0.13.0", @@ -4499,7 +4534,7 @@ dependencies = [ "regex", "reqwest 0.12.9", "revm-inspectors", - "rustls 0.23.18", + "rustls 0.23.17", "semver 1.0.23", "serde", "serde_json", @@ -4534,6 +4569,7 @@ dependencies = [ "derive_more 1.0.0", "eyre", "forge-fmt", + "foundry-common", "foundry-compilers", "foundry-config", "itertools 0.13.0", @@ -4641,10 +4677,10 @@ dependencies = [ "eyre", "foundry-common", "prettyplease", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "serde_json", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -4693,8 +4729,8 @@ dependencies = [ [[package]] name = "foundry-block-explorers" -version = "0.8.0" -source = "git+https://github.com/Moonsong-Labs/block-explorers?branch=zksync-v0.7.3#0cf56eaa2484e420ef38243773eff671c5f142a0" +version = "0.9.0" +source = "git+https://github.com/Moonsong-Labs/block-explorers?branch=zksync-v0.9.0#6a8e00b830638ddcaa86ab83126a715a499ef482" dependencies = [ "alloy-chains", "alloy-json-abi", @@ -4805,6 +4841,7 @@ dependencies = [ "foundry-wallets", "futures 0.3.31", "indicatif", + "rayon", "regex", "serde", "serde_json", @@ -4825,6 +4862,7 @@ dependencies = [ "alloy-consensus", "alloy-contract", "alloy-dyn-abi", + "alloy-eips", "alloy-json-abi", "alloy-json-rpc", "alloy-primitives", @@ -4851,6 +4889,7 @@ dependencies = [ "foundry-compilers", "foundry-config", "foundry-zksync-compiler", + "itertools 0.13.0", "num-format", "reqwest 0.12.9", "semver 1.0.23", @@ -4889,8 +4928,8 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.11.6" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.6#a17fbc0a02fd3fb2e7f04ef4ce4a424b82a963b4" +version = "0.12.3" +source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.12.3#c0cc4bcaedac36b7b61b4dcf4a289c305af312aa" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4915,7 +4954,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "solang-parser", + "solar-parse", "svm-rs", "svm-rs-builds", "tempfile", @@ -4929,8 +4968,8 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.11.6" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.6#a17fbc0a02fd3fb2e7f04ef4ce4a424b82a963b4" +version = "0.12.3" +source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.12.3#c0cc4bcaedac36b7b61b4dcf4a289c305af312aa" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -4939,8 +4978,8 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.11.6" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.6#a17fbc0a02fd3fb2e7f04ef4ce4a424b82a963b4" +version = "0.12.3" +source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.12.3#c0cc4bcaedac36b7b61b4dcf4a289c305af312aa" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4962,8 +5001,8 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.11.6" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.6#a17fbc0a02fd3fb2e7f04ef4ce4a424b82a963b4" +version = "0.12.3" +source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.12.3#c0cc4bcaedac36b7b61b4dcf4a289c305af312aa" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4976,8 +5015,8 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-zksolc" -version = "0.11.6" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.6#a17fbc0a02fd3fb2e7f04ef4ce4a424b82a963b4" +version = "0.12.3" +source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.12.3#c0cc4bcaedac36b7b61b4dcf4a289c305af312aa" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4997,8 +5036,8 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.11.6" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.6#a17fbc0a02fd3fb2e7f04ef4ce4a424b82a963b4" +version = "0.12.3" +source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.12.3#c0cc4bcaedac36b7b61b4dcf4a289c305af312aa" dependencies = [ "alloy-primitives", "cfg-if 1.0.0", @@ -5117,13 +5156,14 @@ dependencies = [ name = "foundry-evm-core" version = "0.0.2" dependencies = [ + "alloy-consensus", "alloy-dyn-abi", "alloy-genesis", "alloy-json-abi", + "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rpc-types", - "alloy-serde", "alloy-sol-types", "alloy-transport", "auto_impl", @@ -5145,6 +5185,7 @@ dependencies = [ "thiserror 1.0.69", "tokio", "tracing", + "url", ] [[package]] @@ -5220,9 +5261,10 @@ dependencies = [ [[package]] name = "foundry-fork-db" -version = "0.6.0" -source = "git+https://github.com/Moonsong-Labs/foundry-zksync-fork-db?branch=zksync-v0.6.0#f2e915d1c476007ae16be9fb96b25ffe1b8f5113" +version = "0.7.1" +source = "git+https://github.com/Moonsong-Labs/foundry-zksync-fork-db?branch=zksync-v0.7.1#402d191fa5c4d12a003f5dca0e5c32611c3476f7" dependencies = [ + "alloy-consensus", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -5255,9 +5297,9 @@ name = "foundry-macros" version = "0.0.2" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -5545,9 +5587,9 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -5607,7 +5649,7 @@ dependencies = [ "bytes", "chrono", "futures 0.3.31", - "hyper 1.5.1", + "hyper 1.5.0", "jsonwebtoken", "once_cell", "prost 0.13.3", @@ -5716,27 +5758,27 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.14.10" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49aaeef5d98390a3bcf9dbc6440b520b793d1bf3ed99317dc407b02be995b28e" +checksum = "f3de3fdca9c75fa4b83a76583d265fa49b1de6b088ebcd210749c24ceeb74660" dependencies = [ "bitflags 2.6.0", "bstr", "gix-path", "libc", - "thiserror 2.0.3", + "thiserror 1.0.69", ] [[package]] name = "gix-date" -version = "0.9.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691142b1a34d18e8ed6e6114bc1a2736516c5ad60ef3aa9bd1b694886e3ca92d" +checksum = "d10d543ac13c97292a15e8e8b7889cd006faf739777437ed95362504b8fe81a0" dependencies = [ "bstr", "itoa", "jiff", - "thiserror 2.0.3", + "thiserror 1.0.69", ] [[package]] @@ -5819,15 +5861,15 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.13" +version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc292ef1a51e340aeb0e720800338c805975724c1dfbd243185452efd8645b7" +checksum = "c04e5a94fdb56b1e91eb7df2658ad16832428b8eeda24ff1a0f0288de2bce554" dependencies = [ "bstr", "gix-trace", "home", "once_cell", - "thiserror 2.0.3", + "thiserror 1.0.69", ] [[package]] @@ -5853,9 +5895,9 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.10" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8b876ef997a955397809a2ec398d6a45b7a55b4918f2446344330f778d14fd6" +checksum = "a2007538eda296445c07949cf04f4a767307d887184d6b3e83e2d636533ddc6e" dependencies = [ "bitflags 2.6.0", "gix-path", @@ -5894,12 +5936,12 @@ dependencies = [ [[package]] name = "gix-validate" -version = "0.9.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd520d09f9f585b34b32aba1d0b36ada89ab7fefb54a8ca3fe37fc482a750937" +checksum = "e187b263461bc36cea17650141567753bc6207d036cedd1de6e81a52f277ff68" dependencies = [ "bstr", - "thiserror 2.0.3", + "thiserror 1.0.69", ] [[package]] @@ -6085,9 +6127,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -6168,9 +6210,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" dependencies = [ "allocator-api2", "equivalent", @@ -6279,9 +6321,9 @@ dependencies = [ "log", "mac", "markup5ever", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -6400,14 +6442,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.7", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -6443,11 +6485,11 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-util", "log", - "rustls 0.23.18", - "rustls-native-certs 0.8.1", + "rustls 0.23.17", + "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -6461,7 +6503,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.5.1", + "hyper 1.5.0", "hyper-util", "pin-project-lite", "tokio", @@ -6489,7 +6531,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-util", "native-tls", "tokio", @@ -6508,7 +6550,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.5.1", + "hyper 1.5.0", "pin-project-lite", "socket2", "tokio", @@ -6652,9 +6694,9 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -6710,7 +6752,7 @@ dependencies = [ "futures 0.3.31", "gix-config", "ignore", - "miette 7.3.0", + "miette 7.2.0", "normalize-path", "project-origins", "radix_trie", @@ -6766,13 +6808,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 1.0.109", ] [[package]] @@ -6781,6 +6823,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" + [[package]] name = "indexmap" version = "1.9.3" @@ -6799,7 +6847,7 @@ checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "arbitrary", "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.1", "serde", ] @@ -6883,9 +6931,9 @@ dependencies = [ "darling 0.20.10", "indoc", "pretty_assertions", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -6899,9 +6947,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb" +checksum = "d2f4e4a06d42fab3e85ab1b419ad32b09eab58b901d40c57935ff92db3287a13" dependencies = [ "doctest-file", "futures-core", @@ -6962,15 +7010,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -6982,9 +7021,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" @@ -7103,7 +7142,7 @@ version = "18.0.0" source = "git+https://github.com/matter-labs/jsonrpc.git?branch=master#12c53e3e20c09c2fb9966a4ef1b0ea63de172540" dependencies = [ "proc-macro-crate 0.1.5", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -7185,7 +7224,7 @@ dependencies = [ "http 1.1.0", "jsonrpsee-core", "pin-project 1.1.7", - "rustls 0.23.18", + "rustls 0.23.17", "rustls-pki-types", "rustls-platform-verifier", "soketto", @@ -7235,12 +7274,12 @@ dependencies = [ "async-trait", "base64 0.22.1", "http-body 1.0.1", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-rustls 0.27.3", "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls 0.23.18", + "rustls 0.23.17", "rustls-platform-verifier", "serde", "serde_json", @@ -7259,9 +7298,9 @@ checksum = "7895f186d5921065d96e16bd795e5ca89ac8356ec423fafc6e3d7cf8ec11aee4" dependencies = [ "heck", "proc-macro-crate 3.2.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -7275,7 +7314,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-util", "jsonrpsee-core", "jsonrpsee-types", @@ -7439,6 +7478,16 @@ dependencies = [ "regex-automata 0.4.9", ] +[[package]] +name = "lasso" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e14eda50a3494b3bf7b9ce51c52434a761e383d7238ce1dd5dcec2fbc13e9fb" +dependencies = [ + "dashmap 6.1.0", + "hashbrown 0.14.5", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -7456,9 +7505,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.165" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb4d3d38eab6c5239a362fa8bae48c03baf980a6e7079f063942d563ef3533e" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libdbus-sys" @@ -7555,9 +7604,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[package]] name = "lock_api" @@ -7598,10 +7647,10 @@ checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" dependencies = [ "beef", "fnv", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "regex-syntax 0.6.29", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -7632,7 +7681,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.1", ] [[package]] @@ -7704,9 +7753,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.43" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148" +checksum = "7624879735513024d323e7267a0b3a7176aceb0db537939beb4ee31d9e8945e3" dependencies = [ "ammonia", "anyhow", @@ -7779,12 +7828,12 @@ dependencies = [ [[package]] name = "miette" -version = "7.3.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551cefdb9e93e2a40037f24cd139d88009a7660158c9d5d6076afeca5c8cfb82" +checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" dependencies = [ "cfg-if 1.0.0", - "miette-derive 7.3.0", + "miette-derive 7.2.0", "thiserror 1.0.69", "unicode-width 0.1.14", ] @@ -7795,20 +7844,20 @@ version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "miette-derive" -version = "7.3.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd70bb0b631435c30f187b3c2b528d0b78c65654f542ead7857915e37c177da" +checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -7891,6 +7940,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "mockall" version = "0.13.1" @@ -7912,9 +7967,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if 1.0.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -7935,7 +7990,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -8270,9 +8325,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8281,10 +8336,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2 1.0.92", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8332,9 +8387,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "op-alloy-consensus" -version = "0.5.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26c3b35b7b3e36d15e0563eebffe13c1d9ca16b7aaffcb6a64354633547e16b" +checksum = "bff54d1d790eca1f3aedbd666162e9c42eceff90b9f9d24b352ed9c2df1e901a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8348,9 +8403,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.5.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bae9bf91b620e1e2c2291562e5998bc1247bd8ada011773e1997b31a95de99" +checksum = "981b7f8ab11fe85ba3c1723702f000429b8d0c16b5883c93d577895f262cbac6" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8358,6 +8413,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", + "derive_more 1.0.0", "op-alloy-consensus", "serde", "serde_json", @@ -8389,7 +8445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" dependencies = [ "bytes", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -8427,9 +8483,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8440,9 +8496,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.4.1+3.4.0" +version = "300.4.0+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" dependencies = [ "cc", ] @@ -8650,7 +8706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -8662,9 +8718,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8781a75c6205af67215f382092b6e0a4ff3734798523e69073d4bcd294ec767b" dependencies = [ "proc-macro-crate 3.2.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8769,10 +8825,10 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "proc-macro2-diagnostics", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8835,9 +8891,9 @@ checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8919,9 +8975,9 @@ checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ "phf_generator 0.11.2", "phf_shared 0.11.2", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -8966,7 +9022,7 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -8977,9 +9033,9 @@ version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -9033,9 +9089,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "powerfmt" @@ -9100,8 +9156,8 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ - "proc-macro2 1.0.92", - "syn 2.0.89", + "proc-macro2 1.0.89", + "syn 2.0.87", ] [[package]] @@ -9175,7 +9231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", "version_check", @@ -9187,7 +9243,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "version_check", ] @@ -9198,7 +9254,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", ] @@ -9209,9 +9265,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ "proc-macro-error-attr2", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -9231,9 +9287,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -9244,9 +9300,9 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "version_check", "yansi", ] @@ -9300,9 +9356,9 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -9331,9 +9387,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -9364,7 +9420,7 @@ checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", "heck", - "itertools 0.12.1", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -9373,7 +9429,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.89", + "syn 2.0.87", "tempfile", ] @@ -9384,10 +9440,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", - "proc-macro2 1.0.92", + "itertools 0.11.0", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -9397,10 +9453,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.13.0", - "proc-macro2 1.0.92", + "itertools 0.11.0", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -9499,7 +9555,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -9547,16 +9603,16 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-junit" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed1a693391a16317257103ad06a88c6529ac640846021da7c435a06fffdacd7" +checksum = "62ffd2f9a162cfae131bed6d9d1ed60adced33be340a94f96952897d7cb0c240" dependencies = [ "chrono", "indexmap 2.6.0", "newtype-uuid", - "quick-xml 0.37.1", + "quick-xml 0.36.2", "strip-ansi-escapes", - "thiserror 2.0.3", + "thiserror 1.0.69", "uuid 1.11.0", ] @@ -9589,9 +9645,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.37.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22f29bdff3987b4d8632ef95fd6424ec7e4e0a57e2f4fc63e489e75357f6a03" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", ] @@ -9607,7 +9663,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.0.0", - "rustls 0.23.18", + "rustls 0.23.17", "socket2", "thiserror 2.0.3", "tokio", @@ -9625,7 +9681,7 @@ dependencies = [ "rand 0.8.5", "ring", "rustc-hash 2.0.0", - "rustls 0.23.18", + "rustls 0.23.17", "rustls-pki-types", "slab", "thiserror 2.0.3", @@ -9663,7 +9719,7 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", ] [[package]] @@ -9994,11 +10050,11 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.7", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-rustls 0.27.3", "hyper-tls 0.6.0", "hyper-util", @@ -10012,14 +10068,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.18", - "rustls-native-certs 0.8.1", + "rustls 0.23.17", + "rustls-native-certs 0.8.0", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "system-configuration 0.6.1", "tokio", "tokio-native-tls", @@ -10078,9 +10134,9 @@ dependencies = [ [[package]] name = "revm" -version = "17.1.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055bee6a81aaeee8c2389ae31f0d4de87f44df24f4444a1116f9755fd87a76ad" +checksum = "15689a3c6a8d14b647b4666f2e236ef47b5a5133cdfd423f545947986fff7013" dependencies = [ "auto_impl", "cfg-if 1.0.0", @@ -10093,9 +10149,9 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e29c662f7887f3b659d4b0fd234673419a8fcbeaa1ecc29bf7034c0a75cc8ea" +checksum = "747291a18ad6726a08dd73f8b6a6b3a844db582ecae2063ccf0a04880c44f482" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -10111,9 +10167,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac2034454f8bc69dc7d3c94cdb1b57559e27f5ef0518771f1787de543d7d6a1" +checksum = "74e3f11d0fed049a4a10f79820c59113a79b38aed4ebec786a79d5c667bfeb51" dependencies = [ "revm-primitives", "serde", @@ -10121,9 +10177,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "14.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a88c8c7c5f9b988a9e65fc0990c6ce859cdb74114db705bd118a96d22d08027" +checksum = "e381060af24b750069a2b2d2c54bba273d84e8f5f9e8026fc9262298e26cc336" dependencies = [ "aurora-engine-modexp", "blst", @@ -10141,9 +10197,9 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d11fa1e195b0bebaf3fb18596f314a13ba3a4cb1fdd16d3465934d812fd921e" +checksum = "3702f132bb484f4f0d0ca4f6fbde3c82cfd745041abbedd6eda67730e1868ef0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -10237,7 +10293,7 @@ version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -10259,7 +10315,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -10293,9 +10349,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.7" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" dependencies = [ "const-oid", "digest 0.10.7", @@ -10425,9 +10481,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -10450,9 +10506,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" dependencies = [ "aws-lc-rs", "log", @@ -10473,7 +10529,7 @@ dependencies = [ "openssl-probe", "rustls-pemfile 1.0.4", "schannel", - "security-framework 2.11.1", + "security-framework", ] [[package]] @@ -10486,19 +10542,20 @@ dependencies = [ "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework 2.11.1", + "security-framework", ] [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", + "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework 3.0.1", + "security-framework", ] [[package]] @@ -10534,16 +10591,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" dependencies = [ - "core-foundation 0.9.4", + "core-foundation", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.18", + "rustls 0.23.17", "rustls-native-certs 0.7.3", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "webpki-roots", "winapi", @@ -10653,9 +10710,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.6" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +checksum = "1aa7ffc1c0ef49b0452c6e2986abf2b07743320641ffd5fc63d552458e3b779b" dependencies = [ "cfg-if 1.0.0", "derive_more 1.0.0", @@ -10665,14 +10722,14 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.6" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +checksum = "46385cc24172cf615450267463f937c10072516359b3ff1cb24228a4a08bf951" dependencies = [ "proc-macro-crate 3.2.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -10686,9 +10743,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -10711,10 +10768,10 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "serde_derive_internals", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -10868,26 +10925,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", + "core-foundation", "core-foundation-sys", "libc", "num-bigint 0.4.6", "security-framework-sys", ] -[[package]] -name = "security-framework" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework-sys" version = "2.12.1" @@ -10918,9 +10962,9 @@ dependencies = [ [[package]] name = "semver-parser" -version = "0.10.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" dependencies = [ "pest", ] @@ -11076,9 +11120,9 @@ version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -11087,9 +11131,9 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -11131,9 +11175,9 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -11176,7 +11220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ "darling 0.13.4", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -11214,9 +11258,9 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -11538,12 +11582,116 @@ dependencies = [ "unicode-xid 0.2.6", ] +[[package]] +name = "solar-ast" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5aeaf7a4bd326242c909bd287291226a540b62b36fa5824880248f4b1d4d6af" +dependencies = [ + "alloy-primitives", + "bumpalo", + "either", + "num-bigint 0.4.6", + "num-rational", + "semver 1.0.23", + "solar-data-structures", + "solar-interface", + "solar-macros", + "strum", + "typed-arena", +] + +[[package]] +name = "solar-config" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d00d672a40a1a3620d7696f01a2d3301abf883d8168e1a9da3bf83f0c8e343" +dependencies = [ + "strum", +] + +[[package]] +name = "solar-data-structures" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6e4eb0b72ed7adbb808897c85de08ea99609774a58c72e3dce55c758043ca2" +dependencies = [ + "bumpalo", + "index_vec", + "indexmap 2.6.0", + "parking_lot 0.12.3", + "rayon", + "rustc-hash 2.0.0", + "smallvec", +] + +[[package]] +name = "solar-interface" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fb8925638f3da1bba7a9a6ebeac3511e5c6354f921f2bb2e1ddce4ac70c107" +dependencies = [ + "annotate-snippets", + "anstream", + "anstyle", + "const-hex", + "derive_builder", + "dunce", + "itertools 0.11.0", + "itoa", + "lasso", + "match_cfg", + "normalize-path", + "rayon", + "scc", + "scoped-tls", + "solar-config", + "solar-data-structures", + "solar-macros", + "thiserror 1.0.69", + "tracing", + "unicode-width 0.2.0", +] + +[[package]] +name = "solar-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cc54b74e214647c1bbfc098d080cc5deac77f8dcb99aca91747276b01a15ad" +dependencies = [ + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.87", +] + +[[package]] +name = "solar-parse" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82c3659c15975cd80e5e1c44591278c230c59ad89082d797837499a4784e1b" +dependencies = [ + "alloy-primitives", + "bitflags 2.6.0", + "bumpalo", + "itertools 0.11.0", + "memchr", + "num-bigint 0.4.6", + "num-rational", + "num-traits", + "smallvec", + "solar-ast", + "solar-data-structures", + "solar-interface", + "tracing", +] + [[package]] name = "soldeer-commands" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf7e07f2b6002f8410811915a2f6142f2d1084764dd88cba3f4ebf22232975" +checksum = "f5969c09f89ae6f0e18d5904e5bdbb8842ba948dad0f8202edb7ea510e35654d" dependencies = [ + "bon", "clap", "cliclack", "derive_more 1.0.0", @@ -11554,9 +11702,9 @@ dependencies = [ [[package]] name = "soldeer-core" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea249d0281f3755c3c2b095ad94a554a782cc29138f46c407b8080cfd3918996" +checksum = "e63aeee0e78b5fba04f005d23a58d20f897720212bd21ad744201cacb9dd34f8" dependencies = [ "bon", "chrono", @@ -11648,7 +11796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" dependencies = [ "atoi", - "bigdecimal 0.4.6", + "bigdecimal 0.4.5", "byteorder", "bytes", "chrono", @@ -11691,11 +11839,11 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "sqlx-core", "sqlx-macros-core", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -11709,7 +11857,7 @@ dependencies = [ "heck", "hex", "once_cell", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "serde", "serde_json", @@ -11718,7 +11866,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.89", + "syn 2.0.87", "tempfile", "tokio", "url", @@ -11732,7 +11880,7 @@ checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" dependencies = [ "atoi", "base64 0.22.1", - "bigdecimal 0.4.6", + "bigdecimal 0.4.5", "bitflags 2.6.0", "byteorder", "bytes", @@ -11777,7 +11925,7 @@ checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" dependencies = [ "atoi", "base64 0.22.1", - "bigdecimal 0.4.6", + "bigdecimal 0.4.5", "bitflags 2.6.0", "byteorder", "chrono", @@ -11876,7 +12024,7 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ "phf_generator 0.10.0", "phf_shared 0.10.0", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", ] @@ -11928,10 +12076,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "rustversion", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -12003,32 +12151,44 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.89" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "unicode-ident", ] [[package]] name = "syn-solidity" -version = "0.8.13" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdaa7b9e815582ba343a20c66627437cf45f1c6fba7f69772cbfd1358c7e197" +checksum = "f76fe0a3e1476bdaa0775b9aec5b869ed9520c2b2fedfe9c6df3618f8ea6290b" dependencies = [ "paste", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.87", +] + +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -12039,9 +12199,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" dependencies = [ "futures-core", ] @@ -12052,9 +12212,9 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -12064,7 +12224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys 0.5.0", ] @@ -12075,7 +12235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys 0.6.0", ] @@ -12210,9 +12370,9 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -12221,9 +12381,9 @@ version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -12365,9 +12525,9 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -12396,7 +12556,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.18", + "rustls 0.23.17", "rustls-pki-types", "tokio", ] @@ -12433,7 +12593,7 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.18", + "rustls 0.23.17", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -12535,17 +12695,17 @@ dependencies = [ "axum", "base64 0.22.1", "bytes", - "h2 0.4.7", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.5.0", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project 1.1.7", "prost 0.13.3", - "rustls-native-certs 0.8.1", + "rustls-native-certs 0.8.0", "rustls-pemfile 2.2.0", "socket2", "tokio", @@ -12666,16 +12826,16 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -12823,13 +12983,19 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "rustls 0.23.18", + "rustls 0.23.17", "rustls-pki-types", "sha1", "thiserror 1.0.69", "utf-8", ] +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typemap_rev" version = "0.3.0" @@ -12904,9 +13070,9 @@ checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-linebreak" @@ -13013,9 +13179,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.4" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -13136,9 +13302,9 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a511871dc5de990a3b2a0e715facfbc5da848c0c0395597a1415029fb7c250a" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -13163,7 +13329,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", ] @@ -13233,9 +13399,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -13267,9 +13433,9 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -13295,9 +13461,9 @@ dependencies = [ [[package]] name = "wasmtimer" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ed9d8b15c7fb594d72bfb4b5a276f3d2029333cd93a932f376f5937f6f80ee" +checksum = "bb4f099acbc1043cc752b91615b24b02d7f6fcd975bd781fed9f50b3c3e15bf7" dependencies = [ "futures 0.3.31", "js-sys", @@ -13318,7 +13484,7 @@ dependencies = [ "atomic-take", "futures 0.3.31", "ignore-files", - "miette 7.3.0", + "miette 7.2.0", "nix 0.28.0", "normalize-path", "notify", @@ -13350,7 +13516,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f7ccc54db7df8cbbe3251508321e46986ce179af4c4a03b4c70bda539d72755" dependencies = [ - "miette 7.3.0", + "miette 7.2.0", "nix 0.28.0", "thiserror 1.0.69", ] @@ -13392,9 +13558,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -13530,9 +13696,9 @@ version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -13541,9 +13707,9 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -13552,9 +13718,9 @@ version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -13563,9 +13729,9 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -13852,9 +14018,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" dependencies = [ "serde", "stable_deref_trait", @@ -13864,13 +14030,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "synstructure", ] @@ -13890,29 +14056,29 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", "synstructure", ] @@ -13931,9 +14097,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -13953,16 +14119,16 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] name = "zip" -version = "2.2.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d52293fc86ea7cf13971b3bb81eb21683636e7ae24c729cdaf1b7c4157a352" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "bzip2", @@ -13972,7 +14138,7 @@ dependencies = [ "flate2", "indexmap 2.6.0", "memchr", - "thiserror 2.0.3", + "thiserror 1.0.69", "zopfli", ] @@ -14426,7 +14592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5939e2df4288c263c706ff18ac718e984149223ad4289d6d957d767dcfc04c81" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "syn 1.0.109", ] @@ -14437,7 +14603,7 @@ version = "0.1.0" source = "git+https://github.com/matter-labs/zksync-era.git?rev=6c034f6e180cc92e99766f14c8840c90efa56cec#6c034f6e180cc92e99766f14c8840c90efa56cec" dependencies = [ "anyhow", - "bigdecimal 0.4.6", + "bigdecimal 0.4.5", "bincode", "chrono", "hex", @@ -14507,7 +14673,7 @@ dependencies = [ "num-bigint 0.4.6", "num-integer", "num-traits", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "quote 1.0.37", "serde", "syn 1.0.109", @@ -14655,12 +14821,12 @@ dependencies = [ "anyhow", "heck", "prettyplease", - "proc-macro2 1.0.92", + "proc-macro2 1.0.89", "prost-build", "prost-reflect", "protox", "quote 1.0.37", - "syn 2.0.89", + "syn 2.0.87", ] [[package]] @@ -14759,7 +14925,7 @@ version = "0.1.0" source = "git+https://github.com/matter-labs/zksync-era.git?rev=6c034f6e180cc92e99766f14c8840c90efa56cec#6c034f6e180cc92e99766f14c8840c90efa56cec" dependencies = [ "anyhow", - "bigdecimal 0.4.6", + "bigdecimal 0.4.5", "blake2 0.10.6", "chrono", "derive_more 1.0.0", @@ -14792,7 +14958,7 @@ version = "0.1.0" source = "git+https://github.com/matter-labs/zksync-era.git?rev=6c034f6e180cc92e99766f14c8840c90efa56cec#6c034f6e180cc92e99766f14c8840c90efa56cec" dependencies = [ "anyhow", - "bigdecimal 0.4.6", + "bigdecimal 0.4.5", "futures 0.3.31", "hex", "num", @@ -14882,7 +15048,7 @@ dependencies = [ "jsonrpsee", "pin-project-lite", "rlp", - "rustls 0.23.18", + "rustls 0.23.17", "serde", "serde_json", "thiserror 1.0.69", diff --git a/Cargo.toml b/Cargo.toml index cad9fb0db..23cb3b0e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -175,44 +175,44 @@ foundry-zksync-compiler = { path = "crates/zksync/compiler" } foundry-zksync-inspectors = { path = "crates/zksync/inspectors" } # solc & compilation utilities -# foundry-block-explorers = { version = "0.7.3", default-features = false } -# foundry-compilers = { version = "0.11.6", default-features = false } -# foundry-fork-db = "0.6.0" -foundry-block-explorers = { git = "https://github.com/Moonsong-Labs/block-explorers", branch = "zksync-v0.7.3", default-features = false } -foundry-compilers = { git = "https://github.com/Moonsong-Labs/compilers", branch = "zksync-v0.11.6" } -foundry-fork-db = { git = "https://github.com/Moonsong-Labs/foundry-zksync-fork-db", branch = "zksync-v0.6.0" } +# foundry-block-explorers = { version = "0.9.0", default-features = false } +# foundry-compilers = { version = "0.12.3", default-features = false } +# foundry-fork-db = "0.7.0" +foundry-block-explorers = { git = "https://github.com/Moonsong-Labs/block-explorers", branch = "zksync-v0.9.0", default-features = false } +foundry-compilers = { git = "https://github.com/Moonsong-Labs/compilers", branch = "zksync-v0.12.3" } +foundry-fork-db = { git = "https://github.com/Moonsong-Labs/foundry-zksync-fork-db", branch = "zksync-v0.7.1" } solang-parser = "=0.3.3" ## revm -revm = { version = "17.1.0", default-features = false } -revm-primitives = { version = "13.0.0", default-features = false } -revm-inspectors = { version = "0.10.0", features = ["serde"] } +revm = { version = "18.0.0", default-features = false } +revm-primitives = { version = "14.0.0", default-features = false } +revm-inspectors = { version = "0.11.0", features = ["serde"] } ## ethers ethers-contract-abigen = { version = "2.0.14", default-features = false } ## alloy -alloy-consensus = { version = "0.5.4", default-features = false } -alloy-contract = { version = "0.5.4", default-features = false } -alloy-eips = { version = "0.5.4", default-features = false } -alloy-genesis = { version = "0.5.4", default-features = false } -alloy-json-rpc = { version = "0.5.4", default-features = false } -alloy-network = { version = "0.5.4", default-features = false } -alloy-provider = { version = "0.5.4", default-features = false } -alloy-pubsub = { version = "0.5.4", default-features = false } -alloy-rpc-client = { version = "0.5.4", default-features = false } -alloy-rpc-types = { version = "0.5.4", default-features = true } -alloy-serde = { version = "0.5.4", default-features = false } -alloy-signer = { version = "0.5.4", default-features = false } -alloy-signer-aws = { version = "0.5.4", default-features = false } -alloy-signer-gcp = { version = "0.5.4", default-features = false } -alloy-signer-ledger = { version = "0.5.4", default-features = false } -alloy-signer-local = { version = "0.5.4", default-features = false } -alloy-signer-trezor = { version = "0.5.4", default-features = false } -alloy-transport = { version = "0.5.4", default-features = false } -alloy-transport-http = { version = "0.5.4", default-features = false } -alloy-transport-ipc = { version = "0.5.4", default-features = false } -alloy-transport-ws = { version = "0.5.4", default-features = false } +alloy-consensus = { version = "0.6.4", default-features = false } +alloy-contract = { version = "0.6.4", default-features = false } +alloy-eips = { version = "0.6.4", default-features = false } +alloy-genesis = { version = "0.6.4", default-features = false } +alloy-json-rpc = { version = "0.6.4", default-features = false } +alloy-network = { version = "0.6.4", default-features = false } +alloy-provider = { version = "0.6.4", default-features = false } +alloy-pubsub = { version = "0.6.4", default-features = false } +alloy-rpc-client = { version = "0.6.4", default-features = false } +alloy-rpc-types = { version = "0.6.4", default-features = true } +alloy-serde = { version = "0.6.4", default-features = false } +alloy-signer = { version = "0.6.4", default-features = false } +alloy-signer-aws = { version = "0.6.4", default-features = false } +alloy-signer-gcp = { version = "0.6.4", default-features = false } +alloy-signer-ledger = { version = "0.6.4", default-features = false } +alloy-signer-local = { version = "0.6.4", default-features = false } +alloy-signer-trezor = { version = "0.6.4", default-features = false } +alloy-transport = { version = "0.6.4", default-features = false } +alloy-transport-http = { version = "0.6.4", default-features = false } +alloy-transport-ipc = { version = "0.6.4", default-features = false } +alloy-transport-ws = { version = "0.6.4", default-features = false } ## alloy-core alloy-dyn-abi = "0.8.11" @@ -230,11 +230,11 @@ syn-solidity = "0.8.11" alloy-chains = "0.1" alloy-rlp = "0.3" alloy-trie = "0.6.0" -alloy-zksync = "0.5" +alloy-zksync = "0.6.1" ## op-alloy -op-alloy-rpc-types = "0.5.0" -op-alloy-consensus = "0.5.0" +op-alloy-rpc-types = "0.6.5" +op-alloy-consensus = "0.6.5" ## cli anstream = "0.6" @@ -299,7 +299,7 @@ semver = "1" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["arbitrary_precision"] } similar-asserts = "1.6" -soldeer-commands = "=0.4.1" +soldeer-commands = "=0.5.1" strum = "0.26" tempfile = "3.13" tikv-jemallocator = "0.6" @@ -349,32 +349,3 @@ yansi = { version = "1.0", features = ["detect-tty", "detect-env"] } # alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } - -alloy-rpc-client = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-signer-ledger = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-rpc-types-txpool = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-signer-trezor = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-json-rpc = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-signer = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-consensus = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-transport-http = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-rpc-types-anvil = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-serde = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-transport-ws = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-signer-local = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-genesis = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-contract = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-provider = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-signer-aws = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-rpc-types-eth = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-network-primitives = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-transport-ipc = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-pubsub = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-transport = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-rpc-types = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-eips = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-network = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-rpc-types-engine = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-rpc-types-trace = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } -alloy-signer-gcp = { git = "https://github.com/Karrq/alloy", branch = "zksync-v0.5.4" } diff --git a/clippy.toml b/clippy.toml index 3e45486a8..b1756dfd9 100644 --- a/clippy.toml +++ b/clippy.toml @@ -3,10 +3,10 @@ msrv = "1.80" # so it is safe to ignore it as well ignore-interior-mutability = ["bytes::Bytes", "alloy_primitives::Bytes"] -# disallowed-macros = [ -# # See `foundry_common::shell` -# { path = "std::print", reason = "use `sh_print` or similar macros instead" }, -# { path = "std::eprint", reason = "use `sh_eprint` or similar macros instead" }, -# { path = "std::println", reason = "use `sh_println` or similar macros instead" }, -# { path = "std::eprintln", reason = "use `sh_eprintln` or similar macros instead" }, -# ] +disallowed-macros = [ + # See `foundry_common::shell` + { path = "std::print", reason = "use `sh_print` or similar macros instead" }, + { path = "std::eprint", reason = "use `sh_eprint` or similar macros instead" }, + { path = "std::println", reason = "use `sh_println` or similar macros instead" }, + { path = "std::eprintln", reason = "use `sh_eprintln` or similar macros instead" }, +] diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 4c3cbc4f7..b3389d2ec 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -67,7 +67,7 @@ alloy-transport.workspace = true alloy-chains.workspace = true alloy-genesis.workspace = true alloy-trie.workspace = true -op-alloy-consensus.workspace = true +op-alloy-consensus = { workspace = true, features = ["serde"] } # axum related axum.workspace = true diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index dcf8bf508..dacc7f20e 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -22,7 +22,7 @@ revm = { workspace = true, default-features = false, features = [ "c-kzg", ] } -alloy-primitives = { workspace = true, features = ["serde"] } +alloy-primitives = { workspace = true, features = ["serde", "rlp"] } alloy-rpc-types = { workspace = true, features = ["anvil", "trace"] } alloy-serde.workspace = true alloy-rlp.workspace = true @@ -30,8 +30,8 @@ alloy-eips.workspace = true alloy-consensus = { workspace = true, features = ["k256", "kzg"] } alloy-dyn-abi = { workspace = true, features = ["std", "eip712"] } alloy-trie.workspace = true -op-alloy-consensus.workspace = true - +op-alloy-consensus = { workspace = true, features = ["serde"] } +alloy-network.workspace = true serde = { workspace = true, optional = true } serde_json.workspace = true bytes.workspace = true diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index 73c133b2c..b1d3b8522 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -18,7 +18,6 @@ pub mod proof; pub mod subscription; pub mod transaction; pub mod trie; -pub mod utils; pub mod wallet; #[cfg(feature = "serde")] @@ -394,6 +393,13 @@ pub enum EthRequest { )] SetIntervalMining(u64), + /// Gets the current mining behavior + #[cfg_attr( + feature = "serde", + serde(rename = "anvil_getIntervalMining", with = "empty_params") + )] + GetIntervalMining(()), + /// Removes transactions from the pool #[cfg_attr( feature = "serde", diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index 827f14a55..8de659799 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -6,22 +6,23 @@ use alloy_consensus::{ eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar}, TxEip7702, }, - AnyReceiptEnvelope, Receipt, ReceiptEnvelope, ReceiptWithBloom, Signed, TxEip1559, TxEip2930, - TxEnvelope, TxLegacy, TxReceipt, TxType, + AnyReceiptEnvelope, Receipt, ReceiptEnvelope, ReceiptWithBloom, Signed, Transaction, TxEip1559, + TxEip2930, TxEnvelope, TxLegacy, TxReceipt, }; use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Encodable2718}; +use alloy_network::{AnyRpcTransaction, AnyTxEnvelope}; use alloy_primitives::{ - Address, Bloom, Bytes, Log, Parity, Signature, TxHash, TxKind, B256, U256, U64, + Address, Bloom, Bytes, Log, PrimitiveSignature, TxHash, TxKind, B256, U256, U64, }; use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; use alloy_rpc_types::{ request::TransactionRequest, trace::otterscan::OtsReceipt, AccessList, AnyTransactionReceipt, - ConversionError, Signature as RpcSignature, Transaction as RpcTransaction, TransactionReceipt, + ConversionError, Transaction as RpcTransaction, TransactionReceipt, }; use alloy_serde::{OtherFields, WithOtherFields}; use bytes::BufMut; use foundry_evm::traces::CallTraceNode; -use op_alloy_consensus::TxDeposit; +use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID}; use revm::{ interpreter::InstructionResult, primitives::{OptimismFields, TxEnv}, @@ -278,162 +279,64 @@ pub fn to_alloy_transaction_with_hash_and_sender( from: Address, ) -> RpcTransaction { match transaction { - TypedTransaction::Legacy(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.tx().to.to().copied(), - value: t.tx().value, - gas_price: Some(t.tx().gas_price), - max_fee_per_gas: Some(t.tx().gas_price), - max_priority_fee_per_gas: Some(t.tx().gas_price), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: t.tx().chain_id, - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: None, - }), - access_list: None, - transaction_type: Some(0), - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, - TypedTransaction::EIP2930(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.tx().to.to().copied(), - value: t.tx().value, - gas_price: Some(t.tx().gas_price), - max_fee_per_gas: Some(t.tx().gas_price), - max_priority_fee_per_gas: Some(t.tx().gas_price), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: Some(t.tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().access_list.clone()), - transaction_type: Some(1), - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, - TypedTransaction::EIP1559(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.tx().to.to().copied(), - value: t.tx().value, - gas_price: None, - max_fee_per_gas: Some(t.tx().max_fee_per_gas), - max_priority_fee_per_gas: Some(t.tx().max_priority_fee_per_gas), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: Some(t.tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().access_list.clone()), - transaction_type: Some(2), - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, - TypedTransaction::EIP4844(t) => RpcTransaction { - hash, - nonce: t.tx().tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: Some(t.tx().tx().to), - value: t.tx().tx().value, - gas_price: Some(t.tx().tx().max_fee_per_gas), - max_fee_per_gas: Some(t.tx().tx().max_fee_per_gas), - max_priority_fee_per_gas: Some(t.tx().tx().max_priority_fee_per_gas), - gas: t.tx().tx().gas_limit, - input: t.tx().tx().input.clone(), - chain_id: Some(t.tx().tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().tx().access_list.clone()), - transaction_type: Some(3), - max_fee_per_blob_gas: Some(t.tx().tx().max_fee_per_blob_gas), - blob_versioned_hashes: Some(t.tx().tx().blob_versioned_hashes.clone()), - authorization_list: None, - }, - TypedTransaction::EIP7702(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: Some(t.tx().to), - value: t.tx().value, - gas_price: Some(t.tx().max_fee_per_gas), - max_fee_per_gas: Some(t.tx().max_fee_per_gas), - max_priority_fee_per_gas: Some(t.tx().max_priority_fee_per_gas), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: Some(t.tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().access_list.clone()), - transaction_type: Some(4), - authorization_list: Some(t.tx().authorization_list.clone()), - ..Default::default() - }, - TypedTransaction::Deposit(t) => RpcTransaction { - hash, - nonce: t.nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.kind.to().copied(), - value: t.value, - gas_price: None, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - gas: t.gas_limit, - input: t.input.clone().0.into(), - chain_id: t.chain_id().map(u64::from), - signature: None, - access_list: None, - transaction_type: None, - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, + TypedTransaction::Legacy(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Legacy(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP2930(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip2930(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP1559(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip1559(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP4844(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip4844(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP7702(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip7702(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::Deposit(_t) => { + unreachable!("cannot reach here, handled in `transaction_build` ") + } } } @@ -681,7 +584,8 @@ impl TryFrom for TransactionRequest { type Error = ConversionError; fn try_from(value: TypedTransaction) -> Result { - let from = value.recover().map_err(|_| ConversionError::InvalidSignature)?; + let from = + value.recover().map_err(|_| ConversionError::Custom("InvalidSignature".to_string()))?; let essentials = value.essentials(); let tx_type = value.r#type(); Ok(Self { @@ -702,8 +606,77 @@ impl TryFrom for TransactionRequest { } } +impl TryFrom for TypedTransaction { + type Error = ConversionError; + + fn try_from(value: AnyRpcTransaction) -> Result { + let AnyRpcTransaction { inner, .. } = value; + let from = inner.from; + match inner.inner { + AnyTxEnvelope::Ethereum(tx) => match tx { + TxEnvelope::Legacy(tx) => Ok(Self::Legacy(tx)), + TxEnvelope::Eip2930(tx) => Ok(Self::EIP2930(tx)), + TxEnvelope::Eip1559(tx) => Ok(Self::EIP1559(tx)), + TxEnvelope::Eip4844(tx) => Ok(Self::EIP4844(tx)), + TxEnvelope::Eip7702(tx) => Ok(Self::EIP7702(tx)), + _ => Err(ConversionError::Custom("UnsupportedTxType".to_string())), + }, + AnyTxEnvelope::Unknown(mut tx) => { + // Try to convert to deposit transaction + if tx.ty() == DEPOSIT_TX_TYPE_ID { + let nonce = get_field::(&tx.inner.fields, "nonce")?; + tx.inner.fields.insert("from".to_string(), serde_json::to_value(from).unwrap()); + let deposit_tx = + tx.inner.fields.deserialize_into::().map_err(|e| { + ConversionError::Custom(format!( + "Failed to deserialize deposit tx: {e}" + )) + })?; + + let TxDeposit { + source_hash, + is_system_transaction, + value, + gas_limit, + input, + mint, + from, + to, + } = deposit_tx; + + let deposit_tx = DepositTransaction { + nonce: nonce.to(), + source_hash, + from, + kind: to, + mint: mint.map(|m| U256::from(m)).unwrap_or_default(), + value, + gas_limit, + is_system_tx: is_system_transaction, + input, + }; + + return Ok(Self::Deposit(deposit_tx)); + }; + + Err(ConversionError::Custom("UnknownTxType".to_string())) + } + } + } +} + +fn get_field( + fields: &OtherFields, + key: &str, +) -> Result { + fields + .get_deserialized::(key) + .ok_or_else(|| ConversionError::Custom(format!("Missing{key}")))? + .map_err(|e| ConversionError::Custom(format!("Failed to deserialize {key}: {e}"))) +} + impl TypedTransaction { - /// Returns true if the transaction uses dynamic fees: EIP1559 or EIP4844 + /// Returns true if the transaction uses dynamic fees: EIP1559, EIP4844 or EIP7702 pub fn is_dynamic_fee(&self) -> bool { matches!(self, Self::EIP1559(_) | Self::EIP4844(_) | Self::EIP7702(_)) } @@ -992,168 +965,18 @@ impl TypedTransaction { } /// Returns the Signature of the transaction - pub fn signature(&self) -> Signature { + pub fn signature(&self) -> PrimitiveSignature { match self { Self::Legacy(tx) => *tx.signature(), Self::EIP2930(tx) => *tx.signature(), Self::EIP1559(tx) => *tx.signature(), Self::EIP4844(tx) => *tx.signature(), Self::EIP7702(tx) => *tx.signature(), - Self::Deposit(_) => Signature::from_scalars_and_parity( + Self::Deposit(_) => PrimitiveSignature::from_scalars_and_parity( B256::with_last_byte(1), B256::with_last_byte(1), - Parity::Parity(false), - ) - .unwrap(), - } - } -} - -impl TryFrom> for TypedTransaction { - type Error = ConversionError; - - fn try_from(tx: WithOtherFields) -> Result { - if tx.transaction_type.is_some_and(|t| t == 0x7E) { - let mint = tx - .other - .get_deserialized::("mint") - .ok_or(ConversionError::Custom("MissingMint".to_string()))? - .map_err(|_| ConversionError::Custom("Cannot deserialize mint".to_string()))?; - - let source_hash = tx - .other - .get_deserialized::("sourceHash") - .ok_or(ConversionError::Custom("MissingSourceHash".to_string()))? - .map_err(|_| { - ConversionError::Custom("Cannot deserialize source hash".to_string()) - })?; - - let deposit = DepositTransaction { - nonce: tx.nonce, - is_system_tx: true, - from: tx.from, - kind: tx.to.map(TxKind::Call).unwrap_or(TxKind::Create), - value: tx.value, - gas_limit: tx.gas, - input: tx.input.clone(), - mint, - source_hash, - }; - - return Ok(Self::Deposit(deposit)); - } - - let tx = tx.inner; - match tx.transaction_type.unwrap_or_default().try_into()? { - TxType::Legacy => { - let legacy = TxLegacy { - chain_id: tx.chain_id, - nonce: tx.nonce, - gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - gas_limit: tx.gas, - value: tx.value, - input: tx.input, - to: tx.to.map_or(TxKind::Create, TxKind::Call), - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::Legacy(Signed::new_unchecked(legacy, signature, tx.hash))) - } - TxType::Eip1559 => { - let eip1559 = TxEip1559 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - max_fee_per_gas: tx - .max_fee_per_gas - .ok_or(ConversionError::MissingMaxFeePerGas)?, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, - gas_limit: tx.gas, - value: tx.value, - input: tx.input, - to: tx.to.map_or(TxKind::Create, TxKind::Call), - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::EIP1559(Signed::new_unchecked(eip1559, signature, tx.hash))) - } - TxType::Eip2930 => { - let eip2930 = TxEip2930 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - gas_limit: tx.gas, - value: tx.value, - input: tx.input, - to: tx.to.map_or(TxKind::Create, TxKind::Call), - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::EIP2930(Signed::new_unchecked(eip2930, signature, tx.hash))) - } - TxType::Eip4844 => { - let eip4844 = TxEip4844 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - gas_limit: tx.gas, - max_fee_per_gas: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, - max_fee_per_blob_gas: tx - .max_fee_per_blob_gas - .ok_or(ConversionError::MissingMaxFeePerBlobGas)?, - to: tx.to.ok_or(ConversionError::MissingTo)?, - value: tx.value, - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - blob_versioned_hashes: tx - .blob_versioned_hashes - .ok_or(ConversionError::MissingBlobVersionedHashes)?, - input: tx.input, - }; - Ok(Self::EIP4844(Signed::new_unchecked( - TxEip4844Variant::TxEip4844(eip4844), - tx.signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?, - tx.hash, - ))) - } - TxType::Eip7702 => { - let eip7702 = TxEip7702 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - gas_limit: tx.gas, - max_fee_per_gas: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, - to: tx.to.ok_or(ConversionError::MissingTo)?, - value: tx.value, - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - input: tx.input, - authorization_list: tx.authorization_list.unwrap_or_default(), - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::EIP7702(Signed::new_unchecked(eip7702, signature, tx.hash))) - } + false, + ), } } } @@ -1200,10 +1023,7 @@ impl Encodable2718 for TypedTransaction { Self::EIP2930(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), Self::EIP1559(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), Self::EIP4844(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), - Self::EIP7702(tx) => { - let payload_length = tx.tx().fields_len() + tx.signature().rlp_vrs_len(); - Header { list: true, payload_length }.length() + payload_length + 1 - } + Self::EIP7702(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), Self::Deposit(tx) => 1 + tx.length(), } } @@ -1214,7 +1034,7 @@ impl Encodable2718 for TypedTransaction { Self::EIP2930(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), Self::EIP1559(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), Self::EIP4844(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), - Self::EIP7702(tx) => tx.tx().encode_with_signature(tx.signature(), out, false), + Self::EIP7702(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), Self::Deposit(tx) => { tx.encode_2718(out); } @@ -1224,15 +1044,14 @@ impl Encodable2718 for TypedTransaction { impl Decodable2718 for TypedTransaction { fn typed_decode(ty: u8, buf: &mut &[u8]) -> Result { - match ty { - 0x04 => return Ok(Self::EIP7702(TxEip7702::decode_signed_fields(buf)?)), - 0x7E => return Ok(Self::Deposit(DepositTransaction::decode(buf)?)), - _ => {} + if ty == 0x7E { + return Ok(Self::Deposit(DepositTransaction::decode(buf)?)) } match TxEnvelope::typed_decode(ty, buf)? { TxEnvelope::Eip2930(tx) => Ok(Self::EIP2930(tx)), TxEnvelope::Eip1559(tx) => Ok(Self::EIP1559(tx)), TxEnvelope::Eip4844(tx) => Ok(Self::EIP4844(tx)), + TxEnvelope::Eip7702(tx) => Ok(Self::EIP7702(tx)), _ => unreachable!(), } } @@ -1703,7 +1522,7 @@ mod tests { chain_id: Some(4), }; - let signature = Signature::from_str("0eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca182b").unwrap(); + let signature = PrimitiveSignature::from_str("0eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca182b").unwrap(); let tx = TypedTransaction::Legacy(Signed::new_unchecked( tx, diff --git a/crates/anvil/core/src/eth/utils.rs b/crates/anvil/core/src/eth/utils.rs deleted file mode 100644 index a60439280..000000000 --- a/crates/anvil/core/src/eth/utils.rs +++ /dev/null @@ -1,13 +0,0 @@ -use alloy_primitives::Parity; - -/// See -/// > If you do, then the v of the signature MUST be set to {0,1} + CHAIN_ID * 2 + 35 where -/// > {0,1} is the parity of the y value of the curve point for which r is the x-value in the -/// > secp256k1 signing process. -pub fn meets_eip155(chain_id: u64, v: Parity) -> bool { - let double_chain_id = chain_id.saturating_mul(2); - match v { - Parity::Eip155(v) => v == double_chain_id + 35 || v == double_chain_id + 36, - _ => false, - } -} diff --git a/crates/anvil/src/anvil.rs b/crates/anvil/src/anvil.rs index 5e2a42f59..48e17ed44 100644 --- a/crates/anvil/src/anvil.rs +++ b/crates/anvil/src/anvil.rs @@ -3,7 +3,7 @@ use anvil::cmd::NodeArgs; use clap::{CommandFactory, Parser, Subcommand}; use eyre::Result; -use foundry_cli::{opts::ShellOpts, utils}; +use foundry_cli::{opts::GlobalOpts, utils}; #[cfg(all(feature = "jemalloc", unix))] #[global_allocator] @@ -13,14 +13,15 @@ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; #[derive(Parser)] #[command(name = "anvil", version = anvil::VERSION_MESSAGE, next_display_order = None)] pub struct Anvil { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(flatten)] pub node: NodeArgs, #[command(subcommand)] pub cmd: Option, - - #[clap(flatten)] - pub shell: ShellOpts, } #[derive(Subcommand)] @@ -48,7 +49,7 @@ fn run() -> Result<()> { utils::load_dotenv(); let mut args = Anvil::parse(); - args.shell.shell().set(); + args.global.init()?; args.node.evm_opts.resolve_rpc_alias(); if let Some(cmd) = &args.cmd { diff --git a/crates/anvil/src/cmd.rs b/crates/anvil/src/cmd.rs index 839dae016..eda009418 100644 --- a/crates/anvil/src/cmd.rs +++ b/crates/anvil/src/cmd.rs @@ -189,6 +189,10 @@ pub struct NodeArgs { #[command(flatten)] pub server_config: ServerConfig, + + /// Path to the cache directory where states are stored. + #[arg(long, value_name = "PATH")] + pub cache_path: Option, } #[cfg(windows)] @@ -274,7 +278,8 @@ impl NodeArgs { .with_alphanet(self.evm_opts.alphanet) .with_disable_default_create2_deployer(self.evm_opts.disable_default_create2_deployer) .with_slots_in_an_epoch(self.slots_in_an_epoch) - .with_memory_limit(self.evm_opts.memory_limit)) + .with_memory_limit(self.evm_opts.memory_limit) + .with_cache_path(self.cache_path)) } fn account_generator(&self) -> AccountGenerator { diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index 556175818..ada482329 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -15,12 +15,12 @@ use crate::{ mem::{self, in_memory_db::MemDb}, EthereumHardfork, FeeManager, PrecompileFactory, }; +use alloy_consensus::BlockHeader; use alloy_genesis::Genesis; -use alloy_network::AnyNetwork; +use alloy_network::{AnyNetwork, TransactionResponse}; use alloy_primitives::{hex, map::HashMap, utils::Unit, BlockNumber, TxHash, U256}; use alloy_provider::Provider; -use alloy_rpc_types::{Block, BlockNumberOrTag, Transaction}; -use alloy_serde::WithOtherFields; +use alloy_rpc_types::{Block, BlockNumberOrTag}; use alloy_signer::Signer; use alloy_signer_local::{ coins_bip39::{English, Mnemonic}, @@ -189,6 +189,8 @@ pub struct NodeConfig { pub alphanet: bool, /// Do not print log messages. pub silent: bool, + /// The path where states are cached. + pub cache_path: Option, } impl NodeConfig { @@ -465,6 +467,7 @@ impl Default for NodeConfig { precompile_factory: None, alphanet: false, silent: false, + cache_path: None, } } } @@ -969,6 +972,13 @@ impl NodeConfig { self } + /// Sets the path where states are cached + #[must_use] + pub fn with_cache_path(mut self, cache_path: Option) -> Self { + self.cache_path = cache_path; + self + } + /// Configures everything related to env, backend and database and returns the /// [Backend](mem::Backend) /// @@ -1051,6 +1061,7 @@ impl NodeConfig { self.max_persisted_states, self.transaction_block_keeper, self.block_time, + self.cache_path.clone(), Arc::new(tokio::sync::RwLock::new(self.clone())), ) .await; @@ -1291,12 +1302,15 @@ latest block number: {latest_block}" /// we only use the gas limit value of the block if it is non-zero and the block gas /// limit is enabled, since there are networks where this is not used and is always /// `0x0` which would inevitably result in `OutOfGas` errors as soon as the evm is about to record gas, See also - pub(crate) fn fork_gas_limit(&self, block: &Block>) -> u128 { + pub(crate) fn fork_gas_limit( + &self, + block: &Block, + ) -> u128 { if !self.disable_block_gas_limit { if let Some(gas_limit) = self.gas_limit { return gas_limit; - } else if block.header.gas_limit > 0 { - return block.header.gas_limit as u128; + } else if block.header.gas_limit() > 0 { + return block.header.gas_limit() as u128; } } @@ -1335,19 +1349,21 @@ async fn derive_block_and_transactions( // Get the block pertaining to the fork transaction let transaction_block = provider - .get_block_by_number(transaction_block_number.into(), true) + .get_block_by_number( + transaction_block_number.into(), + alloy_rpc_types::BlockTransactionsKind::Full, + ) .await? .ok_or(eyre::eyre!("Failed to get fork block by number"))?; // Filter out transactions that are after the fork transaction - let filtered_transactions: Vec<&alloy_serde::WithOtherFields> = - transaction_block - .transactions - .as_transactions() - .ok_or(eyre::eyre!("Failed to get transactions from full fork block"))? - .iter() - .take_while_inclusive(|&transaction| transaction.hash != transaction_hash.0) - .collect(); + let filtered_transactions = transaction_block + .transactions + .as_transactions() + .ok_or(eyre::eyre!("Failed to get transactions from full fork block"))? + .iter() + .take_while_inclusive(|&transaction| transaction.tx_hash() != transaction_hash.0) + .collect::>(); // Convert the transactions to PoolTransactions let force_transactions = filtered_transactions diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 81990d755..daf9dc4a0 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -30,15 +30,16 @@ use crate::{ revm::primitives::{BlobExcessGasAndPrice, Output}, ClientFork, LoggingManager, Miner, MiningMode, StorageInfo, }; -use alloy_consensus::{transaction::eip4844::TxEip4844Variant, Account, TxEnvelope}; +use alloy_consensus::{transaction::eip4844::TxEip4844Variant, Account}; use alloy_dyn_abi::TypedData; use alloy_eips::eip2718::Encodable2718; use alloy_network::{ - eip2718::Decodable2718, BlockResponse, Ethereum, NetworkWallet, TransactionBuilder, + eip2718::Decodable2718, AnyRpcBlock, AnyRpcTransaction, BlockResponse, Ethereum, NetworkWallet, + TransactionBuilder, TransactionResponse, }; use alloy_primitives::{ map::{HashMap, HashSet}, - Address, Bytes, Parity, TxHash, TxKind, B256, B64, U256, U64, + Address, Bytes, PrimitiveSignature as Signature, TxHash, TxKind, B256, B64, U256, U64, }; use alloy_provider::utils::{ eip1559_default_estimator, EIP1559_FEE_ESTIMATION_PAST_BLOCKS, @@ -56,12 +57,10 @@ use alloy_rpc_types::{ parity::LocalizedTransactionTrace, }, txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus}, - AccessList, AccessListResult, AnyNetworkBlock, BlockId, BlockNumberOrTag as BlockNumber, - BlockTransactions, EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, - Transaction, + AccessList, AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, + EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, }; use alloy_serde::WithOtherFields; -use alloy_signer::Signature; use alloy_transport::TransportErrorKind; use anvil_core::{ eth::{ @@ -326,6 +325,7 @@ impl EthApi { EthRequest::SetIntervalMining(interval) => { self.anvil_set_interval_mining(interval).to_rpc_result() } + EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(), EthRequest::DropTransaction(tx) => { self.anvil_drop_transaction(tx).await.to_rpc_result() } @@ -474,13 +474,11 @@ impl EthApi { ) -> Result { match request { TypedTransactionRequest::Deposit(_) => { - let nil_signature: alloy_primitives::Signature = - alloy_primitives::Signature::from_scalars_and_parity( - B256::with_last_byte(1), - B256::with_last_byte(1), - Parity::Parity(false), - ) - .unwrap(); + let nil_signature = Signature::from_scalars_and_parity( + B256::with_last_byte(1), + B256::with_last_byte(1), + false, + ); return build_typed_transaction(request, nil_signature) } _ => { @@ -513,10 +511,7 @@ impl EthApi { match self.pool.get_transaction(hash) { Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())), None => match self.backend.transaction_by_hash(hash).await? { - Some(tx) => TxEnvelope::try_from(tx.inner) - .map_or(Err(BlockchainError::FailedToDecodeTransaction), |tx| { - Ok(Some(tx.encoded_2718().into())) - }), + Some(tx) => Ok(Some(tx.inner.inner.encoded_2718().into())), None => Ok(None), }, } @@ -741,7 +736,7 @@ impl EthApi { /// Returns block with given hash. /// /// Handler for ETH RPC call: `eth_getBlockByHash` - pub async fn block_by_hash(&self, hash: B256) -> Result> { + pub async fn block_by_hash(&self, hash: B256) -> Result> { node_info!("eth_getBlockByHash"); self.backend.block_by_hash(hash).await } @@ -749,7 +744,7 @@ impl EthApi { /// Returns a _full_ block with given hash. /// /// Handler for ETH RPC call: `eth_getBlockByHash` - pub async fn block_by_hash_full(&self, hash: B256) -> Result> { + pub async fn block_by_hash_full(&self, hash: B256) -> Result> { node_info!("eth_getBlockByHash"); self.backend.block_by_hash_full(hash).await } @@ -757,7 +752,7 @@ impl EthApi { /// Returns block with given number. /// /// Handler for ETH RPC call: `eth_getBlockByNumber` - pub async fn block_by_number(&self, number: BlockNumber) -> Result> { + pub async fn block_by_number(&self, number: BlockNumber) -> Result> { node_info!("eth_getBlockByNumber"); if number == BlockNumber::Pending { return Ok(Some(self.pending_block().await)); @@ -769,10 +764,7 @@ impl EthApi { /// Returns a _full_ block with given number /// /// Handler for ETH RPC call: `eth_getBlockByNumber` - pub async fn block_by_number_full( - &self, - number: BlockNumber, - ) -> Result> { + pub async fn block_by_number_full(&self, number: BlockNumber) -> Result> { node_info!("eth_getBlockByNumber"); if number == BlockNumber::Pending { return Ok(self.pending_block_full().await); @@ -1184,10 +1176,7 @@ impl EthApi { /// this will also scan the mempool for a matching pending transaction /// /// Handler for ETH RPC call: `eth_getTransactionByHash` - pub async fn transaction_by_hash( - &self, - hash: B256, - ) -> Result>> { + pub async fn transaction_by_hash(&self, hash: B256) -> Result> { node_info!("eth_getTransactionByHash"); let mut tx = self.pool.get_transaction(hash).map(|pending| { let from = *pending.sender(); @@ -1217,7 +1206,7 @@ impl EthApi { &self, hash: B256, index: Index, - ) -> Result>> { + ) -> Result> { node_info!("eth_getTransactionByBlockHashAndIndex"); self.backend.transaction_by_block_hash_and_index(hash, index).await } @@ -1229,7 +1218,7 @@ impl EthApi { &self, block: BlockNumber, idx: Index, - ) -> Result>> { + ) -> Result> { node_info!("eth_getTransactionByBlockNumberAndIndex"); self.backend.transaction_by_block_number_and_index(block, idx).await } @@ -1261,7 +1250,7 @@ impl EthApi { &self, block_hash: B256, idx: Index, - ) -> Result> { + ) -> Result> { node_info!("eth_getUncleByBlockHashAndIndex"); let number = self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?; @@ -1281,7 +1270,7 @@ impl EthApi { &self, block_number: BlockNumber, idx: Index, - ) -> Result> { + ) -> Result> { node_info!("eth_getUncleByBlockNumberAndIndex"); let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?; if let Some(fork) = self.get_fork() { @@ -1543,7 +1532,7 @@ impl EthApi { ) -> Result> { node_info!("eth_getRawTransactionByBlockHashAndIndex"); match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? { - Some(tx) => self.inner_raw_transaction(tx.hash).await, + Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await, None => Ok(None), } } @@ -1558,7 +1547,7 @@ impl EthApi { ) -> Result> { node_info!("eth_getRawTransactionByBlockNumberAndIndex"); match self.backend.transaction_by_block_number_and_index(block_number, index).await? { - Some(tx) => self.inner_raw_transaction(tx.hash).await, + Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await, None => Ok(None), } } @@ -1665,6 +1654,14 @@ impl EthApi { Ok(self.miner.is_auto_mine()) } + /// Returns the value of mining interval, if set. + /// + /// Handler for ETH RPC call: `anvil_getIntervalMining`. + pub fn anvil_get_interval_mining(&self) -> Result> { + node_info!("anvil_getIntervalMining"); + Ok(self.miner.get_interval()) + } + /// Enables or disables, based on the single boolean argument, the automatic mining of new /// blocks with each new transaction submitted to the network. /// @@ -2166,10 +2163,7 @@ impl EthApi { /// **Note**: This behaves exactly as [Self::evm_mine] but returns different output, for /// compatibility reasons, this is a separate call since `evm_mine` is not an anvil original. /// and `ganache` may change the `0x0` placeholder. - pub async fn evm_mine_detailed( - &self, - opts: Option, - ) -> Result> { + pub async fn evm_mine_detailed(&self, opts: Option) -> Result> { node_info!("evm_mine_detailed"); let mined_blocks = self.do_evm_mine(opts).await?; @@ -2187,7 +2181,7 @@ impl EthApi { BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(), }; for tx in block_txs.iter_mut() { - if let Some(receipt) = self.backend.mined_transaction_receipt(tx.hash) { + if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash()) { if let Some(output) = receipt.out { // insert revert reason if failure if !receipt @@ -2350,10 +2344,10 @@ impl EthApi { /// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content) for more details /// /// Handler for ETH RPC call: `txpool_inspect` - pub async fn txpool_content(&self) -> Result { + pub async fn txpool_content(&self) -> Result> { node_info!("txpool_content"); - let mut content = TxpoolContent::default(); - fn convert(tx: Arc) -> Transaction { + let mut content = TxpoolContent::::default(); + fn convert(tx: Arc) -> Result { let from = *tx.pending_transaction.sender(); let mut tx = transaction_build( Some(tx.hash()), @@ -2366,18 +2360,19 @@ impl EthApi { // we set the from field here explicitly to the set sender of the pending transaction, // in case the transaction is impersonated. tx.from = from; - tx.inner + + Ok(tx) } for pending in self.pool.ready_transactions() { let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default(); let key = pending.pending_transaction.nonce().to_string(); - entry.insert(key, convert(pending)); + entry.insert(key, convert(pending)?); } for queued in self.pool.pending_transactions() { let entry = content.pending.entry(*queued.pending_transaction.sender()).or_default(); let key = queued.pending_transaction.nonce().to_string(); - entry.insert(key, convert(queued)); + entry.insert(key, convert(queued)?); } Ok(content) @@ -2794,14 +2789,14 @@ impl EthApi { } /// Returns the pending block with tx hashes - async fn pending_block(&self) -> AnyNetworkBlock { + async fn pending_block(&self) -> AnyRpcBlock { let transactions = self.pool.ready_transactions().collect::>(); let info = self.backend.pending_block(transactions).await; self.backend.convert_block(info.block) } /// Returns the full pending block with `Transaction` objects - async fn pending_block_full(&self) -> Option { + async fn pending_block_full(&self) -> Option { let transactions = self.pool.ready_transactions().collect::>(); let BlockInfo { block, transactions, receipts: _ } = self.backend.pending_block(transactions).await; @@ -2916,7 +2911,7 @@ impl EthApi { TypedTransactionRequest::Legacy(_) => Signature::from_scalars_and_parity( B256::with_last_byte(1), B256::with_last_byte(1), - Parity::NonEip155(false), + false, ), TypedTransactionRequest::EIP2930(_) | TypedTransactionRequest::EIP1559(_) | @@ -2924,10 +2919,9 @@ impl EthApi { TypedTransactionRequest::Deposit(_) => Signature::from_scalars_and_parity( B256::with_last_byte(1), B256::with_last_byte(1), - Parity::Parity(false), + false, ), } - .unwrap() } /// Returns the nonce of the `address` depending on the `block_number` diff --git a/crates/anvil/src/eth/backend/db.rs b/crates/anvil/src/eth/backend/db.rs index ca3ff68fa..ad28bd03a 100644 --- a/crates/anvil/src/eth/backend/db.rs +++ b/crates/anvil/src/eth/backend/db.rs @@ -569,8 +569,8 @@ mod test { let block = r#"{ "header": { "parentHash": "0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929", - "ommersHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "beneficiary": "0x0000000000000000000000000000000000000000", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x0000000000000000000000000000000000000000", "stateRoot": "0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1", "transactionsRoot": "0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988", "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", diff --git a/crates/anvil/src/eth/backend/fork.rs b/crates/anvil/src/eth/backend/fork.rs index 7d887f697..64852c802 100644 --- a/crates/anvil/src/eth/backend/fork.rs +++ b/crates/anvil/src/eth/backend/fork.rs @@ -3,7 +3,7 @@ use crate::eth::{backend::db::Db, error::BlockchainError, pool::transactions::PoolTransaction}; use alloy_consensus::Account; use alloy_eips::eip2930::AccessListResult; -use alloy_network::BlockResponse; +use alloy_network::{AnyRpcBlock, AnyRpcTransaction, BlockResponse, TransactionResponse}; use alloy_primitives::{ map::{FbHashMap, HashMap}, Address, Bytes, StorageValue, B256, U256, @@ -18,8 +18,8 @@ use alloy_rpc_types::{ geth::{GethDebugTracingOptions, GethTrace}, parity::LocalizedTransactionTrace as Trace, }, - AnyNetworkBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, - EIP1186AccountProofResponse, FeeHistory, Filter, Log, Transaction, + BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, EIP1186AccountProofResponse, + FeeHistory, Filter, Log, }; use alloy_serde::WithOtherFields; use alloy_transport::TransportError; @@ -291,7 +291,7 @@ impl ClientFork { &self, number: u64, index: usize, - ) -> Result>, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_number(number).await? { match block.transactions() { BlockTransactions::Full(txs) => { @@ -315,7 +315,7 @@ impl ClientFork { &self, hash: B256, index: usize, - ) -> Result>, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_hash(hash).await? { match block.transactions() { BlockTransactions::Full(txs) => { @@ -338,7 +338,7 @@ impl ClientFork { pub async fn transaction_by_hash( &self, hash: B256, - ) -> Result>, TransportError> { + ) -> Result, TransportError> { trace!(target: "backend::fork", "transaction_by_hash={:?}", hash); if let tx @ Some(_) = self.storage_read().transactions.get(&hash).cloned() { return Ok(tx); @@ -450,10 +450,7 @@ impl ClientFork { Ok(None) } - pub async fn block_by_hash( - &self, - hash: B256, - ) -> Result, TransportError> { + pub async fn block_by_hash(&self, hash: B256) -> Result, TransportError> { if let Some(mut block) = self.storage_read().blocks.get(&hash).cloned() { block.transactions.convert_to_hashes(); return Ok(Some(block)); @@ -468,7 +465,7 @@ impl ClientFork { pub async fn block_by_hash_full( &self, hash: B256, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.storage_read().blocks.get(&hash).cloned() { return Ok(Some(self.convert_to_full_block(block))); } @@ -478,7 +475,7 @@ impl ClientFork { pub async fn block_by_number( &self, block_number: u64, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(mut block) = self .storage_read() .hashes @@ -499,7 +496,7 @@ impl ClientFork { pub async fn block_by_number_full( &self, block_number: u64, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self .storage_read() .hashes @@ -516,7 +513,7 @@ impl ClientFork { async fn fetch_full_block( &self, block_id: impl Into, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.provider().get_block(block_id.into(), true.into()).await? { let hash = block.header.hash; let block_number = block.header.number; @@ -526,7 +523,7 @@ impl ClientFork { BlockTransactions::Full(txs) => txs.to_owned(), _ => vec![], }; - storage.transactions.extend(block_txs.iter().map(|tx| (tx.hash, tx.clone()))); + storage.transactions.extend(block_txs.iter().map(|tx| (tx.tx_hash(), tx.clone()))); storage.hashes.insert(block_number, hash); storage.blocks.insert(hash, block.clone()); return Ok(Some(block)); @@ -539,7 +536,7 @@ impl ClientFork { &self, hash: B256, index: usize, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_hash(hash).await? { return self.uncles_by_block_and_index(block, index).await; } @@ -550,7 +547,7 @@ impl ClientFork { &self, number: u64, index: usize, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_number(number).await? { return self.uncles_by_block_and_index(block, index).await; } @@ -559,9 +556,9 @@ impl ClientFork { async fn uncles_by_block_and_index( &self, - block: AnyNetworkBlock, + block: AnyRpcBlock, index: usize, - ) -> Result, TransportError> { + ) -> Result, TransportError> { let block_hash = block.header.hash; let block_number = block.header.number; if let Some(uncles) = self.storage_read().uncles.get(&block_hash) { @@ -582,7 +579,7 @@ impl ClientFork { } /// Converts a block of hashes into a full block - fn convert_to_full_block(&self, mut block: AnyNetworkBlock) -> AnyNetworkBlock { + fn convert_to_full_block(&self, mut block: AnyRpcBlock) -> AnyRpcBlock { let storage = self.storage.read(); let block_txs_len = match block.transactions { BlockTransactions::Full(ref txs) => txs.len(), @@ -684,10 +681,10 @@ impl ClientForkConfig { /// This is used as a cache so repeated requests to the same data are not sent to the remote client #[derive(Clone, Debug, Default)] pub struct ForkedStorage { - pub uncles: FbHashMap<32, Vec>, - pub blocks: FbHashMap<32, AnyNetworkBlock>, + pub uncles: FbHashMap<32, Vec>, + pub blocks: FbHashMap<32, AnyRpcBlock>, pub hashes: HashMap, - pub transactions: FbHashMap<32, WithOtherFields>, + pub transactions: FbHashMap<32, AnyRpcTransaction>, pub transaction_receipts: FbHashMap<32, ReceiptResponse>, pub transaction_traces: FbHashMap<32, Vec>, pub logs: HashMap>, diff --git a/crates/anvil/src/eth/backend/info.rs b/crates/anvil/src/eth/backend/info.rs index 3ac359619..0f539f937 100644 --- a/crates/anvil/src/eth/backend/info.rs +++ b/crates/anvil/src/eth/backend/info.rs @@ -1,9 +1,8 @@ //! Handler that can get current storage related data use crate::mem::Backend; +use alloy_network::AnyRpcBlock; use alloy_primitives::B256; -use alloy_rpc_types::{Block as AlloyBlock, Transaction}; -use alloy_serde::WithOtherFields; use anvil_core::eth::{block::Block, transaction::TypedReceipt}; use std::{fmt, sync::Arc}; @@ -43,10 +42,7 @@ impl StorageInfo { } /// Returns the block with the given hash in the format of the ethereum API - pub fn eth_block( - &self, - hash: B256, - ) -> Option>>> { + pub fn eth_block(&self, hash: B256) -> Option { let block = self.block(hash)?; Some(self.backend.convert_block(block)) } diff --git a/crates/anvil/src/eth/backend/mem/cache.rs b/crates/anvil/src/eth/backend/mem/cache.rs index e51aaae7e..51b92c3d6 100644 --- a/crates/anvil/src/eth/backend/mem/cache.rs +++ b/crates/anvil/src/eth/backend/mem/cache.rs @@ -18,6 +18,10 @@ pub struct DiskStateCache { } impl DiskStateCache { + /// Specify the path where to create the tempdir in + pub fn with_path(self, temp_path: PathBuf) -> Self { + Self { temp_path: Some(temp_path), temp_dir: None } + } /// Returns the cache file for the given hash fn with_cache_file(&mut self, hash: B256, f: F) -> Option where diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index c7ff9422a..83718ad82 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -34,9 +34,14 @@ use crate::{ ForkChoice, NodeConfig, PrecompileFactory, }; use alloy_chains::NamedChain; -use alloy_consensus::{Account, Header, Receipt, ReceiptWithBloom}; +use alloy_consensus::{ + Account, Header, Receipt, ReceiptWithBloom, Signed, Transaction as TransactionTrait, TxEnvelope, +}; use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; -use alloy_network::EthereumWallet; +use alloy_network::{ + AnyHeader, AnyRpcBlock, AnyRpcTransaction, AnyTxEnvelope, AnyTxType, EthereumWallet, + UnknownTxEnvelope, UnknownTypedTransaction, +}; use alloy_primitives::{ address, hex, keccak256, utils::Unit, Address, Bytes, TxHash, TxKind, B256, U256, U64, }; @@ -53,21 +58,19 @@ use alloy_rpc_types::{ }, parity::LocalizedTransactionTrace, }, - AccessList, AnyNetworkBlock, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, - BlockTransactions, EIP1186AccountProofResponse as AccountProof, - EIP1186StorageProof as StorageProof, Filter, FilteredParams, Header as AlloyHeader, Index, Log, - Transaction, TransactionReceipt, + AccessList, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, + EIP1186AccountProofResponse as AccountProof, EIP1186StorageProof as StorageProof, Filter, + FilteredParams, Header as AlloyHeader, Index, Log, Transaction, TransactionReceipt, }; -use alloy_serde::WithOtherFields; +use alloy_serde::{OtherFields, WithOtherFields}; use alloy_signer_local::PrivateKeySigner; use alloy_trie::{proof::ProofRetainer, HashBuilder, Nibbles}; use anvil_core::eth::{ block::{Block, BlockInfo}, transaction::{ - DepositReceipt, MaybeImpersonatedTransaction, PendingTransaction, ReceiptResponse, - TransactionInfo, TypedReceipt, TypedTransaction, + optimism::DepositTransaction, DepositReceipt, MaybeImpersonatedTransaction, + PendingTransaction, ReceiptResponse, TransactionInfo, TypedReceipt, TypedTransaction, }, - utils::meets_eip155, wallet::{Capabilities, DelegationCapability, WalletCapabilities}, }; use anvil_rpc::error::RpcError; @@ -89,6 +92,7 @@ use foundry_evm::{ traces::TracingInspectorConfig, }; use futures::channel::mpsc::{unbounded, UnboundedSender}; +use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID}; use parking_lot::{Mutex, RwLock}; use revm::{ db::WrapDatabaseRef, @@ -99,12 +103,12 @@ use revm::{ use std::{ collections::BTreeMap, io::{Read, Write}, + path::PathBuf, sync::Arc, time::Duration, }; use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT}; use tokio::sync::RwLock as AsyncRwLock; - pub mod cache; pub mod fork_db; pub mod in_memory_db; @@ -223,6 +227,7 @@ impl Backend { max_persisted_states: Option, transaction_block_keeper: Option, automine_block_time: Option, + cache_path: Option, node_config: Arc>, ) -> Self { // if this is a fork then adjust the blockchain storage @@ -245,7 +250,7 @@ impl Backend { genesis.timestamp }; - let states = if prune_state_history_config.is_config_enabled() { + let mut states = if prune_state_history_config.is_config_enabled() { // if prune state history is enabled, configure the state cache only for memory prune_state_history_config .max_memory_history @@ -260,6 +265,10 @@ impl Backend { Default::default() }; + if let Some(cache_path) = cache_path { + states = states.disk_path(cache_path); + } + let (slots_in_an_epoch, precompile_factory) = { let cfg = node_config.read().await; (cfg.slots_in_an_epoch, cfg.precompile_factory.clone()) @@ -1709,10 +1718,7 @@ impl Backend { } } - pub async fn block_by_hash( - &self, - hash: B256, - ) -> Result, BlockchainError> { + pub async fn block_by_hash(&self, hash: B256) -> Result, BlockchainError> { trace!(target: "backend", "get block by hash {:?}", hash); if let tx @ Some(_) = self.mined_block_by_hash(hash) { return Ok(tx); @@ -1728,7 +1734,7 @@ impl Backend { pub async fn block_by_hash_full( &self, hash: B256, - ) -> Result, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "get block by hash {:?}", hash); if let tx @ Some(_) = self.get_full_block(hash) { return Ok(tx); @@ -1741,7 +1747,7 @@ impl Backend { Ok(None) } - fn mined_block_by_hash(&self, hash: B256) -> Option { + fn mined_block_by_hash(&self, hash: B256) -> Option { let block = self.blockchain.get_block_by_hash(&hash)?; Some(self.convert_block(block)) } @@ -1749,7 +1755,7 @@ impl Backend { pub(crate) async fn mined_transactions_by_block_number( &self, number: BlockNumber, - ) -> Option>> { + ) -> Option> { if let Some(block) = self.get_block(number) { return self.mined_transactions_in_block(&block); } @@ -1760,7 +1766,7 @@ impl Backend { pub(crate) fn mined_transactions_in_block( &self, block: &Block, - ) -> Option>> { + ) -> Option> { let mut transactions = Vec::with_capacity(block.transactions.len()); let base_fee = block.header.base_fee_per_gas; let storage = self.blockchain.storage.read(); @@ -1777,7 +1783,7 @@ impl Backend { pub async fn block_by_number( &self, number: BlockNumber, - ) -> Result, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "get block by number {:?}", number); if let tx @ Some(_) = self.mined_block_by_number(number) { return Ok(tx); @@ -1796,7 +1802,7 @@ impl Backend { pub async fn block_by_number_full( &self, number: BlockNumber, - ) -> Result, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "get block by number {:?}", number); if let tx @ Some(_) = self.get_full_block(number) { return Ok(tx); @@ -1849,14 +1855,14 @@ impl Backend { self.blockchain.get_block_by_hash(&hash) } - pub fn mined_block_by_number(&self, number: BlockNumber) -> Option { + pub fn mined_block_by_number(&self, number: BlockNumber) -> Option { let block = self.get_block(number)?; let mut block = self.convert_block(block); block.transactions.convert_to_hashes(); Some(block) } - pub fn get_full_block(&self, id: impl Into) -> Option { + pub fn get_full_block(&self, id: impl Into) -> Option { let block = self.get_block(id)?; let transactions = self.mined_transactions_in_block(&block)?; let mut block = self.convert_block(block); @@ -1866,63 +1872,21 @@ impl Backend { } /// Takes a block as it's stored internally and returns the eth api conform block format. - pub fn convert_block(&self, block: Block) -> AnyNetworkBlock { + pub fn convert_block(&self, block: Block) -> AnyRpcBlock { let size = U256::from(alloy_rlp::encode(&block).len() as u32); let Block { header, transactions, .. } = block; let hash = header.hash_slow(); - let Header { - parent_hash, - ommers_hash, - beneficiary, - state_root, - transactions_root, - receipts_root, - logs_bloom, - difficulty, - number, - gas_limit, - gas_used, - timestamp, - requests_hash, - extra_data, - mix_hash, - nonce, - base_fee_per_gas, - withdrawals_root, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - } = header; + let Header { number, withdrawals_root, .. } = header; let block = AlloyBlock { header: AlloyHeader { + inner: AnyHeader::from(header), hash, - parent_hash, - uncles_hash: ommers_hash, - miner: beneficiary, - state_root, - transactions_root, - receipts_root, - number, - gas_used, - gas_limit, - extra_data: extra_data.0.into(), - logs_bloom, - timestamp, total_difficulty: Some(self.total_difficulty()), - difficulty, - mix_hash: Some(mix_hash), - nonce: Some(nonce), - base_fee_per_gas, - withdrawals_root, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - requests_hash, + size: Some(size), }, - size: Some(size), transactions: alloy_rpc_types::BlockTransactions::Hashes( transactions.into_iter().map(|tx| tx.hash()).collect(), ), @@ -2030,7 +1994,7 @@ impl Backend { if let Some(state) = self.states.write().get(&block_hash) { let block = BlockEnv { number: block_number, - coinbase: block.header.miner, + coinbase: block.header.beneficiary, timestamp: U256::from(block.header.timestamp), difficulty: block.header.difficulty, prevrandao: block.header.mix_hash, @@ -2469,7 +2433,7 @@ impl Backend { &self, number: BlockNumber, index: Index, - ) -> Result>, BlockchainError> { + ) -> Result, BlockchainError> { if let Some(block) = self.mined_block_by_number(number) { return Ok(self.mined_transaction_by_block_hash_and_index(block.header.hash, index)); } @@ -2488,7 +2452,7 @@ impl Backend { &self, hash: B256, index: Index, - ) -> Result>, BlockchainError> { + ) -> Result, BlockchainError> { if let tx @ Some(_) = self.mined_transaction_by_block_hash_and_index(hash, index) { return Ok(tx); } @@ -2504,7 +2468,7 @@ impl Backend { &self, block_hash: B256, index: Index, - ) -> Option> { + ) -> Option { let (info, block, tx) = { let storage = self.blockchain.storage.read(); let block = storage.blocks.get(&block_hash).cloned()?; @@ -2526,7 +2490,7 @@ impl Backend { pub async fn transaction_by_hash( &self, hash: B256, - ) -> Result>, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "transaction_by_hash={:?}", hash); if let tx @ Some(_) = self.mined_transaction_by_hash(hash) { return Ok(tx); @@ -2539,7 +2503,7 @@ impl Backend { Ok(None) } - pub fn mined_transaction_by_hash(&self, hash: B256) -> Option> { + pub fn mined_transaction_by_hash(&self, hash: B256) -> Option { let (info, block) = { let storage = self.blockchain.storage.read(); let MinedTransaction { info, block_hash, .. } = @@ -2604,7 +2568,7 @@ impl Backend { .map(|(key, proof)| { let storage_key: U256 = key.into(); let value = account.storage.get(&storage_key).cloned().unwrap_or_default(); - StorageProof { key: JsonStorageKey(key), value, proof } + StorageProof { key: JsonStorageKey::Hash(key), value, proof } }) .collect(), }; @@ -2749,7 +2713,7 @@ impl TransactionValidator for Backend { if let Some(legacy) = tx.as_legacy() { // if env.handler_cfg.spec_id >= SpecId::SPURIOUS_DRAGON && - !meets_eip155(chain_id.to::(), legacy.signature().v()) + legacy.tx().chain_id.is_none() { warn!(target: "backend", ?chain_id, ?tx_chain_id, "incompatible EIP155-based V"); return Err(InvalidTransactionError::IncompatibleEIP155); @@ -2880,7 +2844,7 @@ impl TransactionValidator for Backend { } } -/// Creates a `Transaction` as it's expected for the `eth` RPC api from storage data +/// Creates a `AnyRpcTransaction` as it's expected for the `eth` RPC api from storage data #[allow(clippy::too_many_arguments)] pub fn transaction_build( tx_hash: Option, @@ -2888,56 +2852,134 @@ pub fn transaction_build( block: Option<&Block>, info: Option, base_fee: Option, -) -> WithOtherFields { - let mut transaction: Transaction = eth_transaction.clone().into(); - if info.is_some() && transaction.transaction_type == Some(0x7E) { - transaction.nonce = info.as_ref().unwrap().nonce; - } +) -> AnyRpcTransaction { + if let TypedTransaction::Deposit(ref deposit_tx) = eth_transaction.transaction { + let DepositTransaction { + nonce: _, + source_hash, + from, + kind, + mint, + gas_limit, + is_system_tx, + input, + value, + } = deposit_tx.clone(); + + let dep_tx = TxDeposit { + source_hash, + input, + from, + mint: Some(mint.to()), + to: kind, + is_system_transaction: is_system_tx, + value, + gas_limit, + }; - if eth_transaction.is_dynamic_fee() { - if block.is_none() && info.is_none() { - // transaction is not mined yet, gas price is considered just `max_fee_per_gas` - transaction.gas_price = transaction.max_fee_per_gas; - } else { - // if transaction is already mined, gas price is considered base fee + priority fee: the - // effective gas price. - let base_fee = base_fee.map_or(0u128, |g| g as u128); - let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas.unwrap_or(0); - transaction.gas_price = Some(base_fee.saturating_add(max_priority_fee_per_gas)); + let ser = serde_json::to_value(&dep_tx).unwrap(); + let maybe_deposit_fields = OtherFields::try_from(ser); + + match maybe_deposit_fields { + Ok(fields) => { + let inner = UnknownTypedTransaction { + ty: AnyTxType(DEPOSIT_TX_TYPE_ID), + fields, + memo: Default::default(), + }; + + let envelope = AnyTxEnvelope::Unknown(UnknownTxEnvelope { + hash: eth_transaction.hash(), + inner, + }); + + let tx = Transaction { + inner: envelope, + block_hash: block + .as_ref() + .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))), + block_number: block.as_ref().map(|block| block.header.number), + transaction_index: info.as_ref().map(|info| info.transaction_index), + effective_gas_price: None, + from, + }; + + return WithOtherFields::new(tx); + } + Err(_) => { + error!(target: "backend", "failed to serialize deposit transaction"); + } } - } else { - transaction.max_fee_per_gas = None; - transaction.max_priority_fee_per_gas = None; } - transaction.block_hash = - block.as_ref().map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))); + let mut transaction: Transaction = eth_transaction.clone().into(); - transaction.block_number = block.as_ref().map(|block| block.header.number); + let effective_gas_price = if !eth_transaction.is_dynamic_fee() { + transaction.effective_gas_price(base_fee) + } else if block.is_none() && info.is_none() { + // transaction is not mined yet, gas price is considered just `max_fee_per_gas` + transaction.max_fee_per_gas() + } else { + // if transaction is already mined, gas price is considered base fee + priority + // fee: the effective gas price. + let base_fee = base_fee.map_or(0u128, |g| g as u128); + let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas().unwrap_or(0); - transaction.transaction_index = info.as_ref().map(|info| info.transaction_index); + base_fee.saturating_add(max_priority_fee_per_gas) + }; - // need to check if the signature of the transaction is impersonated, if so then we - // can't recover the sender, instead we use the sender from the executed transaction and set the - // impersonated hash. - if eth_transaction.is_impersonated() { - transaction.from = info.as_ref().map(|info| info.from).unwrap_or_default(); - transaction.hash = eth_transaction.impersonated_hash(transaction.from); - } else { - transaction.from = eth_transaction.recover().expect("can recover signed tx"); - } + transaction.effective_gas_price = Some(effective_gas_price); - // if a specific hash was provided we update the transaction's hash - // This is important for impersonated transactions since they all use the `BYPASS_SIGNATURE` - // which would result in different hashes - // Note: for impersonated transactions this only concerns pending transactions because there's - // no `info` yet. - if let Some(tx_hash) = tx_hash { - transaction.hash = tx_hash; - } + let envelope = transaction.inner; - transaction.to = info.as_ref().map_or(eth_transaction.to(), |status| status.to); - WithOtherFields::new(transaction) + // if a specific hash was provided we update the transaction's hash + // This is important for impersonated transactions since they all use the + // `BYPASS_SIGNATURE` which would result in different hashes + // Note: for impersonated transactions this only concerns pending transactions because + // there's // no `info` yet. + let hash = tx_hash.unwrap_or(*envelope.tx_hash()); + + let envelope = match envelope { + TxEnvelope::Legacy(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Legacy(new_signed)) + } + TxEnvelope::Eip1559(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip1559(new_signed)) + } + TxEnvelope::Eip2930(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip2930(new_signed)) + } + TxEnvelope::Eip4844(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip4844(new_signed)) + } + TxEnvelope::Eip7702(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip7702(new_signed)) + } + _ => unreachable!("unknown tx type"), + }; + + let tx = Transaction { + inner: envelope, + block_hash: block + .as_ref() + .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))), + block_number: block.as_ref().map(|block| block.header.number), + transaction_index: info.as_ref().map(|info| info.transaction_index), + from: eth_transaction.recover().expect("can recover signed tx"), + // deprecated + effective_gas_price: Some(effective_gas_price), + }; + WithOtherFields::new(tx) } /// Prove a storage key's existence or nonexistence in the account's storage trie. diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index d5a72fccb..056b88627 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -41,7 +41,7 @@ use foundry_evm::{ }; use parking_lot::RwLock; use revm::primitives::SpecId; -use std::{collections::VecDeque, fmt, sync::Arc, time::Duration}; +use std::{collections::VecDeque, fmt, path::PathBuf, sync::Arc, time::Duration}; // use yansi::Paint; // === various limits in number of blocks === @@ -94,6 +94,12 @@ impl InMemoryBlockStates { self } + /// Configures the path on disk where the states will cached. + pub fn disk_path(mut self, path: PathBuf) -> Self { + self.disk_cache = self.disk_cache.with_path(path); + self + } + /// This modifies the `limit` what to keep stored in memory. /// /// This will ensure the new limit adjusts based on the block time. diff --git a/crates/anvil/src/eth/error.rs b/crates/anvil/src/eth/error.rs index 0c478ee06..394f33492 100644 --- a/crates/anvil/src/eth/error.rs +++ b/crates/anvil/src/eth/error.rs @@ -90,6 +90,8 @@ pub enum BlockchainError { EIP7702TransactionUnsupportedAtHardfork, #[error("op-stack deposit tx received but is not supported.\n\nYou can use it by running anvil with '--optimism'.")] DepositTransactionUnsupported, + #[error("UnknownTransactionType not supported ")] + UnknownTransactionType, #[error("Excess blob gas not set.")] ExcessBlobGasNotSet, #[error("{0}")] @@ -463,6 +465,9 @@ impl ToRpcResponseResult for Result { RpcError::invalid_params(err.to_string()) } err @ BlockchainError::Message(_) => RpcError::internal_error_with(err.to_string()), + err @ BlockchainError::UnknownTransactionType => { + RpcError::invalid_params(err.to_string()) + } } .into(), } diff --git a/crates/anvil/src/eth/miner.rs b/crates/anvil/src/eth/miner.rs index defb6624a..90c455090 100644 --- a/crates/anvil/src/eth/miner.rs +++ b/crates/anvil/src/eth/miner.rs @@ -64,9 +64,12 @@ impl Miner { matches!(*mode, MiningMode::Auto(_)) } - pub fn is_interval(&self) -> bool { + pub fn get_interval(&self) -> Option { let mode = self.mode.read(); - matches!(*mode, MiningMode::FixedBlockTime(_)) + if let MiningMode::FixedBlockTime(ref mm) = *mode { + return Some(mm.interval.period().as_secs()) + } + None } /// Sets the mining mode to operate in diff --git a/crates/anvil/src/eth/otterscan/api.rs b/crates/anvil/src/eth/otterscan/api.rs index e73fe4dd6..617655444 100644 --- a/crates/anvil/src/eth/otterscan/api.rs +++ b/crates/anvil/src/eth/otterscan/api.rs @@ -3,7 +3,11 @@ use crate::eth::{ macros::node_info, EthApi, }; -use alloy_network::BlockResponse; +use alloy_consensus::Transaction as TransactionTrait; +use alloy_network::{ + AnyHeader, AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, AnyTxEnvelope, BlockResponse, + TransactionResponse, +}; use alloy_primitives::{Address, Bytes, B256, U256}; use alloy_rpc_types::{ trace::{ @@ -16,10 +20,8 @@ use alloy_rpc_types::{ RewardAction, TraceOutput, }, }, - AnyNetworkBlock, Block, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, - Transaction, + Block, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, }; -use alloy_serde::WithOtherFields; use itertools::Itertools; use futures::future::join_all; @@ -90,7 +92,7 @@ impl EthApi { pub async fn erigon_get_header_by_number( &self, number: BlockNumber, - ) -> Result> { + ) -> Result> { node_info!("ots_getApiLevel"); self.backend.block_by_number(number).await @@ -146,7 +148,10 @@ impl EthApi { /// For simplicity purposes, we return the entire block instead of emptying the values that /// Otterscan doesn't want. This is the original purpose of the endpoint (to save bandwidth), /// but it doesn't seem necessary in the context of an anvil node - pub async fn ots_get_block_details(&self, number: BlockNumber) -> Result { + pub async fn ots_get_block_details( + &self, + number: BlockNumber, + ) -> Result> { node_info!("ots_getBlockDetails"); if let Some(block) = self.backend.block_by_number(number).await? { @@ -160,7 +165,10 @@ impl EthApi { /// For simplicity purposes, we return the entire block instead of emptying the values that /// Otterscan doesn't want. This is the original purpose of the endpoint (to save bandwidth), /// but it doesn't seem necessary in the context of an anvil node - pub async fn ots_get_block_details_by_hash(&self, hash: B256) -> Result { + pub async fn ots_get_block_details_by_hash( + &self, + hash: B256, + ) -> Result> { node_info!("ots_getBlockDetailsByHash"); if let Some(block) = self.backend.block_by_hash(hash).await? { @@ -178,7 +186,7 @@ impl EthApi { number: u64, page: usize, page_size: usize, - ) -> Result>> { + ) -> Result> { node_info!("ots_getBlockTransactions"); match self.backend.block_by_number_full(number.into()).await? { @@ -193,7 +201,7 @@ impl EthApi { address: Address, block_number: u64, page_size: usize, - ) -> Result { + ) -> Result>> { node_info!("ots_searchTransactionsBefore"); let best = self.backend.best_number(); @@ -236,7 +244,7 @@ impl EthApi { address: Address, block_number: u64, page_size: usize, - ) -> Result { + ) -> Result>> { node_info!("ots_searchTransactionsAfter"); let best = self.backend.best_number(); @@ -295,8 +303,8 @@ impl EthApi { for n in (from..=to).rev() { if let Some(txs) = self.backend.mined_transactions_by_block_number(n.into()).await { for tx in txs { - if U256::from(tx.nonce) == nonce && tx.from == address { - return Ok(Some(tx.hash)); + if U256::from(tx.nonce()) == nonce && tx.from == address { + return Ok(Some(tx.tx_hash())); } } } @@ -352,7 +360,10 @@ impl EthApi { /// based on the existing list. /// /// Therefore we keep it simple by keeping the data in the response - pub async fn build_ots_block_details(&self, block: AnyNetworkBlock) -> Result { + pub async fn build_ots_block_details( + &self, + block: AnyRpcBlock, + ) -> Result>> { if block.transactions.is_uncle() { return Err(BlockchainError::DataUnavailable); } @@ -375,15 +386,10 @@ impl EthApi { .iter() .fold(0, |acc, receipt| acc + receipt.gas_used * receipt.effective_gas_price); - let Block { header, uncles, transactions, size, withdrawals } = block.inner; + let Block { header, uncles, transactions, withdrawals } = block.inner; - let block = OtsSlimBlock { - header, - uncles, - transaction_count: transactions.len(), - size, - withdrawals, - }; + let block = + OtsSlimBlock { header, uncles, transaction_count: transactions.len(), withdrawals }; Ok(BlockDetails { block, @@ -399,10 +405,10 @@ impl EthApi { /// [`ots_getBlockTransactions`]: https://github.com/otterscan/otterscan/blob/develop/docs/custom-jsonrpc.md#ots_getblockdetails pub async fn build_ots_block_tx( &self, - mut block: AnyNetworkBlock, + mut block: AnyRpcBlock, page: usize, page_size: usize, - ) -> Result>> { + ) -> Result> { if block.transactions.is_uncle() { return Err(BlockchainError::DataUnavailable); } @@ -436,8 +442,7 @@ impl EthApi { let transaction_count = block.transactions().len(); let fullblock = OtsBlock { block: block.inner, transaction_count }; - let ots_block_txs = - OtsBlockTransactions::> { fullblock, receipts }; + let ots_block_txs = OtsBlockTransactions { fullblock, receipts }; Ok(ots_block_txs) } @@ -447,7 +452,7 @@ impl EthApi { hashes: Vec, first_page: bool, last_page: bool, - ) -> Result { + ) -> Result>> { let txs_futs = hashes.iter().map(|hash| async { self.transaction_by_hash(*hash).await }); let txs = join_all(txs_futs) diff --git a/crates/anvil/src/eth/pool/transactions.rs b/crates/anvil/src/eth/pool/transactions.rs index 631064549..36e421d7a 100644 --- a/crates/anvil/src/eth/pool/transactions.rs +++ b/crates/anvil/src/eth/pool/transactions.rs @@ -1,10 +1,9 @@ use crate::eth::{error::PoolError, util::hex_fmt_many}; +use alloy_network::AnyRpcTransaction; use alloy_primitives::{ map::{HashMap, HashSet}, Address, TxHash, }; -use alloy_rpc_types::Transaction as RpcTransaction; -use alloy_serde::WithOtherFields; use anvil_core::eth::transaction::{PendingTransaction, TypedTransaction}; use parking_lot::RwLock; use std::{cmp::Ordering, collections::BTreeSet, fmt, str::FromStr, sync::Arc, time::Instant}; @@ -113,10 +112,10 @@ impl fmt::Debug for PoolTransaction { } } -impl TryFrom> for PoolTransaction { +impl TryFrom for PoolTransaction { type Error = eyre::Error; - fn try_from(transaction: WithOtherFields) -> Result { - let typed_transaction = TypedTransaction::try_from(transaction)?; + fn try_from(value: AnyRpcTransaction) -> Result { + let typed_transaction = TypedTransaction::try_from(value)?; let pending_transaction = PendingTransaction::new(typed_transaction)?; Ok(Self { pending_transaction, diff --git a/crates/anvil/src/eth/sign.rs b/crates/anvil/src/eth/sign.rs index 5f99ef9ca..e2ea036a0 100644 --- a/crates/anvil/src/eth/sign.rs +++ b/crates/anvil/src/eth/sign.rs @@ -2,7 +2,7 @@ use crate::eth::error::BlockchainError; use alloy_consensus::SignableTransaction; use alloy_dyn_abi::TypedData; use alloy_network::TxSignerSync; -use alloy_primitives::{map::AddressHashMap, Address, Signature, B256, U256}; +use alloy_primitives::{map::AddressHashMap, Address, PrimitiveSignature as Signature, B256, U256}; use alloy_signer::Signer as AlloySigner; use alloy_signer_local::PrivateKeySigner; use anvil_core::eth::transaction::{ diff --git a/crates/anvil/src/tasks/mod.rs b/crates/anvil/src/tasks/mod.rs index f9ba36b60..022e7dd97 100644 --- a/crates/anvil/src/tasks/mod.rs +++ b/crates/anvil/src/tasks/mod.rs @@ -3,10 +3,10 @@ #![allow(rustdoc::private_doc_tests)] use crate::{shutdown::Shutdown, tasks::block_listener::BlockListener, EthApi}; -use alloy_network::AnyNetwork; +use alloy_network::{AnyHeader, AnyNetwork}; use alloy_primitives::B256; use alloy_provider::Provider; -use alloy_rpc_types::{anvil::Forking, AnyNetworkBlock}; +use alloy_rpc_types::anvil::Forking; use alloy_transport::Transport; use futures::StreamExt; use std::{fmt, future::Future}; @@ -129,13 +129,13 @@ impl TaskManager { P: Provider + 'static, T: Transport + Clone, { - self.spawn_block_subscription(provider, move |block| { + self.spawn_block_subscription(provider, move |header| { let api = api.clone(); async move { let _ = api .anvil_reset(Some(Forking { json_rpc_url: None, - block_number: Some(block.header.number), + block_number: Some(header.number), })) .await; } @@ -149,7 +149,7 @@ impl TaskManager { where P: Provider + 'static, T: Transport + Clone, - F: Fn(AnyNetworkBlock) -> Fut + Unpin + Send + Sync + 'static, + F: Fn(alloy_rpc_types::Header) -> Fut + Unpin + Send + Sync + 'static, Fut: Future + Send, { let shutdown = self.on_shutdown.clone(); diff --git a/crates/anvil/test-data/state-dump-legacy-stress.json b/crates/anvil/test-data/state-dump-legacy-stress.json index 50df9e039..f6605d5ad 100644 --- a/crates/anvil/test-data/state-dump-legacy-stress.json +++ b/crates/anvil/test-data/state-dump-legacy-stress.json @@ -1 +1 @@ -{"block":{"number":"0x5","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66b200cb","gas_limit":"0x1c9c380","basefee":"0x12e09c7a","difficulty":"0x0","prevrandao":"0xe7ef87fc7c2090741a6749a087e4ca8092cb4d07136008799e4ebeac3b69e34a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0x1088aa62285a00","code":"0x","storage":{}},"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd":{"nonce":1,"balance":"0x0","code":"0x6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x19ba1fac55eea44d12a01372a8eb0c2ebbf9ca21":{"nonce":1,"balance":"0x21e19df7c2963f0ac6b","code":"0x","storage":{}},"0x19c6ab860dbe2bc433574193a4409770a8748bf6":{"nonce":1,"balance":"0x21e19df8da6b7bdc410","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x40567ec443c1d1872af5155755ac3803cc3fe61e":{"nonce":1,"balance":"0x21e19da82562f921b40","code":"0x","storage":{}},"0x47d08dad17ccb558b3ea74b1a0e73a9cc804a9dc":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","storage":{"0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0x0"}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":2,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x8138ef7cf908021d117e542120b7a39065016107":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","storage":{}},"0x83a0444b93927c3afcbe46e522280390f748e171":{"nonce":1,"balance":"0x0","code":"0x6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c63430008110033","storage":{"0x5a648c35a2f5512218b4683cf10e03f5b7c9dc7346e1bf77d304ae97f60f592b":"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xc67e2bd3108604cf0168c0e5ef9cd6d78b9bb14b":{"nonce":1,"balance":"0x21e19c6edb7e2445f20","code":"0x","storage":{}},"0xeb045d78d273107348b0300c01d29b7552d622ab":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e08b86820a43ea","code":"0x","storage":{}}},"best_block_number":"0x5","blocks":[{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xcd346446ed010523161f40a5f2b512def549bfb79e165b4354488738416481f2","transactionsRoot":"0xb3a4689832e0b599260ae70362ffcf224b60571b35ff8836904a3d81e2675d66","receiptsRoot":"0x2d13fdc120ab90536fed583939de7fb68b64926a306c1f629593ca9c2c93b198","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x3ea90d","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x2e0b6260","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3ea90d","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b5061494f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xbc73db80bf4b8784ba10a8910a0b7ef85f6846d102b41dd990969ea205335354"}}],"ommers":[]},{"header":{"parentHash":"0x026ae0c6ae91f186a9befa1ac8be30eea35e30e77de51a731085221e5cd39209","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x6e4969a136061ca7a390d12830d47a151585325a8d396819fb2b958ff85e9f8f","receiptsRoot":"0xc3e81df67d3e2a6c8345a954ef250cfcc41abcc2292a5aa263071124533fc9ad","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x3c0f6","timestamp":"0x66b200ce","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x18993a68","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3c0f6","maxFeePerGas":"0x5d4285cd","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b50610380806100206000396000f3fe6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x2476e039803622aeb040f924f04c493f559aed3d6c9372ab405cb33c8c695328"}}],"ommers":[]},{"header":{"parentHash":"0x3d22100ac0ee8d5cde334f7f926191a861b0648971ebc179547df28a0224c6d0","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x9511d4711e5c30a72b0bff38a261daa75dcc5ba8b772d970a5c742244b4c861b","transactionsRoot":"0xba5fff578d3d6c2cd63acbe9bca353eaa6fe22a5c408956eff49106e0a96c507","receiptsRoot":"0xbae111f01cb07677e3a8c5031546138407c01bc964d3493d732dc4edf47d36d3","logsBloom":"0x00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000001000000000000000000000400000001000010000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x5","gasLimit":"0x1c9c380","gasUsed":"0xcae7","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x12e09c7a","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xcc4d","maxFeePerGas":"0x557e5ec4","maxPriorityFeePerGas":"0x3b9aca00","to":"0x83a0444b93927c3afcbe46e522280390f748e171","value":"0x0","accessList":[],"input":"0x3659cfe6000000000000000000000000108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xf88e7b19ee347145c257e0cf7ac4ecc2bae83ca79d7edaa231e71d3213aeb151"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x9c8eaf493f8b4edce2ba1647343eadcc0989cf461e712c0a6253ff2ca1842bb7","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xdd07c07470e1deff3749831f0f1ad8d4b6e35505e83b3c6ea14181716197cd8a","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x24a1ab52","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200c9","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xf6930be4847cac5017bbcbec2756eed19f36b4196526a98a88e311c296e3a9be","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cc","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x200d75e8","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x4","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1592fbf9","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x149d41e3b89d8324cef3feff98ef308e97bafe8745cc8461c60172bc7d4c44ba","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x0b44110186e52ff0ceb6b0776ca2992c94144a4ed712eef65ea038260ef0fcc7","receiptsRoot":"0xc2823b8eb4730d9f2657137cc2ddc2c4f22ab68e0ab826236cf6a1551ca2b3a5","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0xe61f9","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342770c0","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xe94d1","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060008061002661006d60201b61081b1760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610141565b60008060405160200161007f90610121565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b600061010b60238361009e565b9150610116826100af565b604082019050919050565b6000602082019050818103600083015261013a816100fe565b9050919050565b611000806101506000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x4feae6769d748b4f0f7c9bf21d782236c88f13906789a3ec602961296e4c3e43"}}],"ommers":[]},{"header":{"parentHash":"0xb3535af5103fd1c2bbd6dc7ff23f0799037a6542c231ebcb85abd776560fa512","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x23d74fb99ff6e42cbb5c33f92b078e37be6af2b6092459b103ff7059a6517ebc","transactionsRoot":"0x9eab45eca206fe11c107ea985c7d02fcfa442836aea3e04ba11dc4df587d5aa6","receiptsRoot":"0xe25abcfa973db8c55f73292137c626430de130a382ad4466337fefb0f7c8fde0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x3ce3f","timestamp":"0x66b200cd","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1c0bc72b","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3d8a8","maxFeePerGas":"0x6211577c","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060405161068538038061068583398181016040528101906100329190610275565b818181600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361009b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100ae8161019d60201b61004f1760201c565b6100ef57806040517f8a8b41ec0000000000000000000000000000000000000000000000000000000081526004016100e691906102c4565b60405180910390fd5b806100fe6101b060201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050806101536101e160201b6100621760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050610414565b600080823b905060008111915050919050565b6000806040516020016101c290610362565b6040516020818303038152906040528051906020012090508091505090565b6000806040516020016101f3906103f4565b6040516020818303038152906040528051906020012090508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061024282610217565b9050919050565b61025281610237565b811461025d57600080fd5b50565b60008151905061026f81610249565b92915050565b6000806040838503121561028c5761028b610212565b5b600061029a85828601610260565b92505060206102ab85828601610260565b9150509250929050565b6102be81610237565b82525050565b60006020820190506102d960008301846102b5565b92915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b600061034c6021836102df565b9150610357826102f0565b604082019050919050565b6000602082019050818103600083015261037b8161033f565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006103de6023836102df565b91506103e982610382565b604082019050919050565b6000602082019050818103600083015261040d816103d1565b9050919050565b610262806104236000396000f3fe6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c6343000811003300000000000000000000000047d08dad17ccb558b3ea74b1a0e73a9cc804a9dc000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xb6794d5c7abed6f91d447e8efb72ef2580595a6d7c8dee57ba1dbb330970146a"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x29dd5614","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]}]} \ No newline at end of file +{"block":{"number":"0x5","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66b200cb","gas_limit":"0x1c9c380","basefee":"0x12e09c7a","difficulty":"0x0","prevrandao":"0xe7ef87fc7c2090741a6749a087e4ca8092cb4d07136008799e4ebeac3b69e34a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0x1088aa62285a00","code":"0x","storage":{}},"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd":{"nonce":1,"balance":"0x0","code":"0x6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x19ba1fac55eea44d12a01372a8eb0c2ebbf9ca21":{"nonce":1,"balance":"0x21e19df7c2963f0ac6b","code":"0x","storage":{}},"0x19c6ab860dbe2bc433574193a4409770a8748bf6":{"nonce":1,"balance":"0x21e19df8da6b7bdc410","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x40567ec443c1d1872af5155755ac3803cc3fe61e":{"nonce":1,"balance":"0x21e19da82562f921b40","code":"0x","storage":{}},"0x47d08dad17ccb558b3ea74b1a0e73a9cc804a9dc":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","storage":{"0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0x0"}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":2,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x8138ef7cf908021d117e542120b7a39065016107":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","storage":{}},"0x83a0444b93927c3afcbe46e522280390f748e171":{"nonce":1,"balance":"0x0","code":"0x6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c63430008110033","storage":{"0x5a648c35a2f5512218b4683cf10e03f5b7c9dc7346e1bf77d304ae97f60f592b":"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xc67e2bd3108604cf0168c0e5ef9cd6d78b9bb14b":{"nonce":1,"balance":"0x21e19c6edb7e2445f20","code":"0x","storage":{}},"0xeb045d78d273107348b0300c01d29b7552d622ab":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e08b86820a43ea","code":"0x","storage":{}}},"best_block_number":"0x5","blocks":[{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xcd346446ed010523161f40a5f2b512def549bfb79e165b4354488738416481f2","transactionsRoot":"0xb3a4689832e0b599260ae70362ffcf224b60571b35ff8836904a3d81e2675d66","receiptsRoot":"0x2d13fdc120ab90536fed583939de7fb68b64926a306c1f629593ca9c2c93b198","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x3ea90d","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x2e0b6260","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3ea90d","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b5061494f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xbc73db80bf4b8784ba10a8910a0b7ef85f6846d102b41dd990969ea205335354"}}],"ommers":[]},{"header":{"parentHash":"0x026ae0c6ae91f186a9befa1ac8be30eea35e30e77de51a731085221e5cd39209","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x6e4969a136061ca7a390d12830d47a151585325a8d396819fb2b958ff85e9f8f","receiptsRoot":"0xc3e81df67d3e2a6c8345a954ef250cfcc41abcc2292a5aa263071124533fc9ad","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x3c0f6","timestamp":"0x66b200ce","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x18993a68","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3c0f6","maxFeePerGas":"0x5d4285cd","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b50610380806100206000396000f3fe6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x2476e039803622aeb040f924f04c493f559aed3d6c9372ab405cb33c8c695328"}}],"ommers":[]},{"header":{"parentHash":"0x3d22100ac0ee8d5cde334f7f926191a861b0648971ebc179547df28a0224c6d0","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9511d4711e5c30a72b0bff38a261daa75dcc5ba8b772d970a5c742244b4c861b","transactionsRoot":"0xba5fff578d3d6c2cd63acbe9bca353eaa6fe22a5c408956eff49106e0a96c507","receiptsRoot":"0xbae111f01cb07677e3a8c5031546138407c01bc964d3493d732dc4edf47d36d3","logsBloom":"0x00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000001000000000000000000000400000001000010000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x5","gasLimit":"0x1c9c380","gasUsed":"0xcae7","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x12e09c7a","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xcc4d","maxFeePerGas":"0x557e5ec4","maxPriorityFeePerGas":"0x3b9aca00","to":"0x83a0444b93927c3afcbe46e522280390f748e171","value":"0x0","accessList":[],"input":"0x3659cfe6000000000000000000000000108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xf88e7b19ee347145c257e0cf7ac4ecc2bae83ca79d7edaa231e71d3213aeb151"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9c8eaf493f8b4edce2ba1647343eadcc0989cf461e712c0a6253ff2ca1842bb7","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xdd07c07470e1deff3749831f0f1ad8d4b6e35505e83b3c6ea14181716197cd8a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x24a1ab52","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200c9","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xf6930be4847cac5017bbcbec2756eed19f36b4196526a98a88e311c296e3a9be","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cc","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x200d75e8","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x4","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1592fbf9","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x149d41e3b89d8324cef3feff98ef308e97bafe8745cc8461c60172bc7d4c44ba","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x0b44110186e52ff0ceb6b0776ca2992c94144a4ed712eef65ea038260ef0fcc7","receiptsRoot":"0xc2823b8eb4730d9f2657137cc2ddc2c4f22ab68e0ab826236cf6a1551ca2b3a5","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0xe61f9","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342770c0","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xe94d1","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060008061002661006d60201b61081b1760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610141565b60008060405160200161007f90610121565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b600061010b60238361009e565b9150610116826100af565b604082019050919050565b6000602082019050818103600083015261013a816100fe565b9050919050565b611000806101506000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x4feae6769d748b4f0f7c9bf21d782236c88f13906789a3ec602961296e4c3e43"}}],"ommers":[]},{"header":{"parentHash":"0xb3535af5103fd1c2bbd6dc7ff23f0799037a6542c231ebcb85abd776560fa512","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x23d74fb99ff6e42cbb5c33f92b078e37be6af2b6092459b103ff7059a6517ebc","transactionsRoot":"0x9eab45eca206fe11c107ea985c7d02fcfa442836aea3e04ba11dc4df587d5aa6","receiptsRoot":"0xe25abcfa973db8c55f73292137c626430de130a382ad4466337fefb0f7c8fde0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x3ce3f","timestamp":"0x66b200cd","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1c0bc72b","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3d8a8","maxFeePerGas":"0x6211577c","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060405161068538038061068583398181016040528101906100329190610275565b818181600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361009b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100ae8161019d60201b61004f1760201c565b6100ef57806040517f8a8b41ec0000000000000000000000000000000000000000000000000000000081526004016100e691906102c4565b60405180910390fd5b806100fe6101b060201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050806101536101e160201b6100621760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050610414565b600080823b905060008111915050919050565b6000806040516020016101c290610362565b6040516020818303038152906040528051906020012090508091505090565b6000806040516020016101f3906103f4565b6040516020818303038152906040528051906020012090508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061024282610217565b9050919050565b61025281610237565b811461025d57600080fd5b50565b60008151905061026f81610249565b92915050565b6000806040838503121561028c5761028b610212565b5b600061029a85828601610260565b92505060206102ab85828601610260565b9150509250929050565b6102be81610237565b82525050565b60006020820190506102d960008301846102b5565b92915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b600061034c6021836102df565b9150610357826102f0565b604082019050919050565b6000602082019050818103600083015261037b8161033f565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006103de6023836102df565b91506103e982610382565b604082019050919050565b6000602082019050818103600083015261040d816103d1565b9050919050565b610262806104236000396000f3fe6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c6343000811003300000000000000000000000047d08dad17ccb558b3ea74b1a0e73a9cc804a9dc000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xb6794d5c7abed6f91d447e8efb72ef2580595a6d7c8dee57ba1dbb330970146a"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x29dd5614","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]}]} \ No newline at end of file diff --git a/crates/anvil/test-data/state-dump-legacy.json b/crates/anvil/test-data/state-dump-legacy.json index 0641b2f7b..273442701 100644 --- a/crates/anvil/test-data/state-dump-legacy.json +++ b/crates/anvil/test-data/state-dump-legacy.json @@ -1 +1 @@ -{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdc823","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xb92480171c0235f8c6710a4047d7ee14a3be58c630839fb4422826ff3a013e44","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc823","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}}],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdc80e","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xa00dc0c9ee9a888e67ea32d8772f8cc28eff62448c9ec985ee941fcbc921ba59","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc814","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}}],"ommers":[]}]} \ No newline at end of file +{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdc823","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xb92480171c0235f8c6710a4047d7ee14a3be58c630839fb4422826ff3a013e44","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc823","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}}],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdc80e","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xa00dc0c9ee9a888e67ea32d8772f8cc28eff62448c9ec985ee941fcbc921ba59","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc814","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}}],"ommers":[]}]} \ No newline at end of file diff --git a/crates/anvil/test-data/state-dump.json b/crates/anvil/test-data/state-dump.json index 3a3c478cf..e868bf2ef 100644 --- a/crates/anvil/test-data/state-dump.json +++ b/crates/anvil/test-data/state-dump.json @@ -1 +1 @@ -{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdcc2b","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xdb639d7f8af4f0ff2aa9cc49861820e72f5f8bfeeed677d1e3569f6b1625df4a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdcc25","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x3a52101c98a4319c419681131d3585d70a6cf13a9af25136be20d451eed5480a","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc29","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}},"impersonated_sender":null}],"ommers":[]},{"header":{"parentHash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc2b","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}},"impersonated_sender":null}],"ommers":[]}],"transactions":[{"info":{"transaction_hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3","transaction_index":0,"from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","block_number":1},{"info":{"transaction_hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515","transaction_index":0,"from":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","address":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x1f435a603c1bf6d544a90156b572b96d7a1730028422d800839bae78bb3506d0","block_number":2}]} \ No newline at end of file +{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdcc2b","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xdb639d7f8af4f0ff2aa9cc49861820e72f5f8bfeeed677d1e3569f6b1625df4a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdcc25","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x3a52101c98a4319c419681131d3585d70a6cf13a9af25136be20d451eed5480a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc29","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}},"impersonated_sender":null}],"ommers":[]},{"header":{"parentHash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc2b","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}},"impersonated_sender":null}],"ommers":[]}],"transactions":[{"info":{"transaction_hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3","transaction_index":0,"from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","block_number":1},{"info":{"transaction_hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515","transaction_index":0,"from":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","address":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x1f435a603c1bf6d544a90156b572b96d7a1730028422d800839bae78bb3506d0","block_number":2}]} \ No newline at end of file diff --git a/crates/anvil/tests/it/anvil.rs b/crates/anvil/tests/it/anvil.rs index 5a952da6b..65eeac70b 100644 --- a/crates/anvil/tests/it/anvil.rs +++ b/crates/anvil/tests/it/anvil.rs @@ -12,12 +12,14 @@ async fn test_can_change_mining_mode() { let provider = handle.http_provider(); assert!(api.anvil_get_auto_mine().unwrap()); + assert!(api.anvil_get_interval_mining().unwrap().is_none()); let num = provider.get_block_number().await.unwrap(); assert_eq!(num, 0); api.anvil_set_interval_mining(1).unwrap(); assert!(!api.anvil_get_auto_mine().unwrap()); + assert!(matches!(api.anvil_get_interval_mining().unwrap(), Some(1))); // changing the mining mode will instantly mine a new block tokio::time::sleep(std::time::Duration::from_millis(500)).await; let num = provider.get_block_number().await.unwrap(); @@ -30,6 +32,7 @@ async fn test_can_change_mining_mode() { // assert that no block is mined when the interval is set to 0 api.anvil_set_interval_mining(0).unwrap(); assert!(!api.anvil_get_auto_mine().unwrap()); + assert!(api.anvil_get_interval_mining().unwrap().is_none()); tokio::time::sleep(std::time::Duration::from_millis(1000)).await; let num = provider.get_block_number().await.unwrap(); assert_eq!(num, 1); diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index ce78d72ca..b75b088b0 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -13,7 +13,7 @@ use alloy_rpc_types::{ anvil::{ ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo, }, - BlockId, BlockNumberOrTag, TransactionRequest, + BlockId, BlockNumberOrTag, BlockTransactionsKind, TransactionRequest, }; use alloy_serde::WithOtherFields; use anvil::{ @@ -643,7 +643,7 @@ async fn test_fork_revert_call_latest_block_timestamp() { let Multicall::getCurrentBlockCoinbaseReturn { coinbase } = multicall_contract.getCurrentBlockCoinbase().call().await.unwrap(); - assert_eq!(coinbase, latest_block.header.miner); + assert_eq!(coinbase, latest_block.header.beneficiary); } #[tokio::test(flavor = "multi_thread")] @@ -718,14 +718,16 @@ async fn test_reorg() { // The first 3 reorged blocks should have 5 transactions each for num in 14..17 { - let block = provider.get_block_by_number(num.into(), true).await.unwrap(); + let block = + provider.get_block_by_number(num.into(), BlockTransactionsKind::Full).await.unwrap(); let block = block.unwrap(); assert_eq!(block.transactions.len(), 5); } // Verify that historic blocks are still accessible for num in (0..14).rev() { - let _ = provider.get_block_by_number(num.into(), true).await.unwrap(); + let _ = + provider.get_block_by_number(num.into(), BlockTransactionsKind::Full).await.unwrap(); } // Send a few more transaction to verify the chain can still progress @@ -777,7 +779,7 @@ async fn test_reorg() { let signature = accounts[5].sign_transaction_sync(&mut tx).unwrap(); let tx = tx.into_signed(signature); let mut encoded = vec![]; - tx.tx().encode_with_signature(tx.signature(), &mut encoded, false); + tx.eip2718_encode(&mut encoded); let pre_bal = provider.get_balance(accounts[5].address()).await.unwrap(); api.anvil_reorg(ReorgOptions { diff --git a/crates/anvil/tests/it/api.rs b/crates/anvil/tests/it/api.rs index c4172b265..946118af8 100644 --- a/crates/anvil/tests/it/api.rs +++ b/crates/anvil/tests/it/api.rs @@ -266,7 +266,7 @@ async fn can_call_on_pending_block() { .call() .await .unwrap(); - assert_eq!(block.header.miner, ret_coinbase); + assert_eq!(block.header.beneficiary, ret_coinbase); } } diff --git a/crates/anvil/tests/it/eip4844.rs b/crates/anvil/tests/it/eip4844.rs index a4243ce15..ea195f000 100644 --- a/crates/anvil/tests/it/eip4844.rs +++ b/crates/anvil/tests/it/eip4844.rs @@ -1,10 +1,10 @@ use crate::utils::{http_provider, http_provider_with_signer}; -use alloy_consensus::{SidecarBuilder, SimpleCoder}; +use alloy_consensus::{SidecarBuilder, SimpleCoder, Transaction}; use alloy_eips::eip4844::{BLOB_TX_MIN_BLOB_GASPRICE, DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK}; use alloy_network::{EthereumWallet, TransactionBuilder, TransactionBuilder4844}; use alloy_primitives::U256; use alloy_provider::Provider; -use alloy_rpc_types::{BlockId, TransactionRequest}; +use alloy_rpc_types::{BlockId, BlockTransactionsKind, TransactionRequest}; use alloy_serde::WithOtherFields; use anvil::{spawn, EthereumHardfork, NodeConfig}; @@ -176,8 +176,14 @@ async fn can_mine_blobs_when_exceeds_max_blobs() { let second_receipt = second_tx.get_receipt().await.unwrap(); let (first_block, second_block) = tokio::join!( - provider.get_block_by_number(first_receipt.block_number.unwrap().into(), false), - provider.get_block_by_number(second_receipt.block_number.unwrap().into(), false) + provider.get_block_by_number( + first_receipt.block_number.unwrap().into(), + BlockTransactionsKind::Hashes + ), + provider.get_block_by_number( + second_receipt.block_number.unwrap().into(), + BlockTransactionsKind::Hashes + ) ); assert_eq!( first_block.unwrap().unwrap().header.blob_gas_used, @@ -205,6 +211,7 @@ async fn can_check_blob_fields_on_genesis() { assert_eq!(block.header.excess_blob_gas, Some(0)); } +#[allow(clippy::disallowed_macros)] #[tokio::test(flavor = "multi_thread")] async fn can_correctly_estimate_blob_gas_with_recommended_fillers() { let node_config = NodeConfig::test().with_hardfork(Some(EthereumHardfork::Cancun.into())); @@ -238,7 +245,7 @@ async fn can_correctly_estimate_blob_gas_with_recommended_fillers() { receipt.block_number.expect("Failed to get block number") ); - assert!(tx.max_fee_per_blob_gas.unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); + assert!(tx.max_fee_per_blob_gas().unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); assert_eq!(receipt.from, alice); assert_eq!(receipt.to, Some(bob)); assert_eq!( @@ -247,6 +254,7 @@ async fn can_correctly_estimate_blob_gas_with_recommended_fillers() { ); } +#[allow(clippy::disallowed_macros)] #[tokio::test(flavor = "multi_thread")] async fn can_correctly_estimate_blob_gas_with_recommended_fillers_with_signer() { let node_config = NodeConfig::test().with_hardfork(Some(EthereumHardfork::Cancun.into())); @@ -283,7 +291,7 @@ async fn can_correctly_estimate_blob_gas_with_recommended_fillers_with_signer() receipt.block_number.expect("Failed to get block number") ); - assert!(tx.max_fee_per_blob_gas.unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); + assert!(tx.max_fee_per_blob_gas().unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); assert_eq!(receipt.from, alice); assert_eq!(receipt.to, Some(bob)); assert_eq!( diff --git a/crates/anvil/tests/it/eip7702.rs b/crates/anvil/tests/it/eip7702.rs index ab787e4eb..e10633d6c 100644 --- a/crates/anvil/tests/it/eip7702.rs +++ b/crates/anvil/tests/it/eip7702.rs @@ -66,7 +66,7 @@ async fn can_send_eip7702_tx() { let tx = tx.into_signed(signature); let mut encoded = Vec::new(); - tx.tx().encode_with_signature(tx.signature(), &mut encoded, false); + tx.eip2718_encode(&mut encoded); let receipt = provider.send_raw_transaction(&encoded).await.unwrap().get_receipt().await.unwrap(); diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index a35d7c267..3d470894b 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -5,7 +5,7 @@ use crate::{ utils::{http_provider, http_provider_with_signer}, }; use alloy_chains::NamedChain; -use alloy_network::{EthereumWallet, ReceiptResponse, TransactionBuilder}; +use alloy_network::{EthereumWallet, ReceiptResponse, TransactionBuilder, TransactionResponse}; use alloy_primitives::{address, b256, bytes, uint, Address, Bytes, TxHash, TxKind, U256, U64}; use alloy_provider::Provider; use alloy_rpc_types::{ @@ -1040,6 +1040,7 @@ async fn can_impersonate_in_fork() { // #[tokio::test(flavor = "multi_thread")] +#[ignore] async fn test_total_difficulty_fork() { let (api, handle) = spawn(fork_config()).await; @@ -1406,7 +1407,7 @@ async fn test_immutable_fork_transaction_hash() { api.backend.mined_transaction_by_block_hash_and_index(hash, expected.1.into()) }) .unwrap(); - assert_eq!(tx.inner.hash.to_string(), expected.0.to_string()); + assert_eq!(tx.tx_hash().to_string(), expected.0.to_string()); } } diff --git a/crates/anvil/tests/it/ipc.rs b/crates/anvil/tests/it/ipc.rs index 4f13f8aaf..e5d99e01b 100644 --- a/crates/anvil/tests/it/ipc.rs +++ b/crates/anvil/tests/it/ipc.rs @@ -54,7 +54,7 @@ async fn test_sub_new_heads_ipc() { let blocks = provider.subscribe_blocks().await.unwrap().into_stream(); let blocks = blocks.take(3).collect::>().await; - let block_numbers = blocks.into_iter().map(|b| b.header.number).collect::>(); + let block_numbers = blocks.into_iter().map(|b| b.number).collect::>(); assert_eq!(block_numbers, vec![1, 2, 3]); } diff --git a/crates/anvil/tests/it/logs.rs b/crates/anvil/tests/it/logs.rs index 3bf09493d..ac644e6e2 100644 --- a/crates/anvil/tests/it/logs.rs +++ b/crates/anvil/tests/it/logs.rs @@ -7,7 +7,7 @@ use crate::{ use alloy_network::EthereumWallet; use alloy_primitives::{map::B256HashSet, B256}; use alloy_provider::Provider; -use alloy_rpc_types::{BlockNumberOrTag, Filter}; +use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind, Filter}; use anvil::{spawn, NodeConfig}; use futures::StreamExt; @@ -55,7 +55,7 @@ async fn get_past_events() { // and we can fetch the events at a block hash // let hash = provider.get_block(1).await.unwrap().unwrap().hash.unwrap(); let hash = provider - .get_block_by_number(BlockNumberOrTag::from(1), false) + .get_block_by_number(BlockNumberOrTag::from(1), BlockTransactionsKind::Hashes) .await .unwrap() .unwrap() @@ -191,7 +191,10 @@ async fn watch_events() { assert_eq!(log.1.block_number.unwrap(), starting_block_number + i + 1); let hash = provider - .get_block_by_number(BlockNumberOrTag::from(starting_block_number + i + 1), false) + .get_block_by_number( + BlockNumberOrTag::from(starting_block_number + i + 1), + false.into(), + ) .await .unwrap() .unwrap() diff --git a/crates/anvil/tests/it/otterscan.rs b/crates/anvil/tests/it/otterscan.rs index e839c9986..37d21a29e 100644 --- a/crates/anvil/tests/it/otterscan.rs +++ b/crates/anvil/tests/it/otterscan.rs @@ -1,6 +1,7 @@ //! Tests for otterscan endpoints. use crate::abi::Multicall; +use alloy_network::TransactionResponse; use alloy_primitives::{address, Address, Bytes, U256}; use alloy_provider::Provider; use alloy_rpc_types::{ @@ -409,7 +410,7 @@ async fn ots_search_transactions_before() { // check each individual hash result.txs.iter().for_each(|tx| { - assert_eq!(hashes.pop(), Some(tx.hash)); + assert_eq!(hashes.pop(), Some(tx.tx_hash())); }); block = result.txs.last().unwrap().block_number.unwrap(); @@ -444,7 +445,7 @@ async fn ots_search_transactions_after() { // check each individual hash result.txs.iter().rev().for_each(|tx| { - assert_eq!(hashes.pop_back(), Some(tx.hash)); + assert_eq!(hashes.pop_back(), Some(tx.tx_hash())); }); block = result.txs.first().unwrap().block_number.unwrap(); diff --git a/crates/anvil/tests/it/pubsub.rs b/crates/anvil/tests/it/pubsub.rs index a343f7c70..948456055 100644 --- a/crates/anvil/tests/it/pubsub.rs +++ b/crates/anvil/tests/it/pubsub.rs @@ -23,7 +23,7 @@ async fn test_sub_new_heads() { api.anvil_set_interval_mining(1).unwrap(); let blocks = blocks.into_stream().take(3).collect::>().await; - let block_numbers = blocks.into_iter().map(|b| b.header.number).collect::>(); + let block_numbers = blocks.into_iter().map(|b| b.number).collect::>(); assert_eq!(block_numbers, vec![1, 2, 3]); } @@ -247,6 +247,7 @@ async fn test_subscriptions() { assert_eq!(blocks, vec![1, 2, 3]) } +#[allow(clippy::disallowed_macros)] #[tokio::test(flavor = "multi_thread")] async fn test_sub_new_heads_fast() { let (api, handle) = spawn(NodeConfig::test()).await; @@ -261,7 +262,7 @@ async fn test_sub_new_heads_fast() { let mut block_numbers = Vec::new(); for _ in 0..num { api.mine_one().await; - let block_number = blocks.next().await.unwrap().header.number; + let block_number = blocks.next().await.unwrap().number; block_numbers.push(block_number); } diff --git a/crates/anvil/tests/it/transaction.rs b/crates/anvil/tests/it/transaction.rs index 07c120d1c..0afce986b 100644 --- a/crates/anvil/tests/it/transaction.rs +++ b/crates/anvil/tests/it/transaction.rs @@ -2,7 +2,7 @@ use crate::{ abi::{Greeter, Multicall, SimpleStorage}, utils::{connect_pubsub, http_provider_with_signer}, }; -use alloy_network::{EthereumWallet, TransactionBuilder}; +use alloy_network::{EthereumWallet, TransactionBuilder, TransactionResponse}; use alloy_primitives::{map::B256HashSet, Address, Bytes, FixedBytes, U256}; use alloy_provider::Provider; use alloy_rpc_types::{ @@ -718,7 +718,7 @@ async fn can_get_pending_transaction() { api.mine_one().await; let mined = provider.get_transaction_by_hash(*tx.tx_hash()).await.unwrap().unwrap(); - assert_eq!(mined.hash, pending.unwrap().unwrap().hash); + assert_eq!(mined.tx_hash(), pending.unwrap().unwrap().tx_hash()); } #[tokio::test(flavor = "multi_thread")] diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index a16436dd2..f010c279e 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -1,5 +1,5 @@ use crate::cmd::{ - access_list::AccessListArgs, bind::BindArgs, call::CallArgs, + access_list::AccessListArgs, artifact::ArtifactArgs, bind::BindArgs, call::CallArgs, constructor_args::ConstructorArgsArgs, create2::Create2Args, creation_code::CreationCodeArgs, estimate::EstimateArgs, find_block::FindBlockArgs, interface::InterfaceArgs, logs::LogsArgs, mktx::MakeTxArgs, rpc::RpcArgs, run::RunArgs, send::SendTxArgs, storage::StorageArgs, @@ -9,7 +9,7 @@ use alloy_primitives::{Address, B256, U256}; use alloy_rpc_types::BlockId; use clap::{Parser, Subcommand, ValueHint}; use eyre::Result; -use foundry_cli::opts::{EtherscanOpts, RpcOpts, ShellOpts}; +use foundry_cli::opts::{EtherscanOpts, GlobalOpts, RpcOpts}; use foundry_common::ens::NameOrAddress; use std::{path::PathBuf, str::FromStr}; @@ -31,11 +31,12 @@ const VERSION_MESSAGE: &str = concat!( next_display_order = None, )] pub struct Cast { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(subcommand)] pub cmd: CastSubcommand, - - #[clap(flatten)] - pub shell: ShellOpts, } #[derive(Subcommand)] @@ -793,7 +794,7 @@ pub enum CastSubcommand { who: Option, /// Perform a reverse lookup to verify that the name is correct. - #[arg(long, short)] + #[arg(long)] verify: bool, #[command(flatten)] @@ -807,7 +808,7 @@ pub enum CastSubcommand { who: Option
, /// Perform a normal lookup to verify that the address is correct. - #[arg(long, short)] + #[arg(long)] verify: bool, #[command(flatten)] @@ -927,6 +928,10 @@ pub enum CastSubcommand { #[command(visible_alias = "cc")] CreationCode(CreationCodeArgs), + /// Generate an artifact file, that can be used to deploy a contract locally. + #[command(visible_alias = "ar")] + Artifact(ArtifactArgs), + /// Display constructor arguments used for the contract initialization. #[command(visible_alias = "cra")] ConstructorArgs(ConstructorArgsArgs), diff --git a/crates/cast/bin/cmd/artifact.rs b/crates/cast/bin/cmd/artifact.rs new file mode 100644 index 000000000..2e7a7cae0 --- /dev/null +++ b/crates/cast/bin/cmd/artifact.rs @@ -0,0 +1,95 @@ +use alloy_primitives::Address; +use alloy_provider::Provider; +use clap::{command, Parser}; +use eyre::Result; +use foundry_block_explorers::Client; +use foundry_cli::{ + opts::{EtherscanOpts, RpcOpts}, + utils, +}; +use foundry_common::fs; +use foundry_config::Config; +use serde_json::json; +use std::path::PathBuf; + +use super::{ + creation_code::{fetch_creation_code, parse_code_output}, + interface::{fetch_abi_from_etherscan, load_abi_from_file}, +}; + +/// CLI arguments for `cast artifact`. +#[derive(Parser)] +pub struct ArtifactArgs { + /// An Ethereum address, for which the artifact will be produced. + contract: Address, + + /// Path to file containing the contract's JSON ABI. It's necessary if the target contract is + /// not verified on Etherscan. + #[arg(long)] + abi_path: Option, + + /// The path to the output file. + /// + /// If not specified, the artifact will be output to stdout. + #[arg( + short, + long, + value_hint = clap::ValueHint::FilePath, + value_name = "PATH", + )] + output: Option, + + #[command(flatten)] + etherscan: EtherscanOpts, + + #[command(flatten)] + rpc: RpcOpts, +} + +impl ArtifactArgs { + pub async fn run(self) -> Result<()> { + let Self { contract, etherscan, rpc, output: output_location, abi_path } = self; + + let mut etherscan = etherscan; + let config = Config::from(&rpc); + let provider = utils::get_provider(&config)?; + let api_key = etherscan.key().unwrap_or_default(); + let chain = provider.get_chain_id().await?; + etherscan.chain = Some(chain.into()); + let client = Client::new(chain.into(), api_key)?; + + let abi = if let Some(ref abi_path) = abi_path { + load_abi_from_file(abi_path, None)? + } else { + fetch_abi_from_etherscan(contract, ðerscan).await? + }; + + let (abi, _) = abi.first().ok_or_else(|| eyre::eyre!("No ABI found"))?; + + let bytecode = fetch_creation_code(contract, client, provider).await?; + let bytecode = + parse_code_output(bytecode, contract, ðerscan, abi_path.as_deref(), true, false) + .await?; + + let artifact = json!({ + "abi": abi, + "bytecode": { + "object": bytecode + } + }); + + let artifact = serde_json::to_string_pretty(&artifact)?; + + if let Some(loc) = output_location { + if let Some(parent) = loc.parent() { + fs::create_dir_all(parent)?; + } + fs::write(&loc, artifact)?; + sh_println!("Saved artifact at {}", loc.display())?; + } else { + sh_println!("{artifact}")?; + } + + Ok(()) + } +} diff --git a/crates/cast/bin/cmd/constructor_args.rs b/crates/cast/bin/cmd/constructor_args.rs index b0a08704f..8fe42c93c 100644 --- a/crates/cast/bin/cmd/constructor_args.rs +++ b/crates/cast/bin/cmd/constructor_args.rs @@ -1,5 +1,6 @@ use alloy_dyn_abi::DynSolType; use alloy_primitives::{Address, Bytes}; +use alloy_provider::Provider; use clap::{command, Parser}; use eyre::{eyre, OptionExt, Result}; use foundry_block_explorers::Client; @@ -36,13 +37,13 @@ impl ConstructorArgsArgs { pub async fn run(self) -> Result<()> { let Self { contract, etherscan, rpc, abi_path } = self; - let config = Config::from(ðerscan); - let chain = config.chain.unwrap_or_default(); - let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let client = Client::new(chain, api_key)?; - + let mut etherscan = etherscan; let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; + let api_key = etherscan.key().unwrap_or_default(); + let chain = provider.get_chain_id().await?; + etherscan.chain = Some(chain.into()); + let client = Client::new(chain.into(), api_key)?; let bytecode = fetch_creation_code(contract, client, provider).await?; diff --git a/crates/cast/bin/cmd/create2.rs b/crates/cast/bin/cmd/create2.rs index 17523e094..f46066137 100644 --- a/crates/cast/bin/cmd/create2.rs +++ b/crates/cast/bin/cmd/create2.rs @@ -4,7 +4,6 @@ use eyre::{Result, WrapErr}; use rand::{rngs::StdRng, RngCore, SeedableRng}; use regex::RegexSetBuilder; use std::{ - num::NonZeroUsize, sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -73,9 +72,9 @@ pub struct Create2Args { #[arg(alias = "ch", long, value_name = "HASH", required_unless_present = "init_code")] init_code_hash: Option, - /// Number of threads to use. Defaults to and caps at the number of logical cores. - #[arg(short, long)] - jobs: Option, + /// Number of threads to use. Specifying 0 defaults to the number of logical cores. + #[arg(global = true, long, short = 'j', visible_alias = "jobs")] + threads: Option, /// Address of the caller. Used for the first 20 bytes of the salt. #[arg(long, value_name = "ADDRESS")] @@ -107,7 +106,7 @@ impl Create2Args { salt, init_code, init_code_hash, - jobs, + threads, caller, seed, no_random, @@ -168,8 +167,8 @@ impl Create2Args { let regex = RegexSetBuilder::new(regexs).case_insensitive(!case_sensitive).build()?; let mut n_threads = std::thread::available_parallelism().map_or(1, |n| n.get()); - if let Some(jobs) = jobs { - n_threads = n_threads.min(jobs.get()); + if let Some(threads) = threads { + n_threads = n_threads.min(threads); } if cfg!(test) { n_threads = n_threads.min(2); @@ -433,8 +432,14 @@ mod tests { #[test] fn j0() { - let e = - Create2Args::try_parse_from(["foundry-cli", "--starts-with=00", "-j0"]).unwrap_err(); - let _ = e.print(); + let args = Create2Args::try_parse_from([ + "foundry-cli", + "--starts-with=00", + "--init-code-hash", + &B256::ZERO.to_string(), + "-j0", + ]) + .unwrap(); + assert_eq!(args.threads, Some(0)); } } diff --git a/crates/cast/bin/cmd/creation_code.rs b/crates/cast/bin/cmd/creation_code.rs index bcafeac94..b444bff32 100644 --- a/crates/cast/bin/cmd/creation_code.rs +++ b/crates/cast/bin/cmd/creation_code.rs @@ -1,3 +1,4 @@ +use alloy_consensus::Transaction; use alloy_primitives::{Address, Bytes}; use alloy_provider::{ext::TraceApi, Provider}; use alloy_rpc_types::trace::parity::{Action, CreateAction, CreateOutput, TraceOutput}; @@ -49,19 +50,25 @@ impl CreationCodeArgs { let Self { contract, etherscan, rpc, disassemble, without_args, only_args, abi_path } = self; - let config = Config::from(ðerscan); - let chain = config.chain.unwrap_or_default(); - let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let client = Client::new(chain, api_key)?; - + let mut etherscan = etherscan; let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; + let api_key = etherscan.key().unwrap_or_default(); + let chain = provider.get_chain_id().await?; + etherscan.chain = Some(chain.into()); + let client = Client::new(chain.into(), api_key)?; let bytecode = fetch_creation_code(contract, client, provider).await?; - let bytecode = - parse_code_output(bytecode, contract, ðerscan, abi_path, without_args, only_args) - .await?; + let bytecode = parse_code_output( + bytecode, + contract, + ðerscan, + abi_path.as_deref(), + without_args, + only_args, + ) + .await?; if disassemble { let _ = sh_println!("{}", SimpleCast::disassemble(&bytecode)?); @@ -77,11 +84,11 @@ impl CreationCodeArgs { /// - The complete bytecode /// - The bytecode without constructor arguments /// - Only the constructor arguments -async fn parse_code_output( +pub async fn parse_code_output( bytecode: Bytes, contract: Address, etherscan: &EtherscanOpts, - abi_path: Option, + abi_path: Option<&str>, without_args: bool, only_args: bool, ) -> Result { @@ -90,7 +97,7 @@ async fn parse_code_output( } let abi = if let Some(abi_path) = abi_path { - load_abi_from_file(&abi_path, None)? + load_abi_from_file(abi_path, None)? } else { fetch_abi_from_etherscan(contract, etherscan).await? }; @@ -137,9 +144,9 @@ pub async fn fetch_creation_code( let tx_data = provider.get_transaction_by_hash(creation_tx_hash).await?; let tx_data = tx_data.ok_or_eyre("Could not find creation tx data.")?; - let bytecode = if tx_data.inner.to.is_none() { + let bytecode = if tx_data.to().is_none() { // Contract was created using a standard transaction - tx_data.inner.input + tx_data.input().clone() } else { // Contract was created using a factory pattern or create2 // Extract creation code from tx traces diff --git a/crates/cast/bin/cmd/mod.rs b/crates/cast/bin/cmd/mod.rs index 49e3ed2ef..3f57b7668 100644 --- a/crates/cast/bin/cmd/mod.rs +++ b/crates/cast/bin/cmd/mod.rs @@ -6,6 +6,7 @@ //! [`foundry_config::Config`]. pub mod access_list; +pub mod artifact; pub mod bind; pub mod call; pub mod constructor_args; diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 11c7b507e..79083fa8d 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -1,3 +1,5 @@ +use alloy_consensus::Transaction; +use alloy_network::TransactionResponse; use alloy_primitives::U256; use alloy_provider::Provider; use alloy_rpc_types::BlockTransactions; @@ -5,10 +7,10 @@ use cast::revm::primitives::EnvWithHandlerCfg; use clap::Parser; use eyre::{Result, WrapErr}; use foundry_cli::{ - opts::RpcOpts, + opts::{EtherscanOpts, RpcOpts}, utils::{handle_traces, init_progress, TraceResult}, }; -use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; +use foundry_common::{is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE}; use foundry_compilers::artifacts::EvmVersion; use foundry_config::{ figment::{ @@ -48,23 +50,22 @@ pub struct RunArgs { #[arg(long)] quick: bool, - /// Prints the full address of the contract. - #[arg(long, short)] - verbose: bool, - /// Label addresses in the trace. /// /// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth #[arg(long, short)] label: Vec, + #[command(flatten)] + etherscan: EtherscanOpts, + #[command(flatten)] rpc: RpcOpts, /// The EVM version to use. /// /// Overrides the version specified in the config. - #[arg(long, short)] + #[arg(long)] evm_version: Option, /// Sets the number of assumed available compute units per second for this provider @@ -116,10 +117,11 @@ impl RunArgs { .ok_or_else(|| eyre::eyre!("tx not found: {:?}", tx_hash))?; // check if the tx is a system transaction - if is_known_system_sender(tx.from) || tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) { + if is_known_system_sender(tx.from) || tx.transaction_type() == Some(SYSTEM_TRANSACTION_TYPE) + { return Err(eyre::eyre!( "{:?} is a system transaction.\nReplaying system transactions is currently not supported.", - tx.hash + tx.tx_hash() )); } @@ -141,7 +143,7 @@ impl RunArgs { if let Some(block) = &block { env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.miner; + env.block.coinbase = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); @@ -185,27 +187,28 @@ impl RunArgs { // we skip them otherwise this would cause // reverts if is_known_system_sender(tx.from) || - tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) + tx.transaction_type() == Some(SYSTEM_TRANSACTION_TYPE) { pb.set_position((index + 1) as u64); continue; } - if tx.hash == tx_hash { + if tx.tx_hash() == tx_hash { break; } configure_tx_env(&mut env, &tx.inner); - if let Some(to) = tx.to { - trace!(tx=?tx.hash,?to, "executing previous call transaction"); + if let Some(to) = Transaction::to(tx) { + trace!(tx=?tx.tx_hash(),?to, "executing previous call transaction"); executor.transact_with_env(env.clone()).wrap_err_with(|| { format!( "Failed to execute transaction: {:?} in block {}", - tx.hash, env.block.number + tx.tx_hash(), + env.block.number ) })?; } else { - trace!(tx=?tx.hash, "executing previous create transaction"); + trace!(tx=?tx.tx_hash(), "executing previous create transaction"); if let Err(error) = executor.deploy_with_env(env.clone(), None) { match error { // Reverted transactions should be skipped @@ -214,7 +217,8 @@ impl RunArgs { return Err(error).wrap_err_with(|| { format!( "Failed to deploy transaction: {:?} in block {}", - tx.hash, env.block.number + tx.tx_hash(), + env.block.number ) }) } @@ -233,11 +237,11 @@ impl RunArgs { configure_tx_env(&mut env, &tx.inner); - if let Some(to) = tx.to { - trace!(tx=?tx.hash, to=?to, "executing call transaction"); + if let Some(to) = Transaction::to(&tx) { + trace!(tx=?tx.tx_hash(), to=?to, "executing call transaction"); TraceResult::try_from(executor.transact_with_env(env))? } else { - trace!(tx=?tx.hash, "executing create transaction"); + trace!(tx=?tx.tx_hash(), "executing create transaction"); TraceResult::try_from(executor.deploy_with_env(env, None))? } }; @@ -249,7 +253,7 @@ impl RunArgs { self.label, self.debug, self.decode_internal, - self.verbose, + shell::verbosity() > 0, ) .await?; @@ -269,6 +273,10 @@ impl figment::Provider for RunArgs { map.insert("alphanet".into(), self.alphanet.into()); } + if let Some(api_key) = &self.etherscan.key { + map.insert("etherscan_api_key".into(), api_key.as_str().into()); + } + if let Some(evm_version) = self.evm_version { map.insert("evm_version".into(), figment::value::Value::serialize(evm_version)?); } diff --git a/crates/cast/bin/cmd/send.rs b/crates/cast/bin/cmd/send.rs index 7361983d0..e332c4824 100644 --- a/crates/cast/bin/cmd/send.rs +++ b/crates/cast/bin/cmd/send.rs @@ -23,7 +23,7 @@ use foundry_cli::{ }; use foundry_common::ens::NameOrAddress; use foundry_config::Config; -use std::{path::PathBuf, str::FromStr}; +use std::{path::PathBuf, str::FromStr, sync::Arc}; /// ZkSync-specific paymaster parameters for transactions #[derive(Debug, Parser)] @@ -197,20 +197,23 @@ impl SendTxArgs { // move the signers to their respective blocks. if zksync_params.zksync { // Retrieve the signer, and bail if it can't be constructed. - let zk_signer: foundry_wallets::WalletSigner = eth.wallet.signer().await?; - let from = zk_signer.address(); + let signer = eth.wallet.signer().await?; + let from = signer.address(); tx::validate_from_address(eth.wallet.from, from)?; // Zksync transaction - let (tx, _) = builder.build(&zk_signer).await?; + let (tx, _) = builder.build(&signer).await?; + let signer = Arc::new(signer); - let zk_wallet = ZksyncWallet::from(zk_signer); + let zk_wallet = ZksyncWallet::from(signer.clone()); let zk_provider = ProviderBuilder::<_, _, Zksync>::default() .wallet(zk_wallet.clone()) .on_provider(&zk_provider); + + let wallet = EthereumWallet::from(signer); let provider = ProviderBuilder::<_, _, AnyNetwork>::default() - .wallet(zk_wallet) + .wallet(wallet) .on_provider(&provider); cast_send_zk( @@ -280,7 +283,7 @@ async fn cast_send_zk, Z: ZksyncProvider, T: Trans tx.inner.transaction_type = Some(zksync_types::l2::TransactionType::EIP712Transaction as u8); let mut zk_tx: ZkTransactionRequest = tx.inner.clone().into(); if let Some(paymaster_params) = paymaster_params { - zk_tx.set_paymaster(paymaster_params); + zk_tx.set_paymaster_params(paymaster_params); } foundry_zksync_core::estimate_gas(&mut zk_tx, &zk_provider).await?; diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs index 9fca4172e..13fa908bc 100644 --- a/crates/cast/bin/cmd/storage.rs +++ b/crates/cast/bin/cmd/storage.rs @@ -17,12 +17,13 @@ use foundry_common::{ abi::find_source, compile::{etherscan_project, ProjectCompiler}, ens::NameOrAddress, + shell, }; use foundry_compilers::{ artifacts::{ConfigurableContractArtifact, StorageLayout}, compilers::{ solc::{Solc, SolcCompiler}, - Compiler, CompilerSettings, + Compiler, }, Artifact, Project, }; @@ -31,6 +32,7 @@ use foundry_config::{ impl_figment_convert_cast, Config, }; use semver::Version; +use serde::{Deserialize, Serialize}; use std::str::FromStr; /// The minimum Solc version for outputting storage layouts. @@ -45,7 +47,7 @@ pub struct StorageArgs { #[arg(value_parser = NameOrAddress::from_str)] address: NameOrAddress, - /// The storage slot number. + /// The storage slot number. If not provided, it gets the full storage layout. #[arg(value_parser = parse_slot)] slot: Option, @@ -109,19 +111,22 @@ impl StorageArgs { if project.paths.has_input_files() { // Find in artifacts and pretty print add_storage_layout_output(&mut project); - let out = ProjectCompiler::new().compile(&project)?; + let out = ProjectCompiler::new().quiet(shell::is_json()).compile(&project)?; let artifact = out.artifacts().find(|(_, artifact)| { artifact.get_deployed_bytecode_bytes().is_some_and(|b| *b == address_code) }); if let Some((_, artifact)) = artifact { - return fetch_and_print_storage(provider, address, block, artifact, true).await; + return fetch_and_print_storage( + provider, + address, + block, + artifact, + !shell::is_json(), + ) + .await; } } - // Not a forge project or artifact not found - // Get code from Etherscan - sh_warn!("No matching artifacts found, fetching source code from Etherscan...")?; - if !self.etherscan.has_key() { eyre::bail!("You must provide an Etherscan API key if you're fetching a remote contract's storage."); } @@ -180,7 +185,7 @@ impl StorageArgs { // Clear temp directory root.close()?; - fetch_and_print_storage(provider, address, block, artifact, true).await + fetch_and_print_storage(provider, address, block, artifact, !shell::is_json()).await } } @@ -215,6 +220,14 @@ impl StorageValue { } } +/// Represents the storage layout of a contract and its values. +#[derive(Clone, Debug, Serialize, Deserialize)] +struct StorageReport { + #[serde(flatten)] + layout: StorageLayout, + values: Vec, +} + async fn fetch_and_print_storage, T: Transport + Clone>( provider: P, address: Address, @@ -255,7 +268,22 @@ async fn fetch_storage_slots, T: Transport + Clone>( fn print_storage(layout: StorageLayout, values: Vec, pretty: bool) -> Result<()> { if !pretty { - sh_println!("{}", serde_json::to_string_pretty(&serde_json::to_value(layout)?)?)?; + let values: Vec<_> = layout + .storage + .iter() + .zip(&values) + .map(|(slot, storage_value)| { + let storage_type = layout.types.get(&slot.storage_type); + storage_value.value( + slot.offset, + storage_type.and_then(|t| t.number_of_bytes.parse::().ok()), + ) + }) + .collect(); + sh_println!( + "{}", + serde_json::to_string_pretty(&serde_json::to_value(StorageReport { layout, values })?)? + )?; return Ok(()) } @@ -288,7 +316,7 @@ fn print_storage(layout: StorageLayout, values: Vec, pretty: bool) fn add_storage_layout_output(project: &mut Project) { project.artifacts.additional_values.storage_layout = true; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { selection.0.values_mut().for_each(|contract_selection| { contract_selection .values_mut() diff --git a/crates/cast/bin/cmd/wallet/mod.rs b/crates/cast/bin/cmd/wallet/mod.rs index 8023b8bdf..b6dea48e1 100644 --- a/crates/cast/bin/cmd/wallet/mod.rs +++ b/crates/cast/bin/cmd/wallet/mod.rs @@ -183,10 +183,6 @@ pub enum WalletSubcommands { #[arg(value_name = "MNEMONIC_INDEX_OR_DERIVATION_PATH")] mnemonic_index_or_derivation_path_override: Option, - /// Verbose mode, print the address and private key. - #[arg(short = 'v', long)] - verbose: bool, - #[command(flatten)] wallet: WalletOpts, }, @@ -462,7 +458,6 @@ flag to set your key via: wallet, mnemonic_override, mnemonic_index_or_derivation_path_override, - verbose, } => { let (index_override, derivation_path_override) = match mnemonic_index_or_derivation_path_override { @@ -485,7 +480,7 @@ flag to set your key via: .await?; match wallet { WalletSigner::Local(wallet) => { - if verbose { + if shell::verbosity() > 0 { sh_println!("Address: {}", wallet.address())?; sh_println!( "Private key: 0x{}", diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index 480ad3ce6..7df33496a 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate tracing; +use alloy_dyn_abi::DynSolValue; use alloy_primitives::{eip191_hash_message, hex, keccak256, Address, B256}; use alloy_provider::Provider; use alloy_rpc_types::{BlockId, BlockNumberOrTag::Latest}; @@ -12,7 +13,7 @@ use foundry_cli::{handler, utils}; use foundry_common::{ abi::get_event, ens::{namehash, ProviderEnsExt}, - fmt::{format_uint_exp, print_tokens}, + fmt::{format_tokens, format_tokens_raw, format_uint_exp}, fs, selectors::{ decode_calldata, decode_event_topic, decode_function_selector, decode_selectors, @@ -54,8 +55,9 @@ fn run() -> Result<()> { utils::load_dotenv(); utils::subscriber(); utils::enable_paint(); + let args = CastArgs::parse(); - args.shell.shell().set(); + args.global.init()?; main_args(args) } @@ -140,11 +142,11 @@ async fn main_args(args: CastArgs) -> Result<()> { } CastSubcommand::ParseUnits { value, unit } => { let value = stdin::unwrap_line(value)?; - println!("{}", SimpleCast::parse_units(&value, unit)?); + sh_println!("{}", SimpleCast::parse_units(&value, unit)?)?; } CastSubcommand::FormatUnits { value, unit } => { let value = stdin::unwrap_line(value)?; - println!("{}", SimpleCast::format_units(&value, unit)?); + sh_println!("{}", SimpleCast::format_units(&value, unit)?)?; } CastSubcommand::FromWei { value, unit } => { let value = stdin::unwrap_line(value)?; @@ -194,7 +196,7 @@ async fn main_args(args: CastArgs) -> Result<()> { // ABI encoding & decoding CastSubcommand::AbiDecode { sig, calldata, input } => { let tokens = SimpleCast::abi_decode(&sig, &calldata, input)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::AbiEncode { sig, packed, args } => { if !packed { @@ -205,18 +207,19 @@ async fn main_args(args: CastArgs) -> Result<()> { } CastSubcommand::CalldataDecode { sig, calldata } => { let tokens = SimpleCast::calldata_decode(&sig, &calldata, true)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::CalldataEncode { sig, args } => { sh_println!("{}", SimpleCast::calldata_encode(sig, &args)?)?; } CastSubcommand::StringDecode { data } => { let tokens = SimpleCast::calldata_decode("Any(string)", &data, true)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::Interface(cmd) => cmd.run().await?, CastSubcommand::CreationCode(cmd) => cmd.run().await?, CastSubcommand::ConstructorArgs(cmd) => cmd.run().await?, + CastSubcommand::Artifact(cmd) => cmd.run().await?, CastSubcommand::Bind(cmd) => cmd.run().await?, CastSubcommand::PrettyCalldata { calldata, offline } => { let calldata = stdin::unwrap_line(calldata)?; @@ -487,7 +490,7 @@ async fn main_args(args: CastArgs) -> Result<()> { }; let tokens = SimpleCast::calldata_decode(sig, &calldata, true)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::FourByteEvent { topic } => { let topic = stdin::unwrap_line(topic)?; @@ -623,5 +626,22 @@ async fn main_args(args: CastArgs) -> Result<()> { sh_println!("{}", SimpleCast::decode_eof(&eof)?)? } }; + + /// Prints slice of tokens using [`format_tokens`] or [`format_tokens_raw`] depending whether + /// the shell is in JSON mode. + /// + /// This is included here to avoid a cyclic dependency between `fmt` and `common`. + fn print_tokens(tokens: &[DynSolValue]) { + if shell::is_json() { + let tokens: Vec = format_tokens_raw(tokens).collect(); + let _ = sh_println!("{}", serde_json::to_string_pretty(&tokens).unwrap()); + } else { + let tokens = format_tokens(tokens); + tokens.for_each(|t| { + let _ = sh_println!("{t}"); + }); + } + } + Ok(()) } diff --git a/crates/cast/bin/tx.rs b/crates/cast/bin/tx.rs index cf355d7b5..1eb0ee201 100644 --- a/crates/cast/bin/tx.rs +++ b/crates/cast/bin/tx.rs @@ -252,7 +252,7 @@ where }; if self.state.to.is_none() && code.is_none() { - let has_value = self.tx.value.map_or(false, |v| !v.is_zero()); + let has_value = self.tx.value.is_some_and(|v| !v.is_zero()); let has_auth = self.auth.is_some(); // We only allow user to omit the recipient address if transaction is an EIP-7702 tx // without a value. diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index d8776e3b5..01741ae1e 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -787,9 +787,9 @@ where .ok_or_else(|| eyre::eyre!("tx not found: {:?}", tx_hash))?; Ok(if raw { - format!("0x{}", hex::encode(TxEnvelope::try_from(tx.inner)?.encoded_2718())) + format!("0x{}", hex::encode(tx.inner.inner.encoded_2718())) } else if let Some(field) = field { - get_pretty_tx_attr(&tx, field.as_str()) + get_pretty_tx_attr(&tx.inner, field.as_str()) .ok_or_else(|| eyre::eyre!("invalid tx field: {}", field.to_string()))? } else if shell::is_json() { // to_value first to sort json object keys @@ -1051,7 +1051,7 @@ where Either::Right(futures::future::pending()) } => { if let (Some(block), Some(to_block)) = (block, to_block_number) { - if block.header.number > to_block { + if block.number > to_block { break; } } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 057c72109..0d945fe8f 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -6,11 +6,11 @@ use anvil::{EthereumHardfork, NodeConfig}; use foundry_test_utils::{ casttest, file, rpc::{ - next_http_rpc_endpoint, next_mainnet_etherscan_api_key, next_rpc_endpoint, - next_ws_rpc_endpoint, + next_etherscan_api_key, next_http_rpc_endpoint, next_mainnet_etherscan_api_key, + next_rpc_endpoint, next_ws_rpc_endpoint, }, str, - util::{self, OutputExt}, + util::OutputExt, ZkSyncNode, }; use std::{fs, io::Write, path::Path, str::FromStr}; @@ -33,12 +33,17 @@ Options: -h, --help Print help (see a summary with '-h') + -j, --threads + Number of threads to use. Specifying 0 defaults to the number of logical cores + + [aliases: jobs] + -V, --version Print version Display options: --color - Log messages coloring + The color of the log messages Possible values: - auto: Intelligently guess whether to use color output (default) @@ -51,8 +56,18 @@ Display options: -q, --quiet Do not print log messages - --verbose - Use verbose output + -v, --verbosity... + Verbosity level of the log messages. + + Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + + Depending on the context the verbosity levels have different meanings. + + For example, the verbosity levels of the EVM are: + - 2 (-vv): Print logs for all tests. + - 3 (-vvv): Print execution traces for failing tests. + - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + - 5 (-vvvvv): Print execution and setup traces for all tests. Find more information in the book: http://book.getfoundry.sh/reference/cast/cast.html @@ -645,8 +660,7 @@ casttest!(rpc_with_args, |_prj, cmd| { // Call `cast rpc eth_getBlockByNumber 0x123 false` cmd.args(["rpc", "--rpc-url", eth_rpc_url.as_str(), "eth_getBlockByNumber", "0x123", "false"]) - .assert_success() - .stdout_eq(str![[r#" + .assert_json_stdout(str![[r#" {"number":"0x123","hash":"0xc5dab4e189004a1312e9db43a40abb2de91ad7dd25e75880bf36016d8e9df524","transactions":[],"totalDifficulty":"0x4dea420908b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","nonce":"0x29d6547c196e00e0","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","difficulty":"0x494433b31","gasLimit":"0x1388","gasUsed":"0x0","uncles":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x3fe6bd17aa85376c7d566df97d9f2e536f37f7a87abb3a6f9e2891cf9442f2e4","mixHash":"0x943056aa305aa6d22a3c06110942980342d1f4d4b11c17711961436a0f963ea0","parentHash":"0x7abfd11e862ccde76d6ea8ee20978aac26f4bcb55de1188cc0335be13e817017","timestamp":"0x55ba4564"} "#]]); @@ -665,8 +679,7 @@ casttest!(rpc_raw_params, |_prj, cmd| { "--raw", r#"["0x123", false]"#, ]) - .assert_success() - .stdout_eq(str![[r#" + .assert_json_stdout(str![[r#" {"number":"0x123","hash":"0xc5dab4e189004a1312e9db43a40abb2de91ad7dd25e75880bf36016d8e9df524","transactions":[],"totalDifficulty":"0x4dea420908b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","nonce":"0x29d6547c196e00e0","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","difficulty":"0x494433b31","gasLimit":"0x1388","gasUsed":"0x0","uncles":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x3fe6bd17aa85376c7d566df97d9f2e536f37f7a87abb3a6f9e2891cf9442f2e4","mixHash":"0x943056aa305aa6d22a3c06110942980342d1f4d4b11c17711961436a0f963ea0","parentHash":"0x7abfd11e862ccde76d6ea8ee20978aac26f4bcb55de1188cc0335be13e817017","timestamp":"0x55ba4564"} "#]]); @@ -682,8 +695,7 @@ casttest!(rpc_raw_params_stdin, |_prj, cmd| { stdin.write_all(b"\n[\n\"0x123\",\nfalse\n]\n").unwrap(); }, ) - .assert_success() - .stdout_eq(str![[r#" + .assert_json_stdout(str![[r#" {"number":"0x123","hash":"0xc5dab4e189004a1312e9db43a40abb2de91ad7dd25e75880bf36016d8e9df524","transactions":[],"totalDifficulty":"0x4dea420908b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","nonce":"0x29d6547c196e00e0","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","difficulty":"0x494433b31","gasLimit":"0x1388","gasUsed":"0x0","uncles":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x3fe6bd17aa85376c7d566df97d9f2e536f37f7a87abb3a6f9e2891cf9442f2e4","mixHash":"0x943056aa305aa6d22a3c06110942980342d1f4d4b11c17711961436a0f963ea0","parentHash":"0x7abfd11e862ccde76d6ea8ee20978aac26f4bcb55de1188cc0335be13e817017","timestamp":"0x55ba4564"} "#]]); @@ -1129,6 +1141,23 @@ casttest!(storage_layout_simple, |_prj, cmd| { "#]]); }); +// +casttest!(storage_layout_simple_json, |_prj, cmd| { + cmd.args([ + "storage", + "--rpc-url", + next_rpc_endpoint(NamedChain::Mainnet).as_str(), + "--block", + "21034138", + "--etherscan-api-key", + next_mainnet_etherscan_api_key().as_str(), + "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2", + "--json", + ]) + .assert_success() + .stdout_eq(file!["../fixtures/storage_layout_simple.json": Json]); +}); + // casttest!(storage_layout_complex, |_prj, cmd| { cmd.args([ @@ -1162,6 +1191,22 @@ casttest!(storage_layout_complex, |_prj, cmd| { "#]]); }); +casttest!(storage_layout_complex_json, |_prj, cmd| { + cmd.args([ + "storage", + "--rpc-url", + next_rpc_endpoint(NamedChain::Mainnet).as_str(), + "--block", + "21034138", + "--etherscan-api-key", + next_mainnet_etherscan_api_key().as_str(), + "0xBA12222222228d8Ba445958a75a0704d566BF2C8", + "--json", + ]) + .assert_success() + .stdout_eq(file!["../fixtures/storage_layout_complex.json": Json]); +}); + casttest!(balance, |_prj, cmd| { let rpc = next_http_rpc_endpoint(); let usdt = "0xdac17f958d2ee523a2206206994597c13d831ec7"; @@ -1509,9 +1554,55 @@ casttest!(fetch_constructor_args_from_etherscan, |_prj, cmd| { "#]]); }); -casttest!(cast_using_paymaster, async |prj, cmd| { - util::initialize(prj.root()); +// +casttest!(test_non_mainnet_traces, |prj, cmd| { + prj.clear(); + cmd.args([ + "run", + "0xa003e419e2d7502269eb5eda56947b580120e00abfd5b5460d08f8af44a0c24f", + "--rpc-url", + next_rpc_endpoint(NamedChain::Optimism).as_str(), + "--etherscan-api-key", + next_etherscan_api_key(NamedChain::Optimism).as_str(), + ]) + .assert_success() + .stdout_eq(str![[r#" +Executing previous transactions from the block. +Traces: + [33841] FiatTokenProxy::fallback(0x111111125421cA6dc452d289314280a0f8842A65, 164054805 [1.64e8]) + ├─ [26673] FiatTokenV2_2::approve(0x111111125421cA6dc452d289314280a0f8842A65, 164054805 [1.64e8]) [delegatecall] + │ ├─ emit Approval(owner: 0x9a95Af47C51562acfb2107F44d7967DF253197df, spender: 0x111111125421cA6dc452d289314280a0f8842A65, value: 164054805 [1.64e8]) + │ └─ ← [Return] true + └─ ← [Return] true +... + +"#]]); +}); +// tests that displays a sample contract artifact +// +casttest!(fetch_artifact_from_etherscan, |_prj, cmd| { + let eth_rpc_url = next_http_rpc_endpoint(); + cmd.args([ + "artifact", + "--etherscan-api-key", + &next_mainnet_etherscan_api_key(), + "0x0923cad07f06b2d0e5e49e63b8b35738d4156b95", + "--rpc-url", + eth_rpc_url.as_str(), + ]) + .assert_success() + .stdout_eq(str![[r#"{ + "abi": [], + "bytecode": { + "object": "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122074c61e8e4eefd410ca92eec26e8112ec6e831d0a4bf35718fdd78b45d68220d064736f6c63430008070033" + } +} + +"#]]); +}); + +casttest!(zk_cast_using_paymaster, async |_prj, cmd| { let node = ZkSyncNode::start(); let url = node.url(); @@ -1591,9 +1682,7 @@ casttest!(cast_using_paymaster, async |prj, cmd| { assert_eq!(balance_after, balance_before); }); -casttest!(cast_without_paymaster, async |prj, cmd| { - util::initialize(prj.root()); - +casttest!(zk_cast_without_paymaster, async |_prj, cmd| { let node = ZkSyncNode::start(); let url = node.url(); diff --git a/crates/cast/tests/fixtures/storage_layout_complex.json b/crates/cast/tests/fixtures/storage_layout_complex.json new file mode 100644 index 000000000..2cad9dc8c --- /dev/null +++ b/crates/cast/tests/fixtures/storage_layout_complex.json @@ -0,0 +1,397 @@ +{ + "storage": [ + { + "astId": 3805, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_status", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9499, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_generalPoolsBalances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_struct(IERC20ToBytes32Map)3177_storage)" + }, + { + "astId": 716, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_nextNonce", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 967, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_paused", + "offset": 0, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 8639, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_authorizer", + "offset": 1, + "slot": "3", + "type": "t_contract(IAuthorizer)11086" + }, + { + "astId": 8645, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_approvedRelayers", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 5769, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_isPoolRegistered", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 5771, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_nextPoolNonce", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 9915, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_minimalSwapInfoPoolsBalances", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_bytes32))" + }, + { + "astId": 9919, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_minimalSwapInfoPoolsTokens", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)3520_storage)" + }, + { + "astId": 10373, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_twoTokenPoolTokens", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_bytes32,t_struct(TwoTokenPoolTokens)10369_storage)" + }, + { + "astId": 4007, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_poolAssetManagers", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_address))" + }, + { + "astId": 8019, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_internalTokenBalance", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_address,t_mapping(t_contract(IERC20)3793,t_uint256))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32", + "base": "t_address" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IAuthorizer)11086": { + "encoding": "inplace", + "label": "contract IAuthorizer", + "numberOfBytes": "20" + }, + "t_contract(IERC20)3793": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_contract(IERC20)3793,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(contract IERC20 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_contract(IERC20)3793,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_address))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(contract IERC20 => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_contract(IERC20)3793,t_address)" + }, + "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_bytes32))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(contract IERC20 => bytes32))", + "numberOfBytes": "32", + "value": "t_mapping(t_contract(IERC20)3793,t_bytes32)" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)3520_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct EnumerableSet.AddressSet)", + "numberOfBytes": "32", + "value": "t_struct(AddressSet)3520_storage" + }, + "t_mapping(t_bytes32,t_struct(IERC20ToBytes32Map)3177_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct EnumerableMap.IERC20ToBytes32Map)", + "numberOfBytes": "32", + "value": "t_struct(IERC20ToBytes32Map)3177_storage" + }, + "t_mapping(t_bytes32,t_struct(TwoTokenPoolBalances)10360_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct TwoTokenPoolsBalance.TwoTokenPoolBalances)", + "numberOfBytes": "32", + "value": "t_struct(TwoTokenPoolBalances)10360_storage" + }, + "t_mapping(t_bytes32,t_struct(TwoTokenPoolTokens)10369_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct TwoTokenPoolsBalance.TwoTokenPoolTokens)", + "numberOfBytes": "32", + "value": "t_struct(TwoTokenPoolTokens)10369_storage" + }, + "t_mapping(t_contract(IERC20)3793,t_address)": { + "encoding": "mapping", + "key": "t_contract(IERC20)3793", + "label": "mapping(contract IERC20 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_contract(IERC20)3793,t_bytes32)": { + "encoding": "mapping", + "key": "t_contract(IERC20)3793", + "label": "mapping(contract IERC20 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_mapping(t_contract(IERC20)3793,t_uint256)": { + "encoding": "mapping", + "key": "t_contract(IERC20)3793", + "label": "mapping(contract IERC20 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_struct(IERC20ToBytes32MapEntry)3166_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct EnumerableMap.IERC20ToBytes32MapEntry)", + "numberOfBytes": "32", + "value": "t_struct(IERC20ToBytes32MapEntry)3166_storage" + }, + "t_struct(AddressSet)3520_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "numberOfBytes": "64", + "members": [ + { + "astId": 3515, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 3519, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + } + ] + }, + "t_struct(IERC20ToBytes32Map)3177_storage": { + "encoding": "inplace", + "label": "struct EnumerableMap.IERC20ToBytes32Map", + "numberOfBytes": "96", + "members": [ + { + "astId": 3168, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_length", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 3172, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_entries", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(IERC20ToBytes32MapEntry)3166_storage)" + }, + { + "astId": 3176, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_indexes", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_contract(IERC20)3793,t_uint256)" + } + ] + }, + "t_struct(IERC20ToBytes32MapEntry)3166_storage": { + "encoding": "inplace", + "label": "struct EnumerableMap.IERC20ToBytes32MapEntry", + "numberOfBytes": "64", + "members": [ + { + "astId": 3163, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_key", + "offset": 0, + "slot": "0", + "type": "t_contract(IERC20)3793" + }, + { + "astId": 3165, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_value", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ] + }, + "t_struct(TwoTokenPoolBalances)10360_storage": { + "encoding": "inplace", + "label": "struct TwoTokenPoolsBalance.TwoTokenPoolBalances", + "numberOfBytes": "64", + "members": [ + { + "astId": 10357, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "sharedCash", + "offset": 0, + "slot": "0", + "type": "t_bytes32" + }, + { + "astId": 10359, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "sharedManaged", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ] + }, + "t_struct(TwoTokenPoolTokens)10369_storage": { + "encoding": "inplace", + "label": "struct TwoTokenPoolsBalance.TwoTokenPoolTokens", + "numberOfBytes": "96", + "members": [ + { + "astId": 10362, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "tokenA", + "offset": 0, + "slot": "0", + "type": "t_contract(IERC20)3793" + }, + { + "astId": 10364, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "tokenB", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)3793" + }, + { + "astId": 10368, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "balances", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_struct(TwoTokenPoolBalances)10360_storage)" + } + ] + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + }, + "values": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000006048a8c631fb7e77eca533cf9c29784e482391e7", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000000000000000000000000000000000000000006e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] +} \ No newline at end of file diff --git a/crates/cast/tests/fixtures/storage_layout_simple.json b/crates/cast/tests/fixtures/storage_layout_simple.json new file mode 100644 index 000000000..35f4777d0 --- /dev/null +++ b/crates/cast/tests/fixtures/storage_layout_simple.json @@ -0,0 +1,36 @@ +{ + "storage": [ + { + "astId": 7, + "contract": "contracts/Create2Deployer.sol:Create2Deployer", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 122, + "contract": "contracts/Create2Deployer.sol:Create2Deployer", + "label": "_paused", + "offset": 20, + "slot": "0", + "type": "t_bool" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + } + }, + "values": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] +} \ No newline at end of file diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 6eb176d5b..fb7a5d612 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -573,6 +573,37 @@ "description": "Status of the transaction, retrieved from the transaction receipt." } ] + }, + { + "name": "SignedDelegation", + "description": "Holds a signed EIP-7702 authorization for an authority account to delegate to an implementation.", + "fields": [ + { + "name": "v", + "ty": "uint8", + "description": "The y-parity of the recovered secp256k1 signature (0 or 1)." + }, + { + "name": "r", + "ty": "bytes32", + "description": "First 32 bytes of the signature." + }, + { + "name": "s", + "ty": "bytes32", + "description": "Second 32 bytes of the signature." + }, + { + "name": "nonce", + "ty": "uint64", + "description": "The current nonce of the authority account at signing time.\n Used to ensure signature can't be replayed after account nonce changes." + }, + { + "name": "implementation", + "ty": "address", + "description": "Address of the contract implementation that will be delegated to.\n Gets encoded into delegation code: 0xef0100 || implementation." + } + ] } ], "cheatcodes": [ @@ -3076,6 +3107,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "attachDelegation", + "description": "Designate the next call as an EIP-7702 transaction", + "declaration": "function attachDelegation(SignedDelegation memory signedDelegation) external;", + "visibility": "external", + "mutability": "", + "signature": "attachDelegation((uint8,bytes32,bytes32,uint64,address))", + "selector": "0x14ae3519", + "selectorBytes": [ + 20, + 174, + 53, + 25 + ] + }, + "group": "scripting", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "blobBaseFee", @@ -4584,9 +4635,9 @@ "func": { "id": "exists", "description": "Returns true if the given path points to an existing entity, else returns false.", - "declaration": "function exists(string calldata path) external returns (bool result);", + "declaration": "function exists(string calldata path) external view returns (bool result);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "exists(string)", "selector": "0x261a323e", "selectorBytes": [ @@ -5304,9 +5355,9 @@ "func": { "id": "getBroadcast", "description": "Returns the most recent broadcast for the given contract on `chainId` matching `txType`.\nFor example:\nThe most recent deployment can be fetched by passing `txType` as `CREATE` or `CREATE2`.\nThe most recent call can be fetched by passing `txType` as `CALL`.", - "declaration": "function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory);", + "declaration": "function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary memory);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getBroadcast(string,uint64,uint8)", "selector": "0x3dc90cb3", "selectorBytes": [ @@ -5324,9 +5375,9 @@ "func": { "id": "getBroadcasts_0", "description": "Returns all broadcasts for the given contract on `chainId` with the specified `txType`.\nSorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.", - "declaration": "function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory);", + "declaration": "function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary[] memory);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getBroadcasts(string,uint64,uint8)", "selector": "0xf7afe919", "selectorBytes": [ @@ -5344,9 +5395,9 @@ "func": { "id": "getBroadcasts_1", "description": "Returns all broadcasts for the given contract on `chainId`.\nSorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.", - "declaration": "function getBroadcasts(string memory contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory);", + "declaration": "function getBroadcasts(string memory contractName, uint64 chainId) external view returns (BroadcastTxSummary[] memory);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getBroadcasts(string,uint64)", "selector": "0xf2fa4a26", "selectorBytes": [ @@ -5404,9 +5455,9 @@ "func": { "id": "getDeployment_0", "description": "Returns the most recent deployment for the current `chainId`.", - "declaration": "function getDeployment(string memory contractName) external returns (address deployedAddress);", + "declaration": "function getDeployment(string memory contractName) external view returns (address deployedAddress);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getDeployment(string)", "selector": "0xa8091d97", "selectorBytes": [ @@ -5424,9 +5475,9 @@ "func": { "id": "getDeployment_1", "description": "Returns the most recent deployment for the given contract on `chainId`", - "declaration": "function getDeployment(string memory contractName, uint64 chainId) external returns (address deployedAddress);", + "declaration": "function getDeployment(string memory contractName, uint64 chainId) external view returns (address deployedAddress);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getDeployment(string,uint64)", "selector": "0x0debd5d6", "selectorBytes": [ @@ -5444,9 +5495,9 @@ "func": { "id": "getDeployments", "description": "Returns all deployments for the given contract on `chainId`\nSorted in descending order of deployment time i.e descending order of BroadcastTxSummary.blockNumber.\nThe most recent deployment is the first element, and the oldest is the last.", - "declaration": "function getDeployments(string memory contractName, uint64 chainId) external returns (address[] memory deployedAddresses);", + "declaration": "function getDeployments(string memory contractName, uint64 chainId) external view returns (address[] memory deployedAddresses);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getDeployments(string,uint64)", "selector": "0x74e133dd", "selectorBytes": [ @@ -5684,9 +5735,9 @@ "func": { "id": "isDir", "description": "Returns true if the path exists on disk and is pointing at a directory, else returns false.", - "declaration": "function isDir(string calldata path) external returns (bool result);", + "declaration": "function isDir(string calldata path) external view returns (bool result);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "isDir(string)", "selector": "0x7d15d019", "selectorBytes": [ @@ -5704,9 +5755,9 @@ "func": { "id": "isFile", "description": "Returns true if the path exists on disk and is pointing at a regular file, else returns false.", - "declaration": "function isFile(string calldata path) external returns (bool result);", + "declaration": "function isFile(string calldata path) external view returns (bool result);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "isFile(string)", "selector": "0xe0eb04d4", "selectorBytes": [ @@ -6002,6 +6053,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "mockCallRevert_2", + "description": "Reverts a call to an address with specified revert data.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCallRevert(address,bytes4,bytes)", + "selector": "0x2dfba5df", + "selectorBytes": [ + 45, + 251, + 165, + 223 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "mockCallRevert_3", + "description": "Reverts a call to an address with a specific `msg.value`, with specified revert data.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCallRevert(address,uint256,bytes4,bytes)", + "selector": "0x596c8f04", + "selectorBytes": [ + 89, + 108, + 143, + 4 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "mockCall_0", @@ -6042,6 +6133,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "mockCall_2", + "description": "Mocks a call to an address, returning specified data.\nCalldata can either be strict or a partial match, e.g. if you only\npass a Solidity selector to the expected calldata, then the entire Solidity\nfunction will be mocked.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCall(address callee, bytes4 data, bytes calldata returnData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCall(address,bytes4,bytes)", + "selector": "0x08e0c537", + "selectorBytes": [ + 8, + 224, + 197, + 55 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "mockCall_3", + "description": "Mocks a call to an address with a specific `msg.value`, returning specified data.\nCalldata match takes precedence over `msg.value` in case of ambiguity.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCall(address,uint256,bytes4,bytes)", + "selector": "0xe7b36a3d", + "selectorBytes": [ + 231, + 179, + 106, + 61 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "mockCalls_0", @@ -7102,6 +7233,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "prank_2", + "description": "Sets the *next* delegate call's `msg.sender` to be the input address.", + "declaration": "function prank(address msgSender, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "prank(address,bool)", + "selector": "0xa7f8bf5c", + "selectorBytes": [ + 167, + 248, + 191, + 92 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "prank_3", + "description": "Sets the *next* delegate call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.", + "declaration": "function prank(address msgSender, address txOrigin, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "prank(address,address,bool)", + "selector": "0x7d73d042", + "selectorBytes": [ + 125, + 115, + 208, + 66 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "prevrandao_0", @@ -8686,6 +8857,26 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "signAndAttachDelegation", + "description": "Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction", + "declaration": "function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation);", + "visibility": "external", + "mutability": "", + "signature": "signAndAttachDelegation(address,uint256)", + "selector": "0xc7fa7288", + "selectorBytes": [ + 199, + 250, + 114, + 136 + ] + }, + "group": "scripting", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "signCompact_0", @@ -8766,6 +8957,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "signDelegation", + "description": "Sign an EIP-7702 authorization for delegation", + "declaration": "function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation);", + "visibility": "external", + "mutability": "", + "signature": "signDelegation(address,uint256)", + "selector": "0x5b593c7b", + "selectorBytes": [ + 91, + 89, + 60, + 123 + ] + }, + "group": "scripting", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "signP256", @@ -9208,6 +9419,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "startPrank_2", + "description": "Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called.", + "declaration": "function startPrank(address msgSender, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "startPrank(address,bool)", + "selector": "0x1cc0b435", + "selectorBytes": [ + 28, + 192, + 180, + 53 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "startPrank_3", + "description": "Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.", + "declaration": "function startPrank(address msgSender, address txOrigin, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "startPrank(address,address,bool)", + "selector": "0x4eb859b5", + "selectorBytes": [ + 78, + 184, + 89, + 181 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "startSnapshotGas_0", @@ -9812,9 +10063,9 @@ "func": { "id": "unixTime", "description": "Returns the time since unix epoch in milliseconds.", - "declaration": "function unixTime() external returns (uint256 milliseconds);", + "declaration": "function unixTime() external view returns (uint256 milliseconds);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "unixTime()", "selector": "0x625387dc", "selectorBytes": [ diff --git a/crates/cheatcodes/spec/src/lib.rs b/crates/cheatcodes/spec/src/lib.rs index eae2ae0ee..c4d7e9868 100644 --- a/crates/cheatcodes/spec/src/lib.rs +++ b/crates/cheatcodes/spec/src/lib.rs @@ -87,6 +87,7 @@ impl Cheatcodes<'static> { Vm::Gas::STRUCT.clone(), Vm::DebugStep::STRUCT.clone(), Vm::BroadcastTxSummary::STRUCT.clone(), + Vm::SignedDelegation::STRUCT.clone(), ]), enums: Cow::Owned(vec![ Vm::CallerMode::ENUM.clone(), @@ -103,6 +104,7 @@ impl Cheatcodes<'static> { } #[cfg(test)] +#[allow(clippy::disallowed_macros)] mod tests { use super::*; use std::{fs, path::Path}; diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index f1e0db3a0..cc3f91387 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -308,6 +308,22 @@ interface Vm { bool success; } + /// Holds a signed EIP-7702 authorization for an authority account to delegate to an implementation. + struct SignedDelegation { + /// The y-parity of the recovered secp256k1 signature (0 or 1). + uint8 v; + /// First 32 bytes of the signature. + bytes32 r; + /// Second 32 bytes of the signature. + bytes32 s; + /// The current nonce of the authority account at signing time. + /// Used to ensure signature can't be replayed after account nonce changes. + uint64 nonce; + /// Address of the contract implementation that will be delegated to. + /// Gets encoded into delegation code: 0xef0100 || implementation. + address implementation; + } + // ======== EVM ======== /// Gets the address for a given private key. @@ -527,6 +543,22 @@ interface Vm { #[cheatcode(group = Evm, safety = Unsafe)] function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + /// Mocks a call to an address, returning specified data. + /// Calldata can either be strict or a partial match, e.g. if you only + /// pass a Solidity selector to the expected calldata, then the entire Solidity + /// function will be mocked. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCall(address callee, bytes4 data, bytes calldata returnData) external; + + /// Mocks a call to an address with a specific `msg.value`, returning specified data. + /// Calldata match takes precedence over `msg.value` in case of ambiguity. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external; + /// Mocks multiple calls to an address, returning specified data for each call. #[cheatcode(group = Evm, safety = Unsafe)] function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external; @@ -544,6 +576,19 @@ interface Vm { function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) external; + /// Reverts a call to an address with specified revert data. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external; + + /// Reverts a call to an address with a specific `msg.value`, with specified revert data. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) + external; + /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls /// `target` with the same calldata. This functionality is similar to a delegate call made to /// `target` contract from `callee`. @@ -571,6 +616,22 @@ interface Vm { #[cheatcode(group = Evm, safety = Unsafe)] function startPrank(address msgSender, address txOrigin) external; + /// Sets the *next* delegate call's `msg.sender` to be the input address. + #[cheatcode(group = Evm, safety = Unsafe)] + function prank(address msgSender, bool delegateCall) external; + + /// Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called. + #[cheatcode(group = Evm, safety = Unsafe)] + function startPrank(address msgSender, bool delegateCall) external; + + /// Sets the *next* delegate call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. + #[cheatcode(group = Evm, safety = Unsafe)] + function prank(address msgSender, address txOrigin, bool delegateCall) external; + + /// Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. + #[cheatcode(group = Evm, safety = Unsafe)] + function startPrank(address msgSender, address txOrigin, bool delegateCall) external; + /// Resets subsequent calls' `msg.sender` to be `address(this)`. #[cheatcode(group = Evm, safety = Unsafe)] function stopPrank() external; @@ -1575,7 +1636,7 @@ interface Vm { /// Returns true if the given path points to an existing entity, else returns false. #[cheatcode(group = Filesystem)] - function exists(string calldata path) external returns (bool result); + function exists(string calldata path) external view returns (bool result); /// Given a path, query the file system to get information about a file, directory, etc. #[cheatcode(group = Filesystem)] @@ -1583,11 +1644,11 @@ interface Vm { /// Returns true if the path exists on disk and is pointing at a directory, else returns false. #[cheatcode(group = Filesystem)] - function isDir(string calldata path) external returns (bool result); + function isDir(string calldata path) external view returns (bool result); /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. #[cheatcode(group = Filesystem)] - function isFile(string calldata path) external returns (bool result); + function isFile(string calldata path) external view returns (bool result); /// Get the path of the current project root. #[cheatcode(group = Filesystem)] @@ -1595,7 +1656,7 @@ interface Vm { /// Returns the time since unix epoch in milliseconds. #[cheatcode(group = Filesystem)] - function unixTime() external returns (uint256 milliseconds); + function unixTime() external view returns (uint256 milliseconds); // -------- Reading and writing -------- @@ -1725,27 +1786,27 @@ interface Vm { /// /// The most recent call can be fetched by passing `txType` as `CALL`. #[cheatcode(group = Filesystem)] - function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory); + function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary memory); /// Returns all broadcasts for the given contract on `chainId` with the specified `txType`. /// /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber. #[cheatcode(group = Filesystem)] - function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory); + function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary[] memory); /// Returns all broadcasts for the given contract on `chainId`. /// /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber. #[cheatcode(group = Filesystem)] - function getBroadcasts(string memory contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory); + function getBroadcasts(string memory contractName, uint64 chainId) external view returns (BroadcastTxSummary[] memory); /// Returns the most recent deployment for the current `chainId`. #[cheatcode(group = Filesystem)] - function getDeployment(string memory contractName) external returns (address deployedAddress); + function getDeployment(string memory contractName) external view returns (address deployedAddress); /// Returns the most recent deployment for the given contract on `chainId` #[cheatcode(group = Filesystem)] - function getDeployment(string memory contractName, uint64 chainId) external returns (address deployedAddress); + function getDeployment(string memory contractName, uint64 chainId) external view returns (address deployedAddress); /// Returns all deployments for the given contract on `chainId` /// @@ -1753,7 +1814,7 @@ interface Vm { /// /// The most recent deployment is the first element, and the oldest is the last. #[cheatcode(group = Filesystem)] - function getDeployments(string memory contractName, uint64 chainId) external returns (address[] memory deployedAddresses); + function getDeployments(string memory contractName, uint64 chainId) external view returns (address[] memory deployedAddresses); // -------- Foreign Function Interface -------- @@ -1995,6 +2056,18 @@ interface Vm { #[cheatcode(group = Scripting)] function broadcastRawTransaction(bytes calldata data) external; + /// Sign an EIP-7702 authorization for delegation + #[cheatcode(group = Scripting)] + function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); + + /// Designate the next call as an EIP-7702 transaction + #[cheatcode(group = Scripting)] + function attachDelegation(SignedDelegation memory signedDelegation) external; + + /// Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction + #[cheatcode(group = Scripting)] + function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); + /// Returns addresses of available unlocked wallets in the script environment. #[cheatcode(group = Scripting)] function getWallets() external returns (address[] memory wallets); diff --git a/crates/cheatcodes/src/crypto.rs b/crates/cheatcodes/src/crypto.rs index cdb07720c..3fd13d9b0 100644 --- a/crates/cheatcodes/src/crypto.rs +++ b/crates/cheatcodes/src/crypto.rs @@ -15,7 +15,9 @@ use k256::{ ecdsa::SigningKey, elliptic_curve::{bigint::ArrayEncoding, sec1::ToEncodedPoint}, }; -use p256::ecdsa::{signature::hazmat::PrehashSigner, Signature, SigningKey as P256SigningKey}; +use p256::ecdsa::{ + signature::hazmat::PrehashSigner, Signature as P256Signature, SigningKey as P256SigningKey, +}; /// The BIP32 default derivation path prefix. const DEFAULT_DERIVATION_PATH_PREFIX: &str = "m/44'/60'/0'/0/"; @@ -215,23 +217,23 @@ fn create_wallet(private_key: &U256, label: Option<&str>, state: &mut Cheatcodes .abi_encode()) } -fn encode_full_sig(sig: alloy_primitives::Signature) -> Vec { +fn encode_full_sig(sig: alloy_primitives::PrimitiveSignature) -> Vec { // Retrieve v, r and s from signature. - let v = U256::from(sig.v().y_parity_byte_non_eip155().unwrap_or(sig.v().y_parity_byte())); + let v = U256::from(sig.v() as u64 + 27); let r = B256::from(sig.r()); let s = B256::from(sig.s()); (v, r, s).abi_encode() } -fn encode_compact_sig(sig: alloy_primitives::Signature) -> Vec { +fn encode_compact_sig(sig: alloy_primitives::PrimitiveSignature) -> Vec { // Implement EIP-2098 compact signature. let r = B256::from(sig.r()); let mut vs = sig.s(); - vs.set_bit(255, sig.v().y_parity()); + vs.set_bit(255, sig.v()); (r, vs).abi_encode() } -fn sign(private_key: &U256, digest: &B256) -> Result { +fn sign(private_key: &U256, digest: &B256) -> Result { // The `ecrecover` precompile does not use EIP-155. No chain ID is needed. let wallet = parse_wallet(private_key)?; let sig = wallet.sign_hash_sync(digest)?; @@ -243,7 +245,7 @@ fn sign_with_wallet( state: &mut Cheatcodes, signer: Option
, digest: &B256, -) -> Result { +) -> Result { if state.wallets().is_empty() { bail!("no wallets available"); } @@ -273,7 +275,7 @@ fn sign_with_wallet( fn sign_p256(private_key: &U256, digest: &B256) -> Result { let signing_key = parse_private_key_p256(private_key)?; - let signature: Signature = signing_key.sign_prehash(digest.as_slice())?; + let signature: P256Signature = signing_key.sign_prehash(digest.as_slice())?; let r_bytes: [u8; 32] = signature.r().to_bytes().into(); let s_bytes: [u8; 32] = signature.s().to_bytes().into(); @@ -403,7 +405,7 @@ mod tests { let result = sign_p256(&pk_u256, &digest).unwrap(); let result_bytes: [u8; 64] = result.try_into().unwrap(); - let signature = Signature::from_bytes(&result_bytes.into()).unwrap(); + let signature = P256Signature::from_bytes(&result_bytes.into()).unwrap(); let verifying_key = VerifyingKey::from(&signing_key); assert!(verifying_key.verify_prehash(digest.as_slice(), &signature).is_ok()); } diff --git a/crates/cheatcodes/src/evm/mock.rs b/crates/cheatcodes/src/evm/mock.rs index f08d43b8d..aed6b1a56 100644 --- a/crates/cheatcodes/src/evm/mock.rs +++ b/crates/cheatcodes/src/evm/mock.rs @@ -35,6 +35,39 @@ impl Cheatcode for mockCall_1Call { } } +impl Cheatcode for mockCall_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, data, returnData } = self; + let _ = make_acc_non_empty(callee, ccx.ecx)?; + + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + None, + returnData, + InstructionResult::Return, + ); + Ok(Default::default()) + } +} + +impl Cheatcode for mockCall_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, msgValue, data, returnData } = self; + ccx.ecx.load_account(*callee)?; + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + Some(msgValue), + returnData, + InstructionResult::Return, + ); + Ok(Default::default()) + } +} + impl Cheatcode for mockCalls_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, returnData } = self; @@ -78,6 +111,40 @@ impl Cheatcode for mockCallRevert_1Call { } } +impl Cheatcode for mockCallRevert_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, data, revertData } = self; + let _ = make_acc_non_empty(callee, ccx.ecx)?; + + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + None, + revertData, + InstructionResult::Revert, + ); + Ok(Default::default()) + } +} + +impl Cheatcode for mockCallRevert_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, msgValue, data, revertData } = self; + let _ = make_acc_non_empty(callee, ccx.ecx)?; + + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + Some(msgValue), + revertData, + InstructionResult::Revert, + ); + Ok(Default::default()) + } +} + impl Cheatcode for mockFunctionCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { callee, target, data } = self; diff --git a/crates/cheatcodes/src/evm/prank.rs b/crates/cheatcodes/src/evm/prank.rs index a310e28e5..1d7ca5a07 100644 --- a/crates/cheatcodes/src/evm/prank.rs +++ b/crates/cheatcodes/src/evm/prank.rs @@ -16,6 +16,8 @@ pub struct Prank { pub depth: u64, /// Whether the prank stops by itself after the next call pub single_call: bool, + /// Whether the prank should be be applied to delegate call + pub delegate_call: bool, /// Whether the prank has been used yet (false if unused) pub used: bool, } @@ -29,8 +31,18 @@ impl Prank { new_origin: Option
, depth: u64, single_call: bool, + delegate_call: bool, ) -> Self { - Self { prank_caller, prank_origin, new_caller, new_origin, depth, single_call, used: false } + Self { + prank_caller, + prank_origin, + new_caller, + new_origin, + depth, + single_call, + delegate_call, + used: false, + } } /// Apply the prank by setting `used` to true iff it is false @@ -47,28 +59,56 @@ impl Prank { impl Cheatcode for prank_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender } = self; - prank(ccx, msgSender, None, true) + prank(ccx, msgSender, None, true, false) } } impl Cheatcode for startPrank_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender } = self; - prank(ccx, msgSender, None, false) + prank(ccx, msgSender, None, false, false) } } impl Cheatcode for prank_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender, txOrigin } = self; - prank(ccx, msgSender, Some(txOrigin), true) + prank(ccx, msgSender, Some(txOrigin), true, false) } } impl Cheatcode for startPrank_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender, txOrigin } = self; - prank(ccx, msgSender, Some(txOrigin), false) + prank(ccx, msgSender, Some(txOrigin), false, false) + } +} + +impl Cheatcode for prank_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, delegateCall } = self; + prank(ccx, msgSender, None, true, *delegateCall) + } +} + +impl Cheatcode for startPrank_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, delegateCall } = self; + prank(ccx, msgSender, None, false, *delegateCall) + } +} + +impl Cheatcode for prank_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, txOrigin, delegateCall } = self; + prank(ccx, msgSender, Some(txOrigin), true, *delegateCall) + } +} + +impl Cheatcode for startPrank_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, txOrigin, delegateCall } = self; + prank(ccx, msgSender, Some(txOrigin), false, *delegateCall) } } @@ -85,6 +125,7 @@ fn prank( new_caller: &Address, new_origin: Option<&Address>, single_call: bool, + delegate_call: bool, ) -> Result { let prank = Prank::new( ccx.caller, @@ -93,8 +134,15 @@ fn prank( new_origin.copied(), ccx.ecx.journaled_state.depth(), single_call, + delegate_call, ); + // Ensure that code exists at `msg.sender` if delegate calling. + if delegate_call { + let code = ccx.code(*new_caller)?; + ensure!(!code.is_empty(), "cannot `prank` delegate call from an EOA"); + } + if let Some(Prank { used, single_call: current_single_call, .. }) = ccx.state.prank { ensure!(used, "cannot overwrite a prank until it is applied at least once"); // This case can only fail if the user calls `vm.startPrank` and then `vm.prank` later on. diff --git a/crates/cheatcodes/src/fs.rs b/crates/cheatcodes/src/fs.rs index a2a4b69a5..6325b71be 100644 --- a/crates/cheatcodes/src/fs.rs +++ b/crates/cheatcodes/src/fs.rs @@ -631,11 +631,11 @@ fn prompt( match rx.recv_timeout(timeout) { Ok(res) => res.map_err(|err| { - println!(); + let _ = sh_println!(); err.to_string().into() }), Err(_) => { - println!(); + let _ = sh_eprintln!(); Err("Prompt timed out".into()) } } diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index f52d4fcee..467456ec7 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -55,13 +55,14 @@ use proptest::test_runner::{RngAlgorithm, TestRng, TestRunner}; use rand::Rng; use revm::{ interpreter::{ - opcode as op, CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, + opcode as op, CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, EOFCreateInputs, EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, }, primitives::{ AccountInfo, BlockEnv, Bytecode, CreateScheme, EVMError, Env, EvmStorageSlot, - ExecutionResult, HashMap as rHashMap, Output, SpecId, EOF_MAGIC_BYTES, KECCAK_EMPTY, + ExecutionResult, HashMap as rHashMap, Output, SignedAuthorization, SpecId, EOF_MAGIC_BYTES, + KECCAK_EMPTY, }, EvmContext, InnerEvmContext, Inspector, }; @@ -502,6 +503,11 @@ pub struct Cheatcodes { /// execution block environment. pub block: Option, + /// Currently active EIP-7702 delegation that will be consumed when building the next + /// transaction. Set by `vm.attachDelegation()` and consumed via `.take()` during + /// transaction construction. + pub active_delegation: Option, + /// The gas price. /// /// Used in the cheatcode handler to overwrite the gas price separately from the gas price @@ -702,9 +708,8 @@ impl Cheatcodes { fs_commit: true, labels: config.labels.clone(), config, - dual_compiled_contracts, - zk_startup_migration, block: Default::default(), + active_delegation: Default::default(), gas_price: Default::default(), prank: Default::default(), expected_revert: Default::default(), @@ -734,10 +739,13 @@ impl Cheatcodes { arbitrary_storage: Default::default(), deprecated: Default::default(), wallets: Default::default(), + dual_compiled_contracts, + zk_startup_migration, use_zk_vm: Default::default(), skip_zk_vm: Default::default(), skip_zk_vm_addresses: Default::default(), record_next_create_address: Default::default(), + //TODO(zk): use initialized above persisted_factory_deps: Default::default(), paymaster_params: None, zk_use_factory_deps: Default::default(), @@ -1546,15 +1554,14 @@ where { call: &mut CallInputs, executor: &mut impl CheatcodesExecutor, ) -> Option { - let ecx_inner = &mut ecx.inner; let gas = Gas::new(call.gas_limit); // At the root call to test function or script `run()`/`setUp()` functions, we are // decreasing sender nonce to ensure that it matches on-chain nonce once we start // broadcasting. - if ecx_inner.journaled_state.depth == 0 { - let sender = ecx_inner.env.tx.caller; - let account = match super::evm::journaled_account(ecx_inner, sender) { + if ecx.journaled_state.depth == 0 { + let sender = ecx.env.tx.caller; + let account = match super::evm::journaled_account(ecx, sender) { Ok(account) => account, Err(err) => { return Some(CallOutcome { @@ -1572,7 +1579,7 @@ where { account.info.nonce = nonce; if self.use_zk_vm { // NOTE(zk): We sync with the nonce changes to ensure that the nonce matches - foundry_zksync_core::cheatcodes::set_nonce(sender, U256::from(nonce), ecx_inner); + foundry_zksync_core::cheatcodes::set_nonce(sender, U256::from(nonce), ecx); } trace!(target: "cheatcodes", %sender, nonce, prev, "corrected nonce"); @@ -1599,6 +1606,10 @@ where { }; } + // NOTE(zk): renamed from `ecx` because we need the full one later + // and this helps with borrow checker + let ecx_inner = &mut ecx.inner; + if call.target_address == HARDHAT_CONSOLE_ADDRESS { return None; } @@ -1691,6 +1702,20 @@ where { // Apply our prank if let Some(prank) = &self.prank { + // Apply delegate call, `call.caller`` will not equal `prank.prank_caller` + // TODO(zk): support delegatecall prank + if let CallScheme::DelegateCall | CallScheme::ExtDelegateCall = call.scheme { + if prank.delegate_call { + call.target_address = prank.new_caller; + call.caller = prank.new_caller; + let acc = ecx_inner.journaled_state.account(prank.new_caller); + call.value = CallValue::Apparent(acc.info.balance); + if let Some(new_origin) = prank.new_origin { + ecx_inner.env.tx.caller = new_origin; + } + } + } + if ecx_inner.journaled_state.depth() >= prank.depth && call.caller == prank.prank_caller { let mut prank_applied = false; @@ -1796,18 +1821,26 @@ where { None }; + let mut tx_req = TransactionRequest { + from: Some(broadcast.new_origin), + to: Some(TxKind::from(Some(call.target_address))), + value: call.transfer_value(), + input: TransactionInput::new(call.input.clone()), + nonce: Some(nonce), + chain_id: Some(ecx_inner.env.cfg.chain_id), + gas: if is_fixed_gas_limit { Some(call.gas_limit) } else { None }, + ..Default::default() + }; + + if let Some(auth_list) = self.active_delegation.take() { + tx_req.authorization_list = Some(vec![auth_list]); + } else { + tx_req.authorization_list = None; + } + self.broadcastable_transactions.push_back(BroadcastableTransaction { rpc: ecx_inner.db.active_fork_url(), - transaction: TransactionRequest { - from: Some(broadcast.new_origin), - to: Some(TxKind::from(Some(call.target_address))), - value: call.transfer_value(), - input: TransactionInput::new(call.input.clone()), - nonce: Some(nonce), - gas: if is_fixed_gas_limit { Some(call.gas_limit) } else { None }, - ..Default::default() - } - .into(), + transaction: tx_req.into(), zk_tx, }); debug!(target: "cheatcodes", tx=?self.broadcastable_transactions.back().unwrap(), "broadcastable call"); @@ -1839,7 +1872,7 @@ where { // nonce, a non-zero KECCAK_EMPTY codehash, or non-empty code let initialized; let old_balance; - if let Ok(acc) = ecx.load_account(call.target_address) { + if let Ok(acc) = ecx_inner.load_account(call.target_address) { initialized = acc.info.exists(); old_balance = acc.info.balance; } else { @@ -1862,8 +1895,8 @@ where { // as "warm" if the call from which they were accessed is reverted recorded_account_diffs_stack.push(vec![AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.db.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.env.cfg.chain_id), + forkId: ecx_inner.db.active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx_inner.env.cfg.chain_id), }, accessor: call.caller, account: call.bytecode_address, @@ -1876,7 +1909,7 @@ where { reverted: false, deployedCode: Bytes::new(), storageAccesses: vec![], // updated on step - depth: ecx.journaled_state.depth(), + depth: ecx_inner.journaled_state.depth(), }]); } diff --git a/crates/cheatcodes/src/json.rs b/crates/cheatcodes/src/json.rs index 0908f247c..6ad36e474 100644 --- a/crates/cheatcodes/src/json.rs +++ b/crates/cheatcodes/src/json.rs @@ -682,7 +682,7 @@ mod tests { match value { DynSolValue::Tuple(_) | DynSolValue::CustomStruct { .. } => true, DynSolValue::Array(v) | DynSolValue::FixedArray(v) => { - v.first().map_or(false, contains_tuple) + v.first().is_some_and(contains_tuple) } _ => false, } diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index a5cc5da5b..9d7442bef 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -6,8 +6,12 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![allow(elided_lifetimes_in_paths)] // Cheats context uses 3 lifetimes +#[macro_use] +extern crate foundry_common; + #[macro_use] pub extern crate foundry_cheatcodes_spec as spec; + #[macro_use] extern crate tracing; diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index 29a804efd..b28141ae0 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -1,11 +1,14 @@ //! Implementations of [`Scripting`](spec::Group::Scripting) cheatcodes. use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; -use alloy_primitives::{Address, B256, U256}; +use alloy_primitives::{Address, PrimitiveSignature, B256, U256}; +use alloy_rpc_types::Authorization; +use alloy_signer::SignerSync; use alloy_signer_local::PrivateKeySigner; use alloy_sol_types::SolValue; use foundry_wallets::{multi_wallet::MultiWallet, WalletSigner}; use parking_lot::Mutex; +use revm::primitives::{Bytecode, SignedAuthorization}; use std::sync::Arc; impl Cheatcode for broadcast_0Call { @@ -29,6 +32,96 @@ impl Cheatcode for broadcast_2Call { } } +impl Cheatcode for attachDelegationCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { signedDelegation } = self; + let SignedDelegation { v, r, s, nonce, implementation } = signedDelegation; + + let auth = Authorization { + address: *implementation, + nonce: *nonce, + chain_id: ccx.ecx.env.cfg.chain_id, + }; + let signed_auth = SignedAuthorization::new_unchecked( + auth, + *v, + U256::from_be_bytes(r.0), + U256::from_be_bytes(s.0), + ); + write_delegation(ccx, signed_auth.clone())?; + ccx.state.active_delegation = Some(signed_auth); + Ok(Default::default()) + } +} + +impl Cheatcode for signDelegationCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { implementation, privateKey } = self; + let signer = PrivateKeySigner::from_bytes(&B256::from(*privateKey))?; + let authority = signer.address(); + let (auth, nonce) = create_auth(ccx, *implementation, authority)?; + let sig = signer.sign_hash_sync(&auth.signature_hash())?; + Ok(sig_to_delegation(sig, nonce, *implementation).abi_encode()) + } +} + +impl Cheatcode for signAndAttachDelegationCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { implementation, privateKey } = self; + let signer = PrivateKeySigner::from_bytes(&B256::from(*privateKey))?; + let authority = signer.address(); + let (auth, nonce) = create_auth(ccx, *implementation, authority)?; + let sig = signer.sign_hash_sync(&auth.signature_hash())?; + let signed_auth = sig_to_auth(sig, auth); + write_delegation(ccx, signed_auth.clone())?; + ccx.state.active_delegation = Some(signed_auth); + Ok(sig_to_delegation(sig, nonce, *implementation).abi_encode()) + } +} + +fn create_auth( + ccx: &mut CheatsCtxt, + implementation: Address, + authority: Address, +) -> Result<(Authorization, u64)> { + let authority_acc = ccx.ecx.journaled_state.load_account(authority, &mut ccx.ecx.db)?; + let nonce = authority_acc.data.info.nonce; + Ok(( + Authorization { address: implementation, nonce, chain_id: ccx.ecx.env.cfg.chain_id }, + nonce, + )) +} + +fn write_delegation(ccx: &mut CheatsCtxt, auth: SignedAuthorization) -> Result<()> { + let authority = auth.recover_authority().map_err(|e| format!("{e}"))?; + let authority_acc = ccx.ecx.journaled_state.load_account(authority, &mut ccx.ecx.db)?; + if authority_acc.data.info.nonce != auth.nonce { + return Err("invalid nonce".into()); + } + authority_acc.data.info.nonce += 1; + let bytecode = Bytecode::new_eip7702(*auth.address()); + ccx.ecx.journaled_state.set_code(authority, bytecode); + Ok(()) +} + +fn sig_to_delegation( + sig: PrimitiveSignature, + nonce: u64, + implementation: Address, +) -> SignedDelegation { + SignedDelegation { + v: sig.v() as u8, + r: sig.r().into(), + s: sig.s().into(), + nonce, + implementation, + } +} + +fn sig_to_auth(sig: PrimitiveSignature, auth: Authorization) -> SignedAuthorization { + SignedAuthorization::new_unchecked(auth, sig.v() as u8, sig.r(), sig.s()) +} + impl Cheatcode for startBroadcast_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; diff --git a/crates/cheatcodes/src/test/expect.rs b/crates/cheatcodes/src/test/expect.rs index 2b7ecb62c..94afe820d 100644 --- a/crates/cheatcodes/src/test/expect.rs +++ b/crates/cheatcodes/src/test/expect.rs @@ -595,7 +595,7 @@ pub(crate) fn handle_expect_emit( return false } // Maybe match source address. - if event_to_fill_or_check.address.map_or(false, |addr| addr != log.address) { + if event_to_fill_or_check.address.is_some_and(|addr| addr != log.address) { return false; } // Maybe match data. diff --git a/crates/chisel/bin/main.rs b/crates/chisel/bin/main.rs index dca99d4a5..acc2c6f17 100644 --- a/crates/chisel/bin/main.rs +++ b/crates/chisel/bin/main.rs @@ -11,7 +11,7 @@ use clap::{Parser, Subcommand}; use eyre::Context; use foundry_cli::{ handler, - opts::{CoreBuildArgs, ShellOpts}, + opts::{CoreBuildArgs, GlobalOpts}, utils::{self, LoadConfig}, }; use foundry_common::{evm::EvmArgs, fs}; @@ -50,12 +50,13 @@ const VERSION_MESSAGE: &str = concat!( #[derive(Debug, Parser)] #[command(name = "chisel", version = VERSION_MESSAGE)] pub struct Chisel { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(subcommand)] pub cmd: Option, - #[clap(flatten)] - pub shell: ShellOpts, - /// Path to a directory containing Solidity files to import, or path to a single Solidity file. /// /// These files will be evaluated before the top-level of the @@ -117,8 +118,9 @@ fn run() -> eyre::Result<()> { handler::install(); utils::subscriber(); utils::load_dotenv(); + let args = Chisel::parse(); - args.shell.shell().set(); + args.global.init()?; main_args(args) } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 89af3647f..ee1fc4c09 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -38,7 +38,9 @@ dotenvy = "0.15" eyre.workspace = true futures.workspace = true indicatif = "0.17" +rayon.workspace = true regex = { workspace = true, default-features = false } +serde_json.workspace = true serde.workspace = true strsim = "0.11" strum = { workspace = true, features = ["derive"] } @@ -46,7 +48,6 @@ tokio = { workspace = true, features = ["macros"] } tracing-subscriber = { workspace = true, features = ["registry", "env-filter"] } tracing.workspace = true yansi.workspace = true -serde_json.workspace = true tracing-tracy = { version = "0.11", optional = true } diff --git a/crates/cli/src/handler.rs b/crates/cli/src/handler.rs index b2fbb49d4..ed32fa16b 100644 --- a/crates/cli/src/handler.rs +++ b/crates/cli/src/handler.rs @@ -1,21 +1,16 @@ use eyre::EyreHandler; -use std::error::Error; -use yansi::Paint; +use std::{error::Error, fmt}; /// A custom context type for Foundry specific error reporting via `eyre` #[derive(Debug)] pub struct Handler; impl EyreHandler for Handler { - fn debug( - &self, - error: &(dyn Error + 'static), - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { + fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { - return core::fmt::Debug::fmt(error, f) + return fmt::Debug::fmt(error, f) } - write!(f, "{}", error.red())?; + write!(f, "{error}")?; if let Some(cause) = error.source() { write!(f, "\n\nContext:")?; @@ -37,7 +32,7 @@ impl EyreHandler for Handler { } } -/// Installs the Foundry eyre hook as the global error report hook. +/// Installs the Foundry [eyre] and [panic](mod@std::panic) hooks as the global ones. /// /// # Details /// @@ -51,19 +46,17 @@ pub fn install() { std::env::set_var("RUST_BACKTRACE", "1"); } - if std::env::var_os("FOUNDRY_DEBUG").is_some() { - if let Err(e) = color_eyre::install() { - debug!("failed to install color eyre error hook: {e}"); - } + let panic_section = + "This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry"; + let (panic_hook, debug_eyre_hook) = + color_eyre::config::HookBuilder::default().panic_section(panic_section).into_hooks(); + panic_hook.install(); + let eyre_install_result = if std::env::var_os("FOUNDRY_DEBUG").is_some() { + debug_eyre_hook.install() } else { - let (panic_hook, _) = color_eyre::config::HookBuilder::default() - .panic_section( - "This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry", - ) - .into_hooks(); - panic_hook.install(); - if let Err(e) = eyre::set_hook(Box::new(move |_| Box::new(Handler))) { - debug!("failed to install eyre error hook: {e}"); - } + eyre::set_hook(Box::new(|_| Box::new(Handler))) + }; + if let Err(e) = eyre_install_result { + debug!("failed to install eyre error hook: {e}"); } } diff --git a/crates/cli/src/opts/build/core.rs b/crates/cli/src/opts/build/core.rs index 23f752290..55e4bb2f3 100644 --- a/crates/cli/src/opts/build/core.rs +++ b/crates/cli/src/opts/build/core.rs @@ -181,7 +181,8 @@ impl<'a> From<&'a CoreBuildArgs> for Figment { }; // remappings should stack - let mut remappings = Remappings::new_with_remappings(args.project_paths.get_remappings()); + let mut remappings = Remappings::new_with_remappings(args.project_paths.get_remappings()) + .with_figment(&figment); remappings .extend(figment.extract_inner::>("remappings").unwrap_or_default()); // override only set values from the CLI for zksync diff --git a/crates/cli/src/opts/global.rs b/crates/cli/src/opts/global.rs new file mode 100644 index 000000000..ad715f241 --- /dev/null +++ b/crates/cli/src/opts/global.rs @@ -0,0 +1,81 @@ +use clap::{ArgAction, Parser}; +use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity}; +use serde::{Deserialize, Serialize}; + +/// Global options. +#[derive(Clone, Debug, Default, Serialize, Deserialize, Parser)] +pub struct GlobalOpts { + /// Verbosity level of the log messages. + /// + /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + /// + /// Depending on the context the verbosity levels have different meanings. + /// + /// For example, the verbosity levels of the EVM are: + /// - 2 (-vv): Print logs for all tests. + /// - 3 (-vvv): Print execution traces for failing tests. + /// - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + /// - 5 (-vvvvv): Print execution and setup traces for all tests. + #[arg(help_heading = "Display options", global = true, short, long, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count)] + verbosity: Verbosity, + + /// Do not print log messages. + #[arg(help_heading = "Display options", global = true, short, long, alias = "silent")] + quiet: bool, + + /// Format log messages as JSON. + #[arg(help_heading = "Display options", global = true, long, alias = "format-json", conflicts_with_all = &["quiet", "color"])] + json: bool, + + /// The color of the log messages. + #[arg(help_heading = "Display options", global = true, long, value_enum)] + color: Option, + + /// Number of threads to use. Specifying 0 defaults to the number of logical cores. + #[arg(global = true, long, short = 'j', visible_alias = "jobs")] + threads: Option, +} + +impl GlobalOpts { + /// Initialize the global options. + pub fn init(&self) -> eyre::Result<()> { + // Set the global shell. + self.shell().set(); + + // Initialize the thread pool only if `threads` was requested to avoid unnecessary overhead. + if self.threads.is_some() { + self.force_init_thread_pool()?; + } + + Ok(()) + } + + /// Initialize the global thread pool. + pub fn force_init_thread_pool(&self) -> eyre::Result<()> { + init_thread_pool(self.threads.unwrap_or(0)) + } + + /// Create a new shell instance. + pub fn shell(&self) -> Shell { + let mode = match self.quiet { + true => OutputMode::Quiet, + false => OutputMode::Normal, + }; + let color = self.json.then_some(ColorChoice::Never).or(self.color).unwrap_or_default(); + let format = match self.json { + true => OutputFormat::Json, + false => OutputFormat::Text, + }; + + Shell::new_with(format, mode, color, self.verbosity) + } +} + +/// Initialize the global thread pool. +pub fn init_thread_pool(threads: usize) -> eyre::Result<()> { + rayon::ThreadPoolBuilder::new() + .thread_name(|i| format!("foundry-{i}")) + .num_threads(threads) + .build_global()?; + Ok(()) +} diff --git a/crates/cli/src/opts/mod.rs b/crates/cli/src/opts/mod.rs index 95bf9e126..4e5d35572 100644 --- a/crates/cli/src/opts/mod.rs +++ b/crates/cli/src/opts/mod.rs @@ -2,12 +2,12 @@ mod build; mod chain; mod dependency; mod ethereum; -mod shell; +mod global; mod transaction; pub use build::*; pub use chain::*; pub use dependency::*; pub use ethereum::*; -pub use shell::*; +pub use global::*; pub use transaction::*; diff --git a/crates/cli/src/opts/shell.rs b/crates/cli/src/opts/shell.rs deleted file mode 100644 index fd83b952b..000000000 --- a/crates/cli/src/opts/shell.rs +++ /dev/null @@ -1,55 +0,0 @@ -use clap::Parser; -use foundry_common::shell::{ColorChoice, OutputFormat, Shell, Verbosity}; - -// note: `verbose` and `quiet` cannot have `short` because of conflicts with multiple commands. - -/// Global shell options. -#[derive(Clone, Copy, Debug, Parser)] -pub struct ShellOpts { - /// Use verbose output. - #[clap(long, global = true, conflicts_with = "quiet", help_heading = "Display options")] - pub verbose: bool, - - /// Do not print log messages. - #[clap( - short, - long, - global = true, - alias = "silent", - conflicts_with = "verbose", - help_heading = "Display options" - )] - pub quiet: bool, - - /// Format log messages as JSON. - #[clap( - long, - global = true, - alias = "format-json", - conflicts_with_all = &["quiet", "color"], - help_heading = "Display options" - )] - pub json: bool, - - /// Log messages coloring. - #[clap(long, global = true, value_enum, help_heading = "Display options")] - pub color: Option, -} - -impl ShellOpts { - pub fn shell(self) -> Shell { - let verbosity = match (self.verbose, self.quiet) { - (true, false) => Verbosity::Verbose, - (false, true) => Verbosity::Quiet, - (false, false) => Verbosity::Normal, - (true, true) => unreachable!(), - }; - let color = self.json.then_some(ColorChoice::Never).or(self.color).unwrap_or_default(); - let format = match self.json { - true => OutputFormat::Json, - false => OutputFormat::Text, - }; - - Shell::new_with(format, color, verbosity) - } -} diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 1bbfaf581..c2d1ed41e 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -3,11 +3,11 @@ use alloy_primitives::Address; use eyre::{Result, WrapErr}; use foundry_common::{fs, TestFunctionExt}; use foundry_compilers::{ - artifacts::{CompactBytecode, CompactDeployedBytecode, Settings}, + artifacts::{CompactBytecode, Settings}, cache::{CacheEntry, CompilerCache}, utils::read_json_file, zksync::artifact_output::zk::ZkContractArtifact, - Artifact, ProjectCompileOutput, + Artifact, ArtifactId, ProjectCompileOutput, }; use foundry_config::{error::ExtractConfigError, figment::Figment, Chain, Config, NamedChain}; use foundry_debugger::Debugger; @@ -33,17 +33,21 @@ use yansi::Paint; /// Runtime Bytecode of the given contract. #[track_caller] pub fn remove_contract( - output: &mut ProjectCompileOutput, + output: ProjectCompileOutput, path: &Path, name: &str, -) -> Result<(JsonAbi, CompactBytecode, CompactDeployedBytecode)> { - let contract = if let Some(contract) = output.remove(path, name) { - contract - } else { +) -> Result<(JsonAbi, CompactBytecode, ArtifactId)> { + let mut other = Vec::new(); + let Some((id, contract)) = output.into_artifacts().find_map(|(id, artifact)| { + if id.name == name && id.source == path { + Some((id, artifact)) + } else { + other.push(id.name); + None + } + }) else { let mut err = format!("could not find artifact: `{name}`"); - if let Some(suggestion) = - super::did_you_mean(name, output.artifacts().map(|(name, _)| name)).pop() - { + if let Some(suggestion) = super::did_you_mean(name, other).pop() { if suggestion != name { err = format!( r#"{err} @@ -65,12 +69,7 @@ pub fn remove_contract( .ok_or_else(|| eyre::eyre!("contract {} does not contain bytecode", name))? .into_owned(); - let runtime = contract - .get_deployed_bytecode() - .ok_or_else(|| eyre::eyre!("contract {} does not contain deployed bytecode", name))? - .into_owned(); - - Ok((abi, bin, runtime)) + Ok((abi, bin, id)) } /// Given a `Project`'s output, removes the matching ABI, Bytecode and @@ -80,14 +79,19 @@ pub fn remove_zk_contract( output: &mut foundry_compilers::zksync::compile::output::ProjectCompileOutput, path: &Path, name: &str, -) -> Result { - let contract = if let Some(contract) = output.remove(path, name) { - contract - } else { +) -> Result<(ZkContractArtifact, ArtifactId)> { + let mut other = Vec::new(); + + let Some(id) = output.artifact_ids().find_map(|(id, _)| { + if id.name == name && id.source == path { + Some(id) + } else { + other.push(id.name); + None + } + }) else { let mut err = format!("could not find artifact: `{name}`"); - if let Some(suggestion) = - super::did_you_mean(name, output.artifacts().map(|(name, _)| name)).pop() - { + if let Some(suggestion) = super::did_you_mean(name, other).pop() { if suggestion != name { err = format!( r#"{err} @@ -99,7 +103,10 @@ pub fn remove_zk_contract( eyre::bail!(err) }; - Ok(contract) + let contract = + output.remove(id.source.as_ref(), &id.name).expect("contract found to exist in zk output"); + + Ok((contract, id)) } /// Helper function for finding a contract by ContractName @@ -158,9 +165,8 @@ pub fn needs_setup(abi: &JsonAbi) -> bool { for setup_fn in setup_fns.iter() { if setup_fn.name != "setUp" { - println!( - "{} Found invalid setup function \"{}\" did you mean \"setUp()\"?", - "Warning:".yellow().bold(), + let _ = sh_warn!( + "Found invalid setup function \"{}\" did you mean \"setUp()\"?", setup_fn.signature() ); } @@ -482,19 +488,19 @@ pub async fn print_traces( ) -> Result<()> { let traces = result.traces.as_mut().expect("No traces found"); - println!("Traces:"); + sh_println!("Traces:")?; for (_, arena) in traces { decode_trace_arena(arena, decoder).await?; - println!("{}", render_trace_arena_with_bytecodes(arena, verbose)); + sh_println!("{}", render_trace_arena_with_bytecodes(arena, verbose))?; } - println!(); + sh_println!()?; if result.success { - println!("{}", "Transaction successfully executed.".green()); + sh_println!("{}", "Transaction successfully executed.".green())?; } else { - println!("{}", "Transaction failed.".red()); + sh_err!("Transaction failed.")?; } - println!("Gas used: {}", result.gas_used); + sh_println!("Gas used: {}", result.gas_used)?; Ok(()) } diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index ea8f0e46e..12b952fda 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -21,6 +21,7 @@ foundry-config.workspace = true alloy-contract.workspace = true alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } +alloy-eips.workspace = true alloy-json-abi.workspace = true alloy-json-rpc.workspace = true alloy-primitives = { workspace = true, features = [ @@ -52,11 +53,12 @@ clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] } comfy-table.workspace = true dunce.workspace = true eyre.workspace = true +itertools.workspace = true num-format.workspace = true reqwest.workspace = true semver.workspace = true serde_json.workspace = true -serde.workspace = true +serde = { workspace = true, features = ["derive"] } thiserror.workspace = true tokio.workspace = true tracing.workspace = true diff --git a/crates/common/fmt/src/dynamic.rs b/crates/common/fmt/src/dynamic.rs index 498d209f7..2ba40286d 100644 --- a/crates/common/fmt/src/dynamic.rs +++ b/crates/common/fmt/src/dynamic.rs @@ -132,18 +132,6 @@ pub fn format_tokens_raw(tokens: &[DynSolValue]) -> impl Iterator tokens.iter().map(format_token_raw) } -/// Prints slice of tokens using [`format_tokens`] or [`format_tokens_raw`] depending on `json` -/// parameter. -pub fn print_tokens(tokens: &[DynSolValue], json: bool) { - if json { - let tokens: Vec = format_tokens_raw(tokens).collect(); - println!("{}", serde_json::to_string_pretty(&tokens).unwrap()); - } else { - let tokens = format_tokens(tokens); - tokens.for_each(|t| println!("{t}")); - } -} - /// Pretty-prints the given value into a string suitable for user output. pub fn format_token(value: &DynSolValue) -> String { DynValueDisplay::new(value, false).to_string() diff --git a/crates/common/fmt/src/lib.rs b/crates/common/fmt/src/lib.rs index f6f792e99..b76016cd4 100644 --- a/crates/common/fmt/src/lib.rs +++ b/crates/common/fmt/src/lib.rs @@ -4,9 +4,7 @@ mod console; pub use console::{console_format, ConsoleFmt, FormatSpec}; mod dynamic; -pub use dynamic::{ - format_token, format_token_raw, format_tokens, format_tokens_raw, parse_tokens, print_tokens, -}; +pub use dynamic::{format_token, format_token_raw, format_tokens, format_tokens_raw, parse_tokens}; mod exp; pub use exp::{format_int_exp, format_uint_exp, to_exp_notation}; diff --git a/crates/common/fmt/src/ui.rs b/crates/common/fmt/src/ui.rs index 5534e72d8..a82d2cdc3 100644 --- a/crates/common/fmt/src/ui.rs +++ b/crates/common/fmt/src/ui.rs @@ -1,11 +1,14 @@ //! Helper trait and functions to format Ethereum types. -use alloy_consensus::{AnyReceiptEnvelope, Eip658Value, Receipt, ReceiptWithBloom, TxType}; -use alloy_network::ReceiptResponse; -use alloy_primitives::{hex, Address, Bloom, Bytes, FixedBytes, Uint, B256, I256, U256, U64}; +use alloy_consensus::{ + AnyReceiptEnvelope, Eip658Value, Receipt, ReceiptWithBloom, Transaction as TxTrait, TxEnvelope, + TxType, +}; +use alloy_network::{AnyHeader, AnyRpcBlock, AnyTxEnvelope, ReceiptResponse}; +use alloy_primitives::{hex, Address, Bloom, Bytes, FixedBytes, Uint, I256, U256, U64, U8}; use alloy_rpc_types::{ - AccessListItem, AnyNetworkBlock, AnyTransactionReceipt, Block, BlockTransactions, Header, Log, - Transaction, TransactionReceipt, + AccessListItem, AnyTransactionReceipt, Block, BlockTransactions, Header, Log, Transaction, + TransactionReceipt, }; use alloy_serde::{OtherFields, WithOtherFields}; use serde::Deserialize; @@ -267,7 +270,7 @@ transactionIndex: {}", } } -impl UIfmt for Block { +impl UIfmt for Block> { fn pretty(&self) -> String { format!( " @@ -317,10 +320,210 @@ impl UIfmt for AccessListItem { } } +impl UIfmt for TxEnvelope { + fn pretty(&self) -> String { + match &self { + Self::Eip2930(tx) => format!( + " +accessList {} +chainId {} +gasLimit {} +gasPrice {} +hash {} +input {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + Self::Eip1559(tx) => format!( + " +accessList {} +chainId {} +gasLimit {} +hash {} +input {} +maxFeePerGas {} +maxPriorityFeePerGas {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + Self::Eip4844(tx) => format!( + " +accessList {} +blobVersionedHashes {} +chainId {} +gasLimit {} +hash {} +input {} +maxFeePerBlobGas {} +maxFeePerGas {} +maxPriorityFeePerGas {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.blob_versioned_hashes().unwrap_or(&[]).pretty(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.max_fee_per_blob_gas().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + Self::Eip7702(tx) => format!( + " +accessList {} +authorizationList {} +chainId {} +gasLimit {} +hash {} +input {} +maxFeePerGas {} +maxPriorityFeePerGas {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.authorization_list() + .as_ref() + .map(|l| serde_json::to_string(&l).unwrap()) + .unwrap_or_default(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + _ => format!( + " +gas {} +gasPrice {} +hash {} +input {} +nonce {} +r {} +s {} +to {} +type {} +v {} +value {}", + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + self.as_legacy() + .map(|tx| FixedBytes::from(tx.signature().r()).pretty()) + .unwrap_or_default(), + self.as_legacy() + .map(|tx| FixedBytes::from(tx.signature().s()).pretty()) + .unwrap_or_default(), + self.to().pretty(), + self.ty(), + self.as_legacy() + .map(|tx| (if tx.signature().v() { 1u64 } else { 0 }).pretty()) + .unwrap_or_default(), + self.value().pretty(), + ), + } + } +} + +impl UIfmt for AnyTxEnvelope { + fn pretty(&self) -> String { + match self { + Self::Ethereum(envelop) => envelop.pretty(), + Self::Unknown(tx) => { + format!( + " +hash {} +type {} +{} + ", + tx.hash.pretty(), + tx.ty(), + tx.inner.fields.pretty(), + ) + } + } + } +} impl UIfmt for Transaction { fn pretty(&self) -> String { - match self.transaction_type { - Some(1) => format!( + match &self.inner { + TxEnvelope::Eip2930(tx) => format!( " accessList {} blockHash {} @@ -339,25 +542,29 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.gas_price.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.inner.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), - Some(2) => format!( + TxEnvelope::Eip1559(tx) => format!( " accessList {} blockHash {} @@ -377,26 +584,30 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.max_fee_per_gas.pretty(), - self.max_priority_fee_per_gas.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + tx.hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), - Some(3) => format!( + TxEnvelope::Eip4844(tx) => format!( " accessList {} blobVersionedHashes {} @@ -418,28 +629,32 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), - self.blob_versioned_hashes.as_deref().unwrap_or(&[]).pretty(), + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.blob_versioned_hashes().unwrap_or(&[]).pretty(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.max_fee_per_blob_gas.pretty(), - self.max_fee_per_gas.pretty(), - self.max_priority_fee_per_gas.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + tx.hash().pretty(), + self.input().pretty(), + self.max_fee_per_blob_gas().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), - Some(4) => format!( + TxEnvelope::Eip7702(tx) => format!( " accessList {} authorizationList {} @@ -460,28 +675,32 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), - self.authorization_list + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.authorization_list() .as_ref() .map(|l| serde_json::to_string(&l).unwrap()) .unwrap_or_default(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.max_fee_per_gas.pretty(), - self.max_priority_fee_per_gas.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + tx.hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), _ => format!( " @@ -502,22 +721,52 @@ value {}", self.block_hash.pretty(), self.block_number.pretty(), self.from.pretty(), - self.gas.pretty(), - self.gas_price.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.nonce, - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.inner.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + self.inner + .as_legacy() + .map(|tx| FixedBytes::from(tx.signature().r()).pretty()) + .unwrap_or_default(), + self.inner + .as_legacy() + .map(|tx| FixedBytes::from(tx.signature().s()).pretty()) + .unwrap_or_default(), + self.to().pretty(), self.transaction_index.pretty(), - self.signature.map(|s| s.v).pretty(), - self.value.pretty(), + self.inner + .as_legacy() + .map(|tx| (if tx.signature().v() { 1u64 } else { 0 }).pretty()) + .unwrap_or_default(), + self.value().pretty(), ), } } } +impl UIfmt for Transaction { + fn pretty(&self) -> String { + format!( + " +blockHash {} +blockNumber {} +from {} +transactionIndex {} +effectiveGasPrice {} +{} + ", + self.block_hash.pretty(), + self.block_number.pretty(), + self.from.pretty(), + self.transaction_index.pretty(), + self.effective_gas_price.pretty(), + self.inner.pretty(), + ) + } +} + impl UIfmt for WithOtherFields { fn pretty(&self) -> String { format!("{}{}", self.inner.pretty(), self.other.pretty()) @@ -555,28 +804,39 @@ impl UIfmt for EthValue { } /// Returns the `UiFmt::pretty()` formatted attribute of the transactions -pub fn get_pretty_tx_attr(transaction: &Transaction, attr: &str) -> Option { +pub fn get_pretty_tx_attr(transaction: &Transaction, attr: &str) -> Option { + let sig = match &transaction.inner { + AnyTxEnvelope::Ethereum(envelope) => match &envelope { + TxEnvelope::Eip2930(tx) => Some(tx.signature()), + TxEnvelope::Eip1559(tx) => Some(tx.signature()), + TxEnvelope::Eip4844(tx) => Some(tx.signature()), + TxEnvelope::Eip7702(tx) => Some(tx.signature()), + TxEnvelope::Legacy(tx) => Some(tx.signature()), + _ => None, + }, + _ => None, + }; match attr { "blockHash" | "block_hash" => Some(transaction.block_hash.pretty()), "blockNumber" | "block_number" => Some(transaction.block_number.pretty()), "from" => Some(transaction.from.pretty()), - "gas" => Some(transaction.gas.pretty()), - "gasPrice" | "gas_price" => Some(transaction.gas_price.pretty()), - "hash" => Some(transaction.hash.pretty()), - "input" => Some(transaction.input.pretty()), - "nonce" => Some(transaction.nonce.to_string()), - "s" => transaction.signature.map(|s| B256::from(s.s).pretty()), - "r" => transaction.signature.map(|s| B256::from(s.r).pretty()), - "to" => Some(transaction.to.pretty()), + "gas" => Some(transaction.gas_limit().pretty()), + "gasPrice" | "gas_price" => Some(Transaction::gas_price(transaction).pretty()), + "hash" => Some(alloy_network::TransactionResponse::tx_hash(transaction).pretty()), + "input" => Some(transaction.input().pretty()), + "nonce" => Some(transaction.nonce().to_string()), + "s" => sig.map(|s| FixedBytes::from(s.s()).pretty()), + "r" => sig.map(|s| FixedBytes::from(s.r()).pretty()), + "to" => Some(transaction.to().pretty()), "transactionIndex" | "transaction_index" => Some(transaction.transaction_index.pretty()), - "v" => transaction.signature.map(|s| s.v.pretty()), - "value" => Some(transaction.value.pretty()), + "v" => sig.map(|s| U8::from_be_slice(&s.as_bytes()[64..]).pretty()), + "value" => Some(transaction.value().pretty()), _ => None, } } /// Returns the `UiFmt::pretty()` formatted attribute of the given block -pub fn get_pretty_block_attr(block: &AnyNetworkBlock, attr: &str) -> Option { +pub fn get_pretty_block_attr(block: &AnyRpcBlock, attr: &str) -> Option { match attr { "baseFeePerGas" | "base_fee_per_gas" => Some(block.header.base_fee_per_gas.pretty()), "difficulty" => Some(block.header.difficulty.pretty()), @@ -585,15 +845,15 @@ pub fn get_pretty_block_attr(block: &AnyNetworkBlock, attr: &str) -> Option Some(block.header.gas_used.pretty()), "hash" => Some(block.header.hash.pretty()), "logsBloom" | "logs_bloom" => Some(block.header.logs_bloom.pretty()), - "miner" | "author" => Some(block.header.miner.pretty()), + "miner" | "author" => Some(block.header.inner.beneficiary.pretty()), "mixHash" | "mix_hash" => Some(block.header.mix_hash.pretty()), "nonce" => Some(block.header.nonce.pretty()), "number" => Some(block.header.number.pretty()), "parentHash" | "parent_hash" => Some(block.header.parent_hash.pretty()), "transactionsRoot" | "transactions_root" => Some(block.header.transactions_root.pretty()), "receiptsRoot" | "receipts_root" => Some(block.header.receipts_root.pretty()), - "sha3Uncles" | "sha_3_uncles" => Some(block.header.uncles_hash.pretty()), - "size" => Some(block.size.pretty()), + "sha3Uncles" | "sha_3_uncles" => Some(block.header.ommers_hash.pretty()), + "size" => Some(block.header.size.pretty()), "stateRoot" | "state_root" => Some(block.header.state_root.pretty()), "timestamp" => Some(block.header.timestamp.pretty()), "totalDifficulty" | "total_difficult" => Some(block.header.total_difficulty.pretty()), @@ -610,37 +870,40 @@ pub fn get_pretty_block_attr(block: &AnyNetworkBlock, attr: &str) -> Option(block: &Block) -> String { +fn pretty_block_basics(block: &Block>) -> String { let Block { header: Header { hash, - parent_hash, - uncles_hash, - miner, - state_root, - transactions_root, - receipts_root, - logs_bloom, - difficulty, - number, - gas_limit, - gas_used, - timestamp, + size, total_difficulty, - extra_data, - mix_hash, - nonce, - base_fee_per_gas, - withdrawals_root, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - requests_hash, + inner: + AnyHeader { + parent_hash, + ommers_hash, + beneficiary, + state_root, + transactions_root, + receipts_root, + logs_bloom, + difficulty, + number, + gas_limit, + gas_used, + timestamp, + extra_data, + mix_hash, + nonce, + base_fee_per_gas, + withdrawals_root, + blob_gas_used, + excess_blob_gas, + parent_beacon_block_root, + requests_hash, + }, }, uncles: _, transactions: _, - size, withdrawals: _, } = block; format!( @@ -676,7 +939,7 @@ requestsHash {}", gas_used.pretty(), hash.pretty(), logs_bloom.pretty(), - miner.pretty(), + beneficiary.pretty(), mix_hash.pretty(), nonce.pretty(), number.pretty(), @@ -684,7 +947,7 @@ requestsHash {}", parent_beacon_block_root.pretty(), transactions_root.pretty(), receipts_root.pretty(), - uncles_hash.pretty(), + ommers_hash.pretty(), size.pretty(), state_root.pretty(), timestamp.pretty(), @@ -702,6 +965,7 @@ requestsHash {}", #[cfg(test)] mod tests { use super::*; + use alloy_primitives::B256; use similar_asserts::assert_eq; use std::str::FromStr; @@ -764,7 +1028,7 @@ r 0x6fca94073a0cf3381978662d46cf890602d3e9ccf6a31e4b69e8ecbd9 s 0x0e804161a2b56a37ca1f6f4c4b8bce926587afa0d9b1acc5165e6556c959d583 to 0x4a16A42407AA491564643E1dfc1fd50af29794eF transactionIndex 0 -v 56 +v 1 value 0 index 435 l1BlockNumber 12691036 @@ -973,7 +1237,7 @@ r 0x19f2694eb9113656dbea0b925e2e7ceb43df83e601c4116aee9c0dd99 s 0x73e5764b324a4f7679d890a198ba658ba1c8cd36983ff9797e10b1b89dbb448e to 0xdca8ce283150AB773BCbeB8d38289bdB5661dE1e transactionIndex 0 -v 37 +v 0 value 0".to_string(); let txs = match block.transactions { BlockTransactions::Full(txs) => txs, @@ -1027,11 +1291,12 @@ value 0".to_string(); #[test] fn test_pretty_tx_attr() { let block = r#"{"number":"0x3","hash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","parentHash":"0x689c70c080ca22bc0e681694fa803c1aba16a69c8b6368fed5311d279eb9de90","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x7270c1c4440180f2bd5215809ee3d545df042b67329499e1ab97eb759d31610d","stateRoot":"0x29f32984517a7d25607da485b23cefabfd443751422ca7e603395e1de9bc8a4b","receiptsRoot":"0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x3e8","gasLimit":"0x6691b7","gasUsed":"0x5208","timestamp":"0x5ecedbb9","transactions":[{"hash":"0xc3c5f700243de37ae986082fd2af88d2a7c2752a0c0f7b9d6ac47c729d45e067","nonce":"0x2","blockHash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","blockNumber":"0x3","transactionIndex":"0x0","from":"0xfdcedc3bfca10ecb0890337fbdd1977aba84807a","to":"0xdca8ce283150ab773bcbeb8d38289bdb5661de1e","value":"0x0","gas":"0x15f90","gasPrice":"0x4a817c800","input":"0x","v":"0x25","r":"0x19f2694eb9113656dbea0b925e2e7ceb43df83e601c4116aee9c0dd99130be88","s":"0x73e5764b324a4f7679d890a198ba658ba1c8cd36983ff9797e10b1b89dbb448e"}],"uncles":[]}"#; - let block: Block = serde_json::from_str(block).unwrap(); + let block: Block> = serde_json::from_str(block).unwrap(); let txs = match block.transactions { BlockTransactions::Full(txes) => txes, _ => panic!("not full transactions"), }; + assert_eq!(None, get_pretty_tx_attr(&txs[0], "")); assert_eq!(Some("3".to_string()), get_pretty_tx_attr(&txs[0], "blockNumber")); assert_eq!( @@ -1059,7 +1324,7 @@ value 0".to_string(); get_pretty_tx_attr(&txs[0], "to") ); assert_eq!(Some("0".to_string()), get_pretty_tx_attr(&txs[0], "transactionIndex")); - assert_eq!(Some("37".to_string()), get_pretty_tx_attr(&txs[0], "v")); + assert_eq!(Some("27".to_string()), get_pretty_tx_attr(&txs[0], "v")); assert_eq!(Some("0".to_string()), get_pretty_tx_attr(&txs[0], "value")); } @@ -1096,7 +1361,7 @@ value 0".to_string(); } ); - let block: AnyNetworkBlock = serde_json::from_value(json).unwrap(); + let block: AnyRpcBlock = serde_json::from_value(json).unwrap(); assert_eq!(None, get_pretty_block_attr(&block, "")); assert_eq!(Some("7".to_string()), get_pretty_block_attr(&block, "baseFeePerGas")); diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index bcf82b1cd..de9b36219 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -146,9 +146,9 @@ pub fn find_source( Ok(source) } else { let implementation = metadata.implementation.unwrap(); - println!( + sh_println!( "Contract at {address} is a proxy, trying to fetch source at {implementation}..." - ); + )?; match find_source(client, implementation).await { impl_source @ Ok(_) => impl_source, Err(e) => { diff --git a/crates/common/src/compile.rs b/crates/common/src/compile.rs index 70575802f..81e45f67f 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -1,6 +1,11 @@ //! Support for compiling [foundry_compilers::Project] -use crate::{term::SpinnerReporter, TestFunctionExt}; +use crate::{ + reports::{report_kind, ReportKind}, + shell, + term::SpinnerReporter, + TestFunctionExt, +}; use comfy_table::{presets::ASCII_MARKDOWN, Attribute, Cell, CellAlignment, Color, Table}; use eyre::Result; use foundry_block_explorers::contract::Metadata; @@ -144,7 +149,7 @@ impl ProjectCompiler { pub fn compile(mut self, project: &Project) -> Result> { // TODO: Avoid process::exit if !project.paths.has_input_files() && self.files.is_empty() { - println!("Nothing to compile"); + sh_println!("Nothing to compile")?; // nothing to do here std::process::exit(0); } @@ -198,11 +203,13 @@ impl ProjectCompiler { } if !quiet { - if output.is_unchanged() { - println!("No files changed, compilation skipped"); - } else { - // print the compiler output / warnings - println!("{output}"); + if !shell::is_json() { + if output.is_unchanged() { + sh_println!("No files changed, compilation skipped")?; + } else { + // print the compiler output / warnings + sh_println!("{output}")?; + } } self.handle_output(&output); @@ -222,24 +229,35 @@ impl ProjectCompiler { for (name, (_, version)) in output.versioned_artifacts() { artifacts.entry(version).or_default().push(name); } - for (version, names) in artifacts { - println!( - " compiler version: {}.{}.{}", - version.major, version.minor, version.patch - ); - for name in names { - println!(" - {name}"); + + if shell::is_json() { + let _ = sh_println!("{}", serde_json::to_string(&artifacts).unwrap()); + } else { + for (version, names) in artifacts { + let _ = sh_println!( + " compiler version: {}.{}.{}", + version.major, + version.minor, + version.patch + ); + for name in names { + let _ = sh_println!(" - {name}"); + } } } } if print_sizes { // add extra newline if names were already printed - if print_names { - println!(); + if print_names && !shell::is_json() { + let _ = sh_println!(); } - let mut size_report = SizeReport { contracts: BTreeMap::new(), zksync: self.zksync }; + let mut size_report = SizeReport { + report_kind: report_kind(), + contracts: BTreeMap::new(), + zksync: self.zksync, + }; let artifacts: BTreeMap<_, _> = output .artifact_ids() @@ -269,7 +287,7 @@ impl ProjectCompiler { .insert(name, ContractInfo { runtime_size, init_size, is_dev_contract }); } - println!("{size_report}"); + let _ = sh_println!("{size_report}"); // TODO: avoid process::exit // exit with error if any contract exceeds the size limit, excluding test contracts. @@ -291,7 +309,7 @@ impl ProjectCompiler { ) -> Result { // TODO: Avoid process::exit if !project.paths.has_input_files() && self.files.is_empty() { - println!("Nothing to compile"); + sh_println!("Nothing to compile")?; // nothing to do here std::process::exit(0); } @@ -361,10 +379,10 @@ impl ProjectCompiler { if !quiet { if output.is_unchanged() { - println!("No files changed, compilation skipped"); + sh_println!("No files changed, compilation skipped")?; } else { // print the compiler output / warnings - println!("{output}"); + sh_println!("{output}")?; } self.zksync_handle_output(root_path, &output)?; @@ -448,23 +466,29 @@ impl ProjectCompiler { artifacts.entry(version).or_default().push(name); } for (version, names) in artifacts { - println!( + let _ = sh_println!( " compiler version: {}.{}.{}", - version.major, version.minor, version.patch + version.major, + version.minor, + version.patch ); for name in names { - println!(" - {name}"); + let _ = sh_println!(" - {name}"); } } } if print_sizes { // add extra newline if names were already printed - if print_names { - println!(); + if print_names && !shell::is_json() { + let _ = sh_println!(); } - let mut size_report = SizeReport { contracts: BTreeMap::new(), zksync: self.zksync }; + let mut size_report = SizeReport { + report_kind: report_kind(), + contracts: BTreeMap::new(), + zksync: self.zksync, + }; let artifacts: BTreeMap<_, _> = output .artifact_ids() @@ -494,7 +518,7 @@ impl ProjectCompiler { .insert(name, ContractInfo { runtime_size, init_size, is_dev_contract }); } - println!("{size_report}"); + let _ = sh_println!("{size_report}"); // TODO: avoid process::exit // exit with error if any contract exceeds the size limit, excluding test contracts. @@ -522,6 +546,8 @@ const ZKSYNC_CONTRACT_SIZE_LIMIT: usize = 450999; /// Contracts with info about their size pub struct SizeReport { + /// What kind of report to generate. + report_kind: ReportKind, /// `contract name -> info` pub contracts: BTreeMap, /// Using zksync size report @@ -570,6 +596,43 @@ impl SizeReport { impl Display for SizeReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + match self.report_kind { + ReportKind::Markdown => { + let table = self.format_table_output(); + writeln!(f, "{table}")?; + } + ReportKind::JSON => { + writeln!(f, "{}", self.format_json_output())?; + } + } + + Ok(()) + } +} + +impl SizeReport { + fn format_json_output(&self) -> String { + let contracts = self + .contracts + .iter() + .filter(|(_, c)| !c.is_dev_contract && (c.runtime_size > 0 || c.init_size > 0)) + .map(|(name, contract)| { + ( + name.clone(), + serde_json::json!({ + "runtime_size": contract.runtime_size, + "init_size": contract.init_size, + "runtime_margin": CONTRACT_RUNTIME_SIZE_LIMIT as isize - contract.runtime_size as isize, + "init_margin": CONTRACT_INITCODE_SIZE_LIMIT as isize - contract.init_size as isize, + }), + ) + }) + .collect::>(); + + serde_json::to_string(&contracts).unwrap() + } + + fn format_table_output(&self) -> Table { let mut table = Table::new(); table.load_preset(ASCII_MARKDOWN); table.set_header([ @@ -643,8 +706,7 @@ impl Display for SizeReport { ]); } - writeln!(f, "{table}")?; - Ok(()) + table } } @@ -661,7 +723,7 @@ fn contract_size(artifact: &T, initcode: bool) -> Option { BytecodeObject::Unlinked(unlinked) => { // we don't need to account for placeholders here, because library placeholders take up // 40 characters: `__$$__` which is the same as a 20byte address in hex. - let mut size = unlinked.as_bytes().len(); + let mut size = unlinked.len(); if unlinked.starts_with("0x") { size -= 2; } @@ -753,7 +815,7 @@ pub fn etherscan_project( /// Configures the reporter and runs the given closure. pub fn with_compilation_reporter(quiet: bool, f: impl FnOnce() -> O) -> O { #[allow(clippy::collapsible_else_if)] - let reporter = if quiet { + let reporter = if quiet || shell::is_json() { Report::new(NoReporter::default()) } else { if std::io::stdout().is_terminal() { diff --git a/crates/common/src/ens.rs b/crates/common/src/ens.rs index f84ea84ce..1c4eadeac 100644 --- a/crates/common/src/ens.rs +++ b/crates/common/src/ens.rs @@ -123,7 +123,9 @@ pub trait ProviderEnsExt> { .call() .await .map_err(EnsError::Resolve) - .inspect_err(|e| eprintln!("{e:?}"))? + .inspect_err(|e| { + let _ = sh_eprintln!("{e:?}"); + })? ._0; Ok(addr) } diff --git a/crates/common/src/evm.rs b/crates/common/src/evm.rs index e738cc6dd..3eca0800e 100644 --- a/crates/common/src/evm.rs +++ b/crates/common/src/evm.rs @@ -1,7 +1,7 @@ //! CLI arguments for configuring the EVM settings. use alloy_primitives::{map::HashMap, Address, B256, U256}; -use clap::{ArgAction, Parser}; +use clap::Parser; use eyre::ContextCompat; use foundry_config::{ figment::{ @@ -14,6 +14,8 @@ use foundry_config::{ }; use serde::Serialize; +use crate::shell; + /// Map keyed by breakpoints char to their location (contract address, pc) pub type Breakpoints = HashMap; @@ -101,19 +103,6 @@ pub struct EvmArgs { #[serde(skip)] pub always_use_create_2_factory: bool, - /// Verbosity of the EVM. - /// - /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). - /// - /// Verbosity levels: - /// - 2: Print logs for all tests - /// - 3: Print execution traces for failing tests - /// - 4: Print execution traces for all tests, and setup traces for failing tests - /// - 5: Print execution and setup traces for all tests - #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count)] - #[serde(skip)] - pub verbosity: u8, - /// Sets the number of assumed available compute units per second for this provider /// /// default value: 330 @@ -163,9 +152,9 @@ impl Provider for EvmArgs { let error = InvalidType(value.to_actual(), "map".into()); let mut dict = value.into_dict().ok_or(error)?; - if self.verbosity > 0 { + if shell::verbosity() > 0 { // need to merge that manually otherwise `from_occurrences` does not work - dict.insert("verbosity".to_string(), self.verbosity.into()); + dict.insert("verbosity".to_string(), shell::verbosity().into()); } if self.ffi { diff --git a/crates/common/src/io/shell.rs b/crates/common/src/io/shell.rs index 45d9c2296..fd667ea68 100644 --- a/crates/common/src/io/shell.rs +++ b/crates/common/src/io/shell.rs @@ -7,6 +7,7 @@ use anstream::AutoStream; use anstyle::Style; use clap::ValueEnum; use eyre::Result; +use serde::{Deserialize, Serialize}; use std::{ fmt, io::{prelude::*, IsTerminal}, @@ -17,19 +18,24 @@ use std::{ }, }; -/// Returns the currently set verbosity. +/// Returns the currently set verbosity level. pub fn verbosity() -> Verbosity { Shell::get().verbosity() } -/// Returns whether the verbosity level is [`Verbosity::Quiet`]. +/// Set the verbosity level. +pub fn set_verbosity(verbosity: Verbosity) { + Shell::get().set_verbosity(verbosity); +} + +/// Returns whether the output mode is [`OutputMode::Quiet`]. pub fn is_quiet() -> bool { - verbosity().is_quiet() + Shell::get().output_mode().is_quiet() } /// Returns whether the output format is [`OutputFormat::Json`]. pub fn is_json() -> bool { - Shell::get().output_format().is_json() + Shell::get().is_json() } /// The global shell instance. @@ -68,11 +74,9 @@ impl TtyWidth { } } -/// The requested verbosity of output. #[derive(Debug, Default, Clone, Copy, PartialEq)] -pub enum Verbosity { - /// All output - Verbose, +/// The requested output mode. +pub enum OutputMode { /// Default output #[default] Normal, @@ -80,20 +84,14 @@ pub enum Verbosity { Quiet, } -impl Verbosity { - /// Returns true if the verbosity level is `Verbose`. - #[inline] - pub fn is_verbose(self) -> bool { - self == Self::Verbose - } - - /// Returns true if the verbosity level is `Normal`. +impl OutputMode { + /// Returns true if the output mode is `Normal`. #[inline] pub fn is_normal(self) -> bool { self == Self::Normal } - /// Returns true if the verbosity level is `Quiet`. + /// Returns true if the output mode is `Quiet`. #[inline] pub fn is_quiet(self) -> bool { self == Self::Quiet @@ -124,6 +122,9 @@ impl OutputFormat { } } +/// The verbosity level. +pub type Verbosity = u8; + /// An abstraction around console output that remembers preferences for output /// verbosity and color. pub struct Shell { @@ -134,7 +135,10 @@ pub struct Shell { /// The format to use for message output. output_format: OutputFormat, - /// How verbose messages should be. + /// The verbosity mode to use for message output. + output_mode: OutputMode, + + /// The verbosity level to use for message output. verbosity: Verbosity, /// Flag that indicates the current line needs to be cleared before @@ -145,6 +149,8 @@ pub struct Shell { impl fmt::Debug for Shell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("Shell"); + s.field("output_format", &self.output_format); + s.field("output_mode", &self.output_mode); s.field("verbosity", &self.verbosity); if let ShellOut::Stream { color_choice, .. } = self.output { s.field("color_choice", &color_choice); @@ -167,7 +173,7 @@ enum ShellOut { } /// Whether messages should use color output. -#[derive(Debug, Default, PartialEq, Clone, Copy, ValueEnum)] +#[derive(Debug, Default, PartialEq, Clone, Copy, Serialize, Deserialize, ValueEnum)] pub enum ColorChoice { /// Intelligently guess whether to use color output (default). #[default] @@ -190,12 +196,22 @@ impl Shell { /// output. #[inline] pub fn new() -> Self { - Self::new_with(OutputFormat::Text, ColorChoice::Auto, Verbosity::Verbose) + Self::new_with( + OutputFormat::Text, + OutputMode::Normal, + ColorChoice::Auto, + Verbosity::default(), + ) } /// Creates a new shell with the given color choice and verbosity. #[inline] - pub fn new_with(format: OutputFormat, color: ColorChoice, verbosity: Verbosity) -> Self { + pub fn new_with( + format: OutputFormat, + mode: OutputMode, + color: ColorChoice, + verbosity: Verbosity, + ) -> Self { Self { output: ShellOut::Stream { stdout: AutoStream::new(std::io::stdout(), color.to_anstream_color_choice()), @@ -204,6 +220,7 @@ impl Shell { stderr_tty: std::io::stderr().is_terminal(), }, output_format: format, + output_mode: mode, verbosity, needs_clear: AtomicBool::new(false), } @@ -215,7 +232,8 @@ impl Shell { Self { output: ShellOut::Empty(std::io::empty()), output_format: OutputFormat::Text, - verbosity: Verbosity::Quiet, + output_mode: OutputMode::Quiet, + verbosity: 0, needs_clear: AtomicBool::new(false), } } @@ -245,6 +263,16 @@ impl Shell { self.needs_clear.swap(needs_clear, Ordering::Relaxed) } + /// Returns `true` if the output format is JSON. + pub fn is_json(&self) -> bool { + self.output_format.is_json() + } + + /// Returns `true` if the verbosity level is `Quiet`. + pub fn is_quiet(&self) -> bool { + self.output_mode.is_quiet() + } + /// Returns `true` if the `needs_clear` flag is set. #[inline] pub fn needs_clear(&self) -> bool { @@ -266,15 +294,27 @@ impl Shell { } } - /// Gets the verbosity of the shell. + /// Gets the output format of the shell. + #[inline] + pub fn output_format(&self) -> OutputFormat { + self.output_format + } + + /// Gets the output mode of the shell. + #[inline] + pub fn output_mode(&self) -> OutputMode { + self.output_mode + } + + /// Gets the verbosity of the shell when [`OutputMode::Normal`] is set. #[inline] pub fn verbosity(&self) -> Verbosity { self.verbosity } - /// Gets the output format of the shell. - pub fn output_format(&self) -> OutputFormat { - self.output_format + /// Sets the verbosity level. + pub fn set_verbosity(&mut self, verbosity: Verbosity) { + self.verbosity = verbosity; } /// Gets the current color choice. @@ -338,24 +378,6 @@ impl Shell { } } - /// Runs the callback only if we are in verbose mode. - #[inline] - pub fn verbose(&mut self, mut callback: impl FnMut(&mut Self) -> Result<()>) -> Result<()> { - match self.verbosity { - Verbosity::Verbose => callback(self), - _ => Ok(()), - } - } - - /// Runs the callback if we are not in verbose mode. - #[inline] - pub fn concise(&mut self, mut callback: impl FnMut(&mut Self) -> Result<()>) -> Result<()> { - match self.verbosity { - Verbosity::Verbose => Ok(()), - _ => callback(self), - } - } - /// Prints a red 'error' message. Use the [`sh_err!`] macro instead. /// This will render a message in [ERROR] style with a bold `Error: ` prefix. /// @@ -370,8 +392,8 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn warn(&mut self, message: impl fmt::Display) -> Result<()> { - match self.verbosity { - Verbosity::Quiet => Ok(()), + match self.output_mode { + OutputMode::Quiet => Ok(()), _ => self.print(&"Warning", &WARN, Some(&message), false), } } @@ -387,10 +409,9 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn print_out(&mut self, fragment: impl fmt::Display) -> Result<()> { - if self.verbosity == Verbosity::Quiet { - Ok(()) - } else { - self.write_stdout(fragment, &Style::new()) + match self.output_mode { + OutputMode::Quiet => Ok(()), + _ => self.write_stdout(fragment, &Style::new()), } } @@ -405,10 +426,9 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn print_err(&mut self, fragment: impl fmt::Display) -> Result<()> { - if self.verbosity == Verbosity::Quiet { - Ok(()) - } else { - self.write_stderr(fragment, &Style::new()) + match self.output_mode { + OutputMode::Quiet => Ok(()), + _ => self.write_stderr(fragment, &Style::new()), } } @@ -421,8 +441,8 @@ impl Shell { message: Option<&dyn fmt::Display>, justified: bool, ) -> Result<()> { - match self.verbosity { - Verbosity::Quiet => Ok(()), + match self.output_mode { + OutputMode::Quiet => Ok(()), _ => { self.maybe_err_erase_line(); self.output.message_stderr(status, style, message, justified) diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 68559d081..259e8fee2 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -26,6 +26,7 @@ pub mod errors; pub mod evm; pub mod fs; pub mod provider; +pub mod reports; pub mod retry; pub mod selectors; pub mod serde_helpers; diff --git a/crates/common/src/provider/mod.rs b/crates/common/src/provider/mod.rs index b88d9c00f..450bdd85f 100644 --- a/crates/common/src/provider/mod.rs +++ b/crates/common/src/provider/mod.rs @@ -144,7 +144,7 @@ impl ProviderBuilder { .wrap_err_with(|| format!("invalid provider URL: {url_str:?}")); // Use the final URL string to guess if it's a local URL. - let is_local = url.as_ref().map_or(false, |url| guess_local_url(url.as_str())); + let is_local = url.as_ref().is_ok_and(|url| guess_local_url(url.as_str())); Self { url, diff --git a/crates/common/src/reports.rs b/crates/common/src/reports.rs new file mode 100644 index 000000000..adbdc11bf --- /dev/null +++ b/crates/common/src/reports.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +use crate::shell; + +#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub enum ReportKind { + #[default] + Markdown, + JSON, +} + +/// Determine the kind of report to generate based on the current shell. +pub fn report_kind() -> ReportKind { + if shell::is_json() { + ReportKind::JSON + } else { + ReportKind::Markdown + } +} diff --git a/crates/common/src/retry.rs b/crates/common/src/retry.rs index 7f649c7ed..59ba2055f 100644 --- a/crates/common/src/retry.rs +++ b/crates/common/src/retry.rs @@ -83,6 +83,6 @@ impl Retry { fn handle_err(&mut self, err: Error) { self.retries -= 1; - warn!("erroneous attempt ({} tries remaining): {}", self.retries, err.root_cause()); + let _ = sh_warn!("{} ({} tries remaining)", err.root_cause(), self.retries); } } diff --git a/crates/common/src/selectors.rs b/crates/common/src/selectors.rs index 23a272a2a..cd4e2ffd0 100644 --- a/crates/common/src/selectors.rs +++ b/crates/common/src/selectors.rs @@ -492,24 +492,20 @@ pub struct SelectorImportResponse { impl SelectorImportResponse { /// Print info about the functions which were uploaded or already known pub fn describe(&self) { - self.result - .function - .imported - .iter() - .for_each(|(k, v)| println!("Imported: Function {k}: {v}")); - self.result.event.imported.iter().for_each(|(k, v)| println!("Imported: Event {k}: {v}")); - self.result - .function - .duplicated - .iter() - .for_each(|(k, v)| println!("Duplicated: Function {k}: {v}")); - self.result - .event - .duplicated - .iter() - .for_each(|(k, v)| println!("Duplicated: Event {k}: {v}")); - - println!("Selectors successfully uploaded to OpenChain"); + self.result.function.imported.iter().for_each(|(k, v)| { + let _ = sh_println!("Imported: Function {k}: {v}"); + }); + self.result.event.imported.iter().for_each(|(k, v)| { + let _ = sh_println!("Imported: Event {k}: {v}"); + }); + self.result.function.duplicated.iter().for_each(|(k, v)| { + let _ = sh_println!("Duplicated: Function {k}: {v}"); + }); + self.result.event.duplicated.iter().for_each(|(k, v)| { + let _ = sh_println!("Duplicated: Event {k}: {v}"); + }); + + let _ = sh_println!("Selectors successfully uploaded to OpenChain"); } } @@ -579,6 +575,7 @@ pub fn parse_signatures(tokens: Vec) -> ParsedSignatures { } #[cfg(test)] +#[allow(clippy::disallowed_macros)] #[allow(clippy::needless_return)] mod tests { use super::*; diff --git a/crates/common/src/term.rs b/crates/common/src/term.rs index 2469fff63..b9f7d6cd8 100644 --- a/crates/common/src/term.rs +++ b/crates/common/src/term.rs @@ -3,6 +3,8 @@ use foundry_compilers::{ artifacts::remappings::Remapping, report::{self, BasicStdoutReporter, Reporter}, }; +use foundry_config::find_project_root; +use itertools::Itertools; use semver::Version; use std::{ io, @@ -17,6 +19,8 @@ use std::{ }; use yansi::Paint; +use crate::shell; + /// Some spinners // https://github.com/gernest/wow/blob/master/spin/spinners.go pub static SPINNERS: &[&[&str]] = &[ @@ -72,7 +76,7 @@ impl Spinner { let indicator = self.indicator[self.idx % self.indicator.len()].green(); let indicator = Paint::new(format!("[{indicator}]")).bold(); - print!("\r\x33[2K\r{indicator} {}", self.message); + let _ = sh_print!("\r\x33[2K\r{indicator} {}", self.message); io::stdout().flush().unwrap(); self.idx = self.idx.wrapping_add(1); @@ -121,11 +125,11 @@ impl SpinnerReporter { Ok(SpinnerMsg::Msg(msg)) => { spinner.message(msg); // new line so past messages are not overwritten - println!(); + let _ = sh_println!(); } Ok(SpinnerMsg::Shutdown(ack)) => { // end with a newline - println!(); + let _ = sh_println!(); let _ = ack.send(()); break } @@ -160,6 +164,24 @@ impl Drop for SpinnerReporter { impl Reporter for SpinnerReporter { fn on_compiler_spawn(&self, compiler_name: &str, version: &Version, dirty_files: &[PathBuf]) { + // Verbose message with dirty files displays first to avoid being overlapped + // by the spinner in .tick() which prints repeatedly over the same line. + if shell::verbosity() >= 5 { + let project_root = find_project_root(None); + + self.send_msg(format!( + "Files to compile:\n{}", + dirty_files + .iter() + .map(|path| { + let trimmed_path = path.strip_prefix(&project_root).unwrap_or(path); + format!("- {}", trimmed_path.display()) + }) + .sorted() + .format("\n") + )); + } + self.send_msg(format!( "Compiling {} files with {} {}.{}.{}", dirty_files.len(), diff --git a/crates/common/src/transactions.rs b/crates/common/src/transactions.rs index 4ddef26dd..b319da0d8 100644 --- a/crates/common/src/transactions.rs +++ b/crates/common/src/transactions.rs @@ -1,6 +1,7 @@ //! Wrappers for transactions. use alloy_consensus::{Transaction, TxEnvelope}; +use alloy_eips::eip7702::SignedAuthorization; use alloy_primitives::{Address, TxKind, U256}; use alloy_provider::{ network::{AnyNetwork, ReceiptResponse, TransactionBuilder}, @@ -57,7 +58,7 @@ impl TransactionReceiptWithRevertReason { if let Some(block_hash) = self.receipt.block_hash { match provider - .call(&WithOtherFields::new(transaction.inner.into())) + .call(&transaction.inner.inner.into()) .block(BlockId::Hash(block_hash.into())) .await { @@ -226,6 +227,14 @@ impl TransactionMaybeSigned { Self::Unsigned(tx) => tx.nonce, } } + + pub fn authorization_list(&self) -> Option> { + match self { + Self::Signed { tx, .. } => tx.authorization_list().map(|auths| auths.to_vec()), + Self::Unsigned(tx) => tx.authorization_list.as_deref().map(|auths| auths.to_vec()), + } + .filter(|auths| !auths.is_empty()) + } } impl From for TransactionMaybeSigned { diff --git a/crates/config/README.md b/crates/config/README.md index 182c49ac2..960461eca 100644 --- a/crates/config/README.md +++ b/crates/config/README.md @@ -115,7 +115,7 @@ no_match_contract = "Bar" match_path = "*/Foo*" no_match_path = "*/Bar*" no_match_coverage = "Baz" -# Number of threads to use. Not set or zero specifies the number of logical cores. +# Number of threads to use. Specifying 0 defaults to the number of logical cores. threads = 0 # whether to show test execution progress show_progress = true diff --git a/crates/config/src/compilation.rs b/crates/config/src/compilation.rs new file mode 100644 index 000000000..b4f00b91b --- /dev/null +++ b/crates/config/src/compilation.rs @@ -0,0 +1,115 @@ +use crate::{filter::GlobMatcher, serde_helpers}; +use foundry_compilers::{ + artifacts::{BytecodeHash, EvmVersion}, + multi::{MultiCompilerRestrictions, MultiCompilerSettings}, + settings::VyperRestrictions, + solc::{Restriction, SolcRestrictions}, + RestrictionsWithVersion, +}; +use semver::VersionReq; +use serde::{Deserialize, Serialize}; + +/// Keeps possible overrides for default settings which users may configure to construct additional +/// settings profile. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct SettingsOverrides { + pub name: String, + pub via_ir: Option, + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub evm_version: Option, + pub optimizer: Option, + pub optimizer_runs: Option, + pub bytecode_hash: Option, +} + +impl SettingsOverrides { + /// Applies the overrides to the given settings. + pub fn apply(&self, settings: &mut MultiCompilerSettings) { + if let Some(via_ir) = self.via_ir { + settings.solc.via_ir = Some(via_ir); + } + + if let Some(evm_version) = self.evm_version { + settings.solc.evm_version = Some(evm_version); + settings.vyper.evm_version = Some(evm_version); + } + + if let Some(enabled) = self.optimizer { + settings.solc.optimizer.enabled = Some(enabled); + } + + if let Some(optimizer_runs) = self.optimizer_runs { + settings.solc.optimizer.runs = Some(optimizer_runs); + } + + if let Some(bytecode_hash) = self.bytecode_hash { + if let Some(metadata) = settings.solc.metadata.as_mut() { + metadata.bytecode_hash = Some(bytecode_hash); + } else { + settings.solc.metadata = Some(bytecode_hash.into()); + } + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum RestrictionsError { + #[error("specified both exact and relative restrictions for {0}")] + BothExactAndRelative(&'static str), +} + +/// Restrictions for compilation of given paths. +/// +/// Only purpose of this type is to accept user input to later construct +/// `RestrictionsWithVersion`. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct CompilationRestrictions { + pub paths: GlobMatcher, + pub version: Option, + pub via_ir: Option, + pub bytecode_hash: Option, + + pub min_optimizer_runs: Option, + pub optimizer_runs: Option, + pub max_optimizer_runs: Option, + + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub min_evm_version: Option, + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub evm_version: Option, + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub max_evm_version: Option, +} + +impl TryFrom for RestrictionsWithVersion { + type Error = RestrictionsError; + + fn try_from(value: CompilationRestrictions) -> Result { + let (min_evm, max_evm) = + match (value.min_evm_version, value.max_evm_version, value.evm_version) { + (None, None, Some(exact)) => (Some(exact), Some(exact)), + (min, max, None) => (min, max), + _ => return Err(RestrictionsError::BothExactAndRelative("evm_version")), + }; + let (min_opt, max_opt) = + match (value.min_optimizer_runs, value.max_optimizer_runs, value.optimizer_runs) { + (None, None, Some(exact)) => (Some(exact), Some(exact)), + (min, max, None) => (min, max), + _ => return Err(RestrictionsError::BothExactAndRelative("optimizer_runs")), + }; + Ok(Self { + restrictions: MultiCompilerRestrictions { + solc: SolcRestrictions { + evm_version: Restriction { min: min_evm, max: max_evm }, + via_ir: value.via_ir, + optimizer_runs: Restriction { min: min_opt, max: max_opt }, + bytecode_hash: value.bytecode_hash, + }, + vyper: VyperRestrictions { + evm_version: Restriction { min: min_evm, max: max_evm }, + }, + }, + version: value.version, + }) + } +} diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index da94187db..e4c3b3b45 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -32,8 +32,10 @@ use foundry_compilers::{ Compiler, }, error::SolcError, + multi::{MultiCompilerParsedSource, MultiCompilerRestrictions}, solc::{CliSettings, SolcSettings}, - ArtifactOutput, ConfigurableArtifacts, Project, ProjectPathsConfig, VyperLanguage, + ArtifactOutput, ConfigurableArtifacts, Graph, Project, ProjectPathsConfig, + RestrictionsWithVersion, VyperLanguage, }; use inflector::Inflector; use regex::Regex; @@ -42,6 +44,7 @@ use semver::Version; use serde::{Deserialize, Serialize, Serializer}; use std::{ borrow::Cow, + collections::BTreeMap, fs, path::{Path, PathBuf}, str::FromStr, @@ -117,6 +120,9 @@ pub use zksync::*; mod bind_json; use bind_json::BindJsonConfig; +mod compilation; +use compilation::{CompilationRestrictions, SettingsOverrides}; + /// Foundry configuration /// /// # Defaults @@ -481,6 +487,14 @@ pub struct Config { #[serde(rename = "__warnings", default, skip_serializing)] pub warnings: Vec, + /// Additional settings profiles to use when compiling. + #[serde(default)] + pub additional_compiler_profiles: Vec, + + /// Restrictions on compilation of certain files. + #[serde(default)] + pub compilation_restrictions: Vec, + /// PRIVATE: This structure may grow, As such, constructing this structure should /// _always_ be done using a public constructor or update syntax: /// @@ -872,12 +886,66 @@ impl Config { self.create_project(false, true) } + /// Builds mapping with additional settings profiles. + fn additional_settings( + &self, + base: &MultiCompilerSettings, + ) -> BTreeMap { + let mut map = BTreeMap::new(); + + for profile in &self.additional_compiler_profiles { + let mut settings = base.clone(); + profile.apply(&mut settings); + map.insert(profile.name.clone(), settings); + } + + map + } + + /// Resolves globs and builds a mapping from individual source files to their restrictions + fn restrictions( + &self, + paths: &ProjectPathsConfig, + ) -> Result>, SolcError> + { + let mut map = BTreeMap::new(); + + let graph = Graph::::resolve(paths)?; + let (sources, _) = graph.into_sources(); + + for res in &self.compilation_restrictions { + for source in sources.keys().filter(|path| { + if res.paths.is_match(path) { + true + } else if let Ok(path) = path.strip_prefix(&paths.root) { + res.paths.is_match(path) + } else { + false + } + }) { + let res: RestrictionsWithVersion<_> = + res.clone().try_into().map_err(SolcError::msg)?; + if !map.contains_key(source) { + map.insert(source.clone(), res); + } else { + map.get_mut(source.as_path()).unwrap().merge(res); + } + } + } + + Ok(map) + } + /// Creates a [Project] with the given `cached` and `no_artifacts` flags pub fn create_project(&self, cached: bool, no_artifacts: bool) -> Result { + let settings = self.compiler_settings()?; + let paths = self.project_paths(); let mut builder = Project::builder() .artifacts(self.configured_artifacts_handler()) - .paths(self.project_paths()) - .settings(self.compiler_settings()?) + .additional_settings(self.additional_settings(&settings)) + .restrictions(self.restrictions(&paths)?) + .settings(settings) + .paths(paths) .ignore_error_codes(self.ignored_error_codes.iter().copied().map(Into::into)) .ignore_paths(self.ignored_file_paths.clone()) .set_compiler_severity_filter(if self.deny_warnings { @@ -941,6 +1009,7 @@ impl Config { /// it's missing, unless the `offline` flag is enabled, in which case an error is thrown. /// /// If `solc` is [`SolcReq::Local`] then this will ensure that the path exists. + #[allow(clippy::disallowed_macros)] fn ensure_solc(&self) -> Result, SolcError> { if self.eof { let (tx, rx) = mpsc::channel(); @@ -965,12 +1034,14 @@ impl Config { return match rx.recv_timeout(Duration::from_secs(1)) { Ok(res) => res, Err(RecvTimeoutError::Timeout) => { + // `sh_warn!` is a circular dependency, preventing us from using it here. eprintln!( "{}", yansi::Paint::yellow( "Pulling Docker image for eof-solc, this might take some time..." ) ); + rx.recv().expect("sender dropped") } Err(RecvTimeoutError::Disconnected) => panic!("sender dropped"), @@ -1099,23 +1170,6 @@ impl Config { } /// Returns all configured remappings. - /// - /// **Note:** this will add an additional `/=` remapping here, see - /// [Self::get_source_dir_remapping()] - /// - /// So that - /// - /// ```solidity - /// import "./math/math.sol"; - /// import "contracts/tokens/token.sol"; - /// ``` - /// - /// in `contracts/contract.sol` are resolved to - /// - /// ```text - /// contracts/tokens/token.sol - /// contracts/math/math.sol - /// ``` pub fn get_all_remappings(&self) -> impl Iterator + '_ { self.remappings.iter().map(|m| m.clone().into()) } @@ -2212,7 +2266,7 @@ impl Default for Config { allow_paths: vec![], include_paths: vec![], force: false, - evm_version: EvmVersion::Paris, + evm_version: EvmVersion::Cancun, gas_reports: vec!["*".to_string()], gas_reports_ignore: vec![], gas_reports_include_tests: false, @@ -2306,6 +2360,8 @@ impl Default for Config { eof_version: None, alphanet: false, transaction_timeout: 120, + additional_compiler_profiles: Default::default(), + compilation_restrictions: Default::default(), eof: false, _non_exhaustive: (), zksync: Default::default(), @@ -4947,6 +5003,7 @@ mod tests { } // a test to print the config, mainly used to update the example config in the README + #[allow(clippy::disallowed_macros)] #[test] #[ignore] fn print_config() { diff --git a/crates/config/src/providers/remappings.rs b/crates/config/src/providers/remappings.rs index 48e9c875f..bb4c969e6 100644 --- a/crates/config/src/providers/remappings.rs +++ b/crates/config/src/providers/remappings.rs @@ -1,7 +1,10 @@ -use crate::{foundry_toml_dirs, remappings_from_env_var, remappings_from_newline, Config}; +use crate::{ + foundry_toml_dirs, remappings_from_env_var, remappings_from_newline, utils::get_dir_remapping, + Config, +}; use figment::{ value::{Dict, Map}, - Error, Metadata, Profile, Provider, + Error, Figment, Metadata, Profile, Provider, }; use foundry_compilers::artifacts::remappings::{RelativeRemapping, Remapping}; use std::{ @@ -16,17 +19,35 @@ use std::{ pub struct Remappings { /// Remappings. remappings: Vec, + /// Source, test and script configured project dirs. + /// Remappings of these dirs from libs are ignored. + project_paths: Vec, } impl Remappings { /// Create a new `Remappings` wrapper with an empty vector. pub fn new() -> Self { - Self { remappings: Vec::new() } + Self { remappings: Vec::new(), project_paths: Vec::new() } } /// Create a new `Remappings` wrapper with a vector of remappings. pub fn new_with_remappings(remappings: Vec) -> Self { - Self { remappings } + Self { remappings, project_paths: Vec::new() } + } + + /// Extract project paths that cannot be remapped by dependencies. + pub fn with_figment(mut self, figment: &Figment) -> Self { + let mut add_project_remapping = |path: &str| { + if let Ok(path) = figment.find_value(path) { + if let Some(remapping) = path.into_string().and_then(get_dir_remapping) { + self.project_paths.push(remapping); + } + } + }; + add_project_remapping("src"); + add_project_remapping("test"); + add_project_remapping("script"); + self } /// Filters the remappings vector by name and context. @@ -46,8 +67,8 @@ impl Remappings { } /// Push an element to the remappings vector, but only if it's not already present. - fn push(&mut self, remapping: Remapping) { - if !self.remappings.iter().any(|existing| { + pub fn push(&mut self, remapping: Remapping) { + if self.remappings.iter().any(|existing| { // What we're doing here is filtering for ambiguous paths. For example, if we have // @prb/=node_modules/@prb/ as existing, and // @prb/math/=node_modules/@prb/math/src/ as the one being checked, @@ -57,8 +78,20 @@ impl Remappings { // we want to exclude any conflicting remappings added from libraries. remapping.name.starts_with(&existing.name) && existing.context == remapping.context }) { - self.remappings.push(remapping) - } + return; + }; + + // Ignore remappings of root project src, test or script dir. + // See . + if self + .project_paths + .iter() + .any(|project_path| remapping.name.eq_ignore_ascii_case(&project_path.name)) + { + return; + }; + + self.remappings.push(remapping); } /// Extend the remappings vector, leaving out the remappings that are already present. @@ -198,7 +231,7 @@ impl RemappingsProvider<'_> { fn lib_foundry_toml_remappings(&self) -> impl Iterator + '_ { self.lib_paths .iter() - .map(|p| self.root.join(p)) + .map(|p| if p.is_absolute() { self.root.join("lib") } else { self.root.join(p) }) .flat_map(foundry_toml_dirs) .inspect(|lib| { trace!("find all remappings of nested foundry.toml lib: {:?}", lib); diff --git a/crates/config/src/resolve.rs b/crates/config/src/resolve.rs index 179ecffa2..20606cb11 100644 --- a/crates/config/src/resolve.rs +++ b/crates/config/src/resolve.rs @@ -23,15 +23,23 @@ impl UnresolvedEnvVarError { pub fn try_resolve(&self) -> Result { interpolate(&self.unresolved) } + + fn is_simple(&self) -> bool { + RE_PLACEHOLDER.captures_iter(&self.unresolved).count() <= 1 + } } impl fmt::Display for UnresolvedEnvVarError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "Failed to resolve env var `{}` in `{}`: {}", - self.var, self.unresolved, self.source - ) + write!(f, "environment variable `{}` ", self.var)?; + f.write_str(match self.source { + VarError::NotPresent => "not found", + VarError::NotUnicode(_) => "is not valid unicode", + })?; + if !self.is_simple() { + write!(f, " in `{}`", self.unresolved)?; + } + Ok(()) } } diff --git a/crates/debugger/src/debugger.rs b/crates/debugger/src/debugger.rs index 0e4de437c..469225118 100644 --- a/crates/debugger/src/debugger.rs +++ b/crates/debugger/src/debugger.rs @@ -48,7 +48,7 @@ impl Debugger { let code = match self.try_run_tui() { Ok(ExitReason::CharExit) => 0, Err(e) => { - println!("{e}"); + let _ = sh_eprintln!("{e}"); 1 } }; diff --git a/crates/debugger/src/lib.rs b/crates/debugger/src/lib.rs index aa561973c..67c9ee984 100644 --- a/crates/debugger/src/lib.rs +++ b/crates/debugger/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/doc/Cargo.toml b/crates/doc/Cargo.toml index 00223eb27..95e26df17 100644 --- a/crates/doc/Cargo.toml +++ b/crates/doc/Cargo.toml @@ -15,6 +15,7 @@ workspace = true [dependencies] forge-fmt.workspace = true +foundry-common.workspace = true foundry-compilers.workspace = true foundry-config.workspace = true diff --git a/crates/doc/src/builder.rs b/crates/doc/src/builder.rs index 3ec433c39..02a23ace5 100644 --- a/crates/doc/src/builder.rs +++ b/crates/doc/src/builder.rs @@ -105,7 +105,7 @@ impl DocBuilder { .collect::>(); if sources.is_empty() { - println!("No sources detected at {}", self.sources.display()); + sh_println!("No sources detected at {}", self.sources.display())?; return Ok(()) } diff --git a/crates/doc/src/lib.rs b/crates/doc/src/lib.rs index fd8e4d3ba..174c76600 100644 --- a/crates/doc/src/lib.rs +++ b/crates/doc/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/evm/core/Cargo.toml b/crates/evm/core/Cargo.toml index fe46a1f4f..d428d6a9e 100644 --- a/crates/evm/core/Cargo.toml +++ b/crates/evm/core/Cargo.toml @@ -30,8 +30,9 @@ alloy-primitives = { workspace = true, features = [ "rlp", ] } alloy-provider.workspace = true +alloy-network.workspace = true +alloy-consensus.workspace = true alloy-rpc-types.workspace = true -alloy-serde.workspace = true alloy-sol-types.workspace = true alloy-transport.workspace = true foundry-fork-db.workspace = true @@ -60,6 +61,7 @@ serde_json.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["time", "macros"] } tracing.workspace = true +url.workspace = true [dev-dependencies] foundry-test-utils.workspace = true diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index e0042f9d7..f02e6cfa4 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -7,10 +7,11 @@ use crate::{ utils::{configure_tx_env, configure_tx_req_env, new_evm_with_inspector}, InspectorExt, }; +use alloy_consensus::Transaction as TransactionTrait; use alloy_genesis::GenesisAccount; +use alloy_network::{AnyRpcBlock, AnyTxEnvelope, TransactionResponse}; use alloy_primitives::{keccak256, map::HashMap, uint, Address, B256, U256}; -use alloy_rpc_types::{Block, BlockNumberOrTag, Transaction, TransactionRequest}; -use alloy_serde::WithOtherFields; +use alloy_rpc_types::{BlockNumberOrTag, Transaction, TransactionRequest}; use eyre::Context; use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; pub use foundry_fork_db::{cache::BlockchainDbMeta, BlockchainDb, SharedBackend}; @@ -916,7 +917,7 @@ impl Backend { &self, id: LocalForkId, transaction: B256, - ) -> eyre::Result<(u64, Block>)> { + ) -> eyre::Result<(u64, AnyRpcBlock)> { let fork = self.inner.get_fork_by_id(id)?; let tx = fork.db.db.get_transaction(transaction)?; @@ -927,14 +928,12 @@ impl Backend { // we need to subtract 1 here because we want the state before the transaction // was mined let fork_block = tx_block - 1; - Ok((fork_block, block.inner)) + Ok((fork_block, block)) } else { let block = fork.db.db.get_full_block(BlockNumberOrTag::Latest)?; let number = block.header.number; - let block = block.inner; - Ok((number, block)) } } @@ -948,7 +947,7 @@ impl Backend { env: Env, tx_hash: B256, journaled_state: &mut JournaledState, - ) -> eyre::Result> { + ) -> eyre::Result>> { trace!(?id, ?tx_hash, "replay until transaction"); let persistent_accounts = self.inner.persistent_accounts.clone(); @@ -962,17 +961,17 @@ impl Backend { // System transactions such as on L2s don't contain any pricing info so we skip them // otherwise this would cause reverts if is_known_system_sender(tx.from) || - tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) + tx.transaction_type() == Some(SYSTEM_TRANSACTION_TYPE) { - trace!(tx=?tx.hash, "skipping system transaction"); + trace!(tx=?tx.tx_hash(), "skipping system transaction"); continue; } - if tx.hash == tx_hash { + if tx.tx_hash() == tx_hash { // found the target transaction return Ok(Some(tx.inner)) } - trace!(tx=?tx.hash, "committing transaction"); + trace!(tx=?tx.tx_hash(), "committing transaction"); commit_transaction( &tx.inner, @@ -2193,22 +2192,23 @@ fn is_contract_in_state(journaled_state: &JournaledState, acc: Address) -> bool } /// Updates the env's block with the block's data -fn update_env_block(env: &mut Env, block: &Block) { +fn update_env_block(env: &mut Env, block: &AnyRpcBlock) { env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.miner; + env.block.coinbase = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); env.block.gas_limit = U256::from(block.header.gas_limit); env.block.number = U256::from(block.header.number); - env.block.blob_excess_gas_and_price = - block.header.excess_blob_gas.map(BlobExcessGasAndPrice::new); + if let Some(excess_blob_gas) = block.header.excess_blob_gas { + env.block.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas)); + } } /// Executes the given transaction and commits state changes to the database _and_ the journaled /// state, with an inspector. fn commit_transaction( - tx: &Transaction, + tx: &Transaction, mut env: EnvWithHandlerCfg, journaled_state: &mut JournaledState, fork: &mut Fork, @@ -2218,7 +2218,7 @@ fn commit_transaction( ) -> eyre::Result<()> { // TODO: Remove after https://github.com/foundry-rs/foundry/pull/9131 // if the tx has the blob_versioned_hashes field, we assume it's a Cancun block - if tx.blob_versioned_hashes.is_some() { + if tx.blob_versioned_hashes().is_some() { env.handler_cfg.spec_id = SpecId::CANCUN; } @@ -2250,7 +2250,7 @@ pub fn update_state( persistent_accounts: Option<&HashSet
>, ) -> Result<(), DB::Error> { for (addr, acc) in state.iter_mut() { - if !persistent_accounts.map_or(false, |accounts| accounts.contains(addr)) { + if !persistent_accounts.is_some_and(|accounts| accounts.contains(addr)) { acc.info = db.basic(*addr)?.unwrap_or_default(); for (key, val) in acc.storage.iter_mut() { val.present_value = db.storage(*addr, *key)?; diff --git a/crates/evm/core/src/decode.rs b/crates/evm/core/src/decode.rs index 368693b32..37ff286d0 100644 --- a/crates/evm/core/src/decode.rs +++ b/crates/evm/core/src/decode.rs @@ -192,7 +192,7 @@ impl RevertDecoder { s.push_str(": "); match std::str::from_utf8(data) { Ok(data) => s.push_str(data), - Err(_) => s.push_str(&trimmed_hex(data)), + Err(_) => s.push_str(&hex::encode(data)), } } s diff --git a/crates/evm/core/src/fork/init.rs b/crates/evm/core/src/fork/init.rs index b32fece5a..ae3f9b7a0 100644 --- a/crates/evm/core/src/fork/init.rs +++ b/crates/evm/core/src/fork/init.rs @@ -1,10 +1,8 @@ use crate::utils::apply_chain_and_block_specific_env_changes; +use alloy_consensus::BlockHeader; use alloy_primitives::{Address, U256}; -use alloy_provider::{ - network::{BlockResponse, HeaderResponse}, - Network, Provider, -}; -use alloy_rpc_types::BlockNumberOrTag; +use alloy_provider::{network::BlockResponse, Network, Provider}; +use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind}; use alloy_transport::Transport; use eyre::WrapErr; use foundry_common::NON_ARCHIVE_NODE_WARNING; @@ -30,7 +28,10 @@ pub async fn environment>( let (fork_gas_price, rpc_chain_id, block) = tokio::try_join!( provider.get_gas_price(), provider.get_chain_id(), - provider.get_block_by_number(BlockNumberOrTag::Number(block_number), false) + provider.get_block_by_number( + BlockNumberOrTag::Number(block_number), + BlockTransactionsKind::Hashes + ) )?; let block = if let Some(block) = block { block @@ -66,7 +67,7 @@ pub async fn environment>( block: BlockEnv { number: U256::from(block.header().number()), timestamp: U256::from(block.header().timestamp()), - coinbase: block.header().coinbase(), + coinbase: block.header().beneficiary(), difficulty: block.header().difficulty(), prevrandao: block.header().mix_hash(), basefee: U256::from(block.header().base_fee_per_gas().unwrap_or_default()), diff --git a/crates/evm/core/src/fork/multi.rs b/crates/evm/core/src/fork/multi.rs index 14fa59aaf..112e1eeda 100644 --- a/crates/evm/core/src/fork/multi.rs +++ b/crates/evm/core/src/fork/multi.rs @@ -4,8 +4,9 @@ //! concurrently active pairs at once. use super::CreateFork; +use alloy_consensus::BlockHeader; use alloy_primitives::{map::HashMap, U256}; -use alloy_provider::network::{BlockResponse, HeaderResponse}; +use alloy_provider::network::BlockResponse; use alloy_transport::layers::RetryBackoffService; use foundry_common::provider::{ runtime_transport::RuntimeTransport, ProviderBuilder, RetryProvider, diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index 7a41d0756..9849fd1ce 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -1,13 +1,13 @@ use super::fork::environment; use crate::fork::CreateFork; use alloy_primitives::{Address, B256, U256}; -use alloy_provider::Provider; -use alloy_rpc_types::AnyNetworkBlock; +use alloy_provider::{network::AnyRpcBlock, Provider}; use eyre::WrapErr; use foundry_common::{provider::ProviderBuilder, ALCHEMY_FREE_TIER_CUPS}; use foundry_config::{Chain, Config}; use revm::primitives::{BlockEnv, CfgEnv, TxEnv}; use serde::{Deserialize, Deserializer, Serialize}; +use url::Url; #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct EvmOpts { @@ -86,7 +86,7 @@ impl EvmOpts { pub async fn fork_evm_env( &self, fork_url: impl AsRef, - ) -> eyre::Result<(revm::primitives::Env, AnyNetworkBlock)> { + ) -> eyre::Result<(revm::primitives::Env, AnyRpcBlock)> { let fork_url = fork_url.as_ref(); let provider = ProviderBuilder::new(fork_url) .compute_units_per_second(self.get_compute_units_per_second()) @@ -102,7 +102,13 @@ impl EvmOpts { ) .await .wrap_err_with(|| { - format!("Could not instantiate forked environment with fork url: {fork_url}") + let mut err_msg = "Could not instantiate forked environment".to_string(); + if let Ok(url) = Url::parse(fork_url) { + if let Some(provider) = url.host() { + err_msg.push_str(&format!(" with provider {provider}")); + } + } + err_msg }) } @@ -192,10 +198,6 @@ impl EvmOpts { /// Returns the chain ID from the RPC, if any. pub async fn get_remote_chain_id(&self) -> Option { if let Some(ref url) = self.fork_url { - if url.contains("mainnet") { - trace!(?url, "auto detected mainnet chain"); - return Some(Chain::mainnet()); - } trace!(?url, "retrieving chain via eth_chainId"); let provider = ProviderBuilder::new(url.as_str()) .compute_units_per_second(self.get_compute_units_per_second()) @@ -206,6 +208,14 @@ impl EvmOpts { if let Ok(id) = provider.get_chain_id().await { return Some(Chain::from(id)); } + + // Provider URLs could be of the format `{CHAIN_IDENTIFIER}-mainnet` + // (e.g. Alchemy `opt-mainnet`, `arb-mainnet`), fallback to this method only + // if we're not able to retrieve chain id from `RetryProvider`. + if url.contains("mainnet") { + trace!(?url, "auto detected mainnet chain"); + return Some(Chain::mainnet()); + } } None diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index b3a50fe1f..67f364252 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -3,12 +3,11 @@ use crate::{ backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER, precompiles::ALPHANET_P256, InspectorExt, }; +use alloy_consensus::BlockHeader; use alloy_json_abi::{Function, JsonAbi}; +use alloy_network::AnyTxEnvelope; use alloy_primitives::{Address, Selector, TxKind, U256}; -use alloy_provider::{ - network::{BlockResponse, HeaderResponse}, - Network, -}; +use alloy_provider::{network::BlockResponse, Network}; use alloy_rpc_types::{Transaction, TransactionRequest}; use foundry_config::NamedChain; use foundry_fork_db::DatabaseError; @@ -86,8 +85,10 @@ pub fn get_function<'a>( } /// Configures the env for the given RPC transaction. -pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { - configure_tx_req_env(env, &tx.clone().into()).expect("cannot fail"); +pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { + if let AnyTxEnvelope::Ethereum(tx) = &tx.inner { + configure_tx_req_env(env, &tx.clone().into()).expect("cannot fail"); + } } /// Configures the env for the given RPC transaction request. @@ -244,7 +245,7 @@ pub fn create2_handler_register( if create2_overrides_inner .borrow() .last() - .map_or(false, |(depth, _)| *depth == ctx.evm.journaled_state.depth()) + .is_some_and(|(depth, _)| *depth == ctx.evm.journaled_state.depth()) { let (_, call_inputs) = create2_overrides_inner.borrow_mut().pop().unwrap(); outcome = ctx.external.call_end(&mut ctx.evm, &call_inputs, outcome); diff --git a/crates/evm/coverage/src/analysis.rs b/crates/evm/coverage/src/analysis.rs index e5eda5262..c18ba823b 100644 --- a/crates/evm/coverage/src/analysis.rs +++ b/crates/evm/coverage/src/analysis.rs @@ -50,15 +50,15 @@ impl<'a> ContractVisitor<'a> { let name: String = node.attribute("name").ok_or_else(|| eyre::eyre!("Function has no name"))?; - // TODO(onbjerg): Figure out why we cannot find anchors for the receive function let kind: String = node.attribute("kind").ok_or_else(|| eyre::eyre!("Function has no kind"))?; - if kind == "receive" { - return Ok(()) - } match &node.body { Some(body) => { + // Do not add coverage item for constructors without statements. + if kind == "constructor" && !has_statements(body) { + return Ok(()) + } self.push_item_kind(CoverageItemKind::Function { name }, &node.src); self.visit_block(body) } diff --git a/crates/evm/coverage/src/anchors.rs b/crates/evm/coverage/src/anchors.rs index f42fd1a62..6643524d6 100644 --- a/crates/evm/coverage/src/anchors.rs +++ b/crates/evm/coverage/src/anchors.rs @@ -171,7 +171,7 @@ pub fn find_anchor_branch( /// Calculates whether `element` is within the range of the target `location`. fn is_in_source_range(element: &SourceElement, location: &SourceLocation) -> bool { // Source IDs must match. - let source_ids_match = element.index().map_or(false, |a| a as usize == location.source_id); + let source_ids_match = element.index().is_some_and(|a| a as usize == location.source_id); if !source_ids_match { return false; } diff --git a/crates/evm/coverage/src/lib.rs b/crates/evm/coverage/src/lib.rs index 220ab6b41..ad4ab53e3 100644 --- a/crates/evm/coverage/src/lib.rs +++ b/crates/evm/coverage/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; @@ -171,6 +174,14 @@ impl CoverageReport { pub struct HitMaps(pub HashMap); impl HitMaps { + pub fn merge_opt(a: &mut Option, b: Option) { + match (a, b) { + (_, None) => {} + (a @ None, Some(b)) => *a = Some(b), + (Some(a), Some(b)) => a.merge(b), + } + } + pub fn merge(&mut self, other: Self) { for (code_hash, hit_map) in other.0 { if let Some(HitMap { hits: extra_hits, .. }) = self.insert(code_hash, hit_map) { @@ -237,7 +248,7 @@ impl HitMap { if let (Some(len1), Some(len2)) = (len1, len2) { let len = std::cmp::max(len1.0, len2.0); let ok = hm1.bytecode.0[..*len] == hm2.bytecode.0[..*len]; - println!("consistent_bytecode: {}, {}, {}, {}", ok, len1.0, len2.0, len); + let _ = sh_println!("consistent_bytecode: {}, {}, {}, {}", ok, len1.0, len2.0, len); return ok; } true diff --git a/crates/evm/evm/src/executors/fuzz/mod.rs b/crates/evm/evm/src/executors/fuzz/mod.rs index 8c8d7ff69..8a479c019 100644 --- a/crates/evm/evm/src/executors/fuzz/mod.rs +++ b/crates/evm/evm/src/executors/fuzz/mod.rs @@ -128,11 +128,7 @@ impl FuzzedExecutor { data.logs.extend(case.logs); } - // Collect and merge coverage if `forge snapshot` context. - match &mut data.coverage { - Some(prev) => prev.merge(case.coverage.unwrap()), - opt => *opt = case.coverage, - } + HitMaps::merge_opt(&mut data.coverage, case.coverage); data.deprecated_cheatcodes = case.deprecated_cheatcodes; diff --git a/crates/evm/evm/src/executors/invariant/mod.rs b/crates/evm/evm/src/executors/invariant/mod.rs index b4a46d775..0fcb9dac8 100644 --- a/crates/evm/evm/src/executors/invariant/mod.rs +++ b/crates/evm/evm/src/executors/invariant/mod.rs @@ -203,10 +203,7 @@ impl InvariantTest { /// Merge current collected coverage with the new coverage from last fuzzed call. pub fn merge_coverage(&self, new_coverage: Option) { - match &mut self.execution_data.borrow_mut().coverage { - Some(prev) => prev.merge(new_coverage.unwrap()), - opt => *opt = new_coverage, - } + HitMaps::merge_opt(&mut self.execution_data.borrow_mut().coverage, new_coverage); } /// Update metrics for a fuzzed selector, extracted from tx details. diff --git a/crates/evm/evm/src/executors/invariant/replay.rs b/crates/evm/evm/src/executors/invariant/replay.rs index 969f1587f..36192a6d6 100644 --- a/crates/evm/evm/src/executors/invariant/replay.rs +++ b/crates/evm/evm/src/executors/invariant/replay.rs @@ -48,16 +48,10 @@ pub fn replay_run( tx.call_details.calldata.clone(), U256::ZERO, )?; + logs.extend(call_result.logs); traces.push((TraceKind::Execution, call_result.traces.clone().unwrap())); - - if let Some(new_coverage) = call_result.coverage { - if let Some(old_coverage) = coverage { - *coverage = Some(std::mem::take(old_coverage).merged(new_coverage)); - } else { - *coverage = Some(new_coverage); - } - } + HitMaps::merge_opt(coverage, call_result.coverage); // Identify newly generated contracts, if they exist. ided_contracts diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 4e276d823..07b425ee7 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -32,8 +32,8 @@ use revm::{ db::{DatabaseCommit, DatabaseRef}, interpreter::{return_ok, InstructionResult}, primitives::{ - BlockEnv, Bytecode, Env, EnvWithHandlerCfg, ExecutionResult, Output, ResultAndState, - SpecId, TxEnv, TxKind, + AuthorizationList, BlockEnv, Bytecode, Env, EnvWithHandlerCfg, ExecutionResult, Output, + ResultAndState, SignedAuthorization, SpecId, TxEnv, TxKind, }, Database, }; @@ -410,6 +410,21 @@ impl Executor { self.call_with_env(env) } + /// Performs a raw call to an account on the current state of the VM with an EIP-7702 + /// authorization list. + pub fn call_raw_with_authorization( + &mut self, + from: Address, + to: Address, + calldata: Bytes, + value: U256, + authorization_list: Vec, + ) -> eyre::Result { + let mut env = self.build_test_env(from, to.into(), calldata, value); + env.tx.authorization_list = Some(AuthorizationList::Signed(authorization_list)); + self.call_with_env(env) + } + /// Performs a raw call to an account on the current state of the VM. pub fn transact_raw( &mut self, @@ -784,6 +799,12 @@ impl std::ops::DerefMut for DeployResult { } } +impl From for RawCallResult { + fn from(d: DeployResult) -> Self { + d.raw + } +} + /// The result of a raw call. #[derive(Debug)] pub struct RawCallResult { @@ -851,6 +872,23 @@ impl Default for RawCallResult { } impl RawCallResult { + /// Unpacks an EVM result. + pub fn from_evm_result(r: Result) -> eyre::Result<(Self, Option)> { + match r { + Ok(r) => Ok((r, None)), + Err(EvmError::Execution(e)) => Ok((e.raw, Some(e.reason))), + Err(e) => Err(e.into()), + } + } + + /// Unpacks an execution result. + pub fn from_execution_result(r: Result) -> (Self, Option) { + match r { + Ok(r) => (r, None), + Err(e) => (e.raw, Some(e.reason)), + } + } + /// Converts the result of the call into an `EvmError`. pub fn into_evm_error(self, rd: Option<&RevertDecoder>) -> EvmError { if let Some(reason) = SkipReason::decode(&self.result) { diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index e44ec61b9..0fb7ca7f5 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -123,6 +123,8 @@ pub struct CallTraceDecoder { pub labels: HashMap, /// Contract addresses that have a receive function. pub receive_contracts: Vec
, + /// Contract addresses that have fallback functions, mapped to function sigs. + pub fallback_contracts: HashMap>, /// All known functions. pub functions: HashMap>, @@ -193,6 +195,7 @@ impl CallTraceDecoder { (POINT_EVALUATION, "PointEvaluation".to_string()), ]), receive_contracts: Default::default(), + fallback_contracts: Default::default(), functions: hh_funcs() .chain( @@ -229,6 +232,7 @@ impl CallTraceDecoder { } self.receive_contracts.clear(); + self.fallback_contracts.clear(); } /// Identify unknown addresses in the specified call trace using the specified identifier. @@ -330,6 +334,14 @@ impl CallTraceDecoder { if abi.receive.is_some() { self.receive_contracts.push(*address); } + + if abi.fallback.is_some() { + let mut functions_sig = vec![]; + for function in abi.functions() { + functions_sig.push(function.signature()); + } + self.fallback_contracts.insert(*address, functions_sig); + } } } @@ -392,9 +404,18 @@ impl CallTraceDecoder { }; }; + // If traced contract is a fallback contract, check if it has the decoded function. + // If not, then replace call data signature with `fallback`. + let mut call_data = self.decode_function_input(trace, func); + if let Some(fallback_functions) = self.fallback_contracts.get(&trace.address) { + if !fallback_functions.contains(&func.signature()) { + call_data.signature = "fallback()".into(); + } + } + DecodedCallTrace { label, - call_data: Some(self.decode_function_input(trace, func)), + call_data: Some(call_data), return_data: self.decode_function_output(trace, functions), } } else { diff --git a/crates/evm/traces/src/identifier/etherscan.rs b/crates/evm/traces/src/identifier/etherscan.rs index 2af6fbb59..96e4b6966 100644 --- a/crates/evm/traces/src/identifier/etherscan.rs +++ b/crates/evm/traces/src/identifier/etherscan.rs @@ -65,7 +65,7 @@ impl EtherscanIdentifier { // filter out vyper files .filter(|(_, metadata)| !metadata.is_vyper()) .map(|(address, metadata)| async move { - println!("Compiling: {} {address}", metadata.contract_name); + sh_println!("Compiling: {} {address}", metadata.contract_name)?; let root = tempfile::tempdir()?; let root_path = root.path(); let project = etherscan_project(metadata, root_path)?; diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index dd4a89664..18136c481 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/fmt/src/comments.rs b/crates/fmt/src/comments.rs index 90054f132..e3fb79043 100644 --- a/crates/fmt/src/comments.rs +++ b/crates/fmt/src/comments.rs @@ -112,7 +112,7 @@ impl CommentWithMetadata { // line has something // check if the last comment after code was a postfix comment if last_comment - .map_or(false, |last| last.loc.end() > code_end && !last.is_prefix()) + .is_some_and(|last| last.loc.end() > code_end && !last.is_prefix()) { // get the indent size of the next item of code let next_indent_len = src[comment.loc().end()..] diff --git a/crates/fmt/src/formatter.rs b/crates/fmt/src/formatter.rs index 6bb814e23..8f52d9e25 100644 --- a/crates/fmt/src/formatter.rs +++ b/crates/fmt/src/formatter.rs @@ -88,7 +88,7 @@ struct Context { impl Context { /// Returns true if the current function context is the constructor pub(crate) fn is_constructor_function(&self) -> bool { - self.function.as_ref().map_or(false, |f| matches!(f.ty, FunctionTy::Constructor)) + self.function.as_ref().is_some_and(|f| matches!(f.ty, FunctionTy::Constructor)) } } @@ -341,7 +341,7 @@ impl<'a, W: Write> Formatter<'a, W> { _ => stmt.loc().start(), }; - self.find_next_line(start_from).map_or(false, |loc| loc >= end_at) + self.find_next_line(start_from).is_some_and(|loc| loc >= end_at) } } } @@ -560,7 +560,7 @@ impl<'a, W: Write> Formatter<'a, W> { fn write_doc_block_line(&mut self, comment: &CommentWithMetadata, line: &str) -> Result<()> { if line.trim().starts_with('*') { let line = line.trim().trim_start_matches('*'); - let needs_space = line.chars().next().map_or(false, |ch| !ch.is_whitespace()); + let needs_space = line.chars().next().is_some_and(|ch| !ch.is_whitespace()); write!(self.buf(), " *{}", if needs_space { " " } else { "" })?; self.write_comment_line(comment, line)?; self.write_whitespace_separator(true)?; @@ -1945,7 +1945,7 @@ impl Visitor for Formatter<'_, W> { )?; // EOF newline - if self.last_char().map_or(true, |char| char != '\n') { + if self.last_char() != Some('\n') { writeln!(self.buf())?; } @@ -3259,7 +3259,7 @@ impl Visitor for Formatter<'_, W> { // we can however check if the contract `is` the `base`, this however also does // not cover all cases - let is_contract_base = self.context.contract.as_ref().map_or(false, |contract| { + let is_contract_base = self.context.contract.as_ref().is_some_and(|contract| { contract.base.iter().any(|contract_base| { contract_base .name @@ -3280,7 +3280,7 @@ impl Visitor for Formatter<'_, W> { let mut base_or_modifier = self.visit_to_chunk(loc.start(), Some(loc.end()), base)?; let is_lowercase = - base_or_modifier.content.chars().next().map_or(false, |c| c.is_lowercase()); + base_or_modifier.content.chars().next().is_some_and(|c| c.is_lowercase()); if is_lowercase && base_or_modifier.content.ends_with("()") { base_or_modifier.content.truncate(base_or_modifier.content.len() - 2); } diff --git a/crates/forge/bin/cmd/bind_json.rs b/crates/forge/bin/cmd/bind_json.rs index c6a052836..de7a5a7a7 100644 --- a/crates/forge/bin/cmd/bind_json.rs +++ b/crates/forge/bin/cmd/bind_json.rs @@ -11,7 +11,7 @@ use foundry_compilers::{ multi::{MultiCompilerLanguage, MultiCompilerParsedSource}, project::ProjectCompiler, solc::SolcLanguage, - CompilerSettings, Graph, Project, + Graph, Project, }; use foundry_config::Config; use itertools::Itertools; @@ -72,7 +72,7 @@ impl BindJsonArgs { // We only generate bindings for a single Solidity version to avoid conflicts. let mut sources = graph // resolve graph into mapping language -> version -> sources - .into_sources_by_version(project.offline, &project.locked_versions, &project.compiler)? + .into_sources_by_version(&project)? .0 .into_iter() // we are only interested in Solidity sources @@ -81,7 +81,7 @@ impl BindJsonArgs { .1 .into_iter() // For now, we are always picking the latest version. - .max_by(|(v1, _), (v2, _)| v1.cmp(v2)) + .max_by(|(v1, _, _), (v2, _, _)| v1.cmp(v2)) .unwrap() .1; @@ -229,7 +229,7 @@ impl PreprocessedState { fn compile(self) -> Result { let Self { sources, target_path, mut project, config } = self; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::ast_output_selection(); }); diff --git a/crates/forge/bin/cmd/build.rs b/crates/forge/bin/cmd/build.rs index 0b10d1416..0821cb1c7 100644 --- a/crates/forge/bin/cmd/build.rs +++ b/crates/forge/bin/cmd/build.rs @@ -91,12 +91,15 @@ impl BuildArgs { // Collect sources to compile if build subdirectories specified. let mut files = vec![]; - if let Some(paths) = self.paths { + if let Some(paths) = &self.paths { for path in paths { - files.extend(source_files_iter( - path.as_path(), - MultiCompilerLanguage::FILE_EXTENSIONS, - )); + let joined = project.root().join(path); + let path = if joined.exists() { &joined } else { path }; + files.extend(source_files_iter(path, MultiCompilerLanguage::FILE_EXTENSIONS)); + } + + if files.is_empty() { + eyre::bail!("No source files found in specified build paths.") } } @@ -106,12 +109,11 @@ impl BuildArgs { .print_names(self.names) .print_sizes(self.sizes) .ignore_eip_3860(self.ignore_eip_3860) - .quiet(format_json) .bail(!format_json); let output = compiler.compile(&project)?; - if format_json { + if format_json && !self.names && !self.sizes { sh_println!("{}", serde_json::to_string_pretty(&output.output())?)?; } @@ -120,19 +122,35 @@ impl BuildArgs { // no way to return a default from either branch. Ok(output) Ok(()) } else { - let format_json = shell::is_json(); let zk_project = foundry_zksync_compiler::config_create_project(&config, config.cache, false)?; + + // Collect sources to compile if build subdirectories specified. + let mut files = vec![]; + if let Some(paths) = &self.paths { + for path in paths { + let joined = zk_project.root().join(path); + let path = if joined.exists() { &joined } else { path }; + files.extend(source_files_iter(path, MultiCompilerLanguage::FILE_EXTENSIONS)); + } + + if files.is_empty() { + eyre::bail!("No source files found in specified build paths.") + } + } + + let format_json = shell::is_json(); let zk_compiler = ProjectCompiler::new() + .files(files) .print_names(self.names) .print_sizes(self.sizes) .zksync_sizes() - .quiet(format_json) .bail(!format_json); let zk_output = zk_compiler.zksync_compile(&zk_project)?; - if format_json { - println!("{}", serde_json::to_string_pretty(&zk_output.output())?); + + if format_json && !self.names && !self.sizes { + sh_println!("{}", serde_json::to_string_pretty(&zk_output.output())?)?; } // TODO(zk): We cannot return the zk_output as it does not match the concrete type for diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 0b0ec171b..f5d62b671 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -1,5 +1,6 @@ -use clap::{ArgAction, Parser, Subcommand, ValueHint}; +use clap::{Parser, Subcommand, ValueHint}; use eyre::Result; +use foundry_common::shell; use foundry_compilers::{artifacts::EvmVersion, Graph}; use foundry_config::Config; use semver::Version; @@ -51,44 +52,25 @@ pub struct ResolveArgs { /// Skip files that match the given regex pattern. #[arg(long, short, value_name = "REGEX")] skip: Option, - - /// Verbosity of the output. - /// - /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). - /// - /// Verbosity levels: - /// - 0: Print compiler versions. - /// - 1: Print compiler version and source paths. - /// - 2: Print compiler version, source paths and max supported EVM version of the compiler. - #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count, help_heading = "Display options")] - pub verbosity: u8, - - /// Print as JSON. - #[arg(long, short, help_heading = "Display options")] - json: bool, } impl ResolveArgs { pub fn run(self) -> Result<()> { - let Self { root, skip, verbosity, json } = self; + let Self { root, skip } = self; let root = root.unwrap_or_else(|| PathBuf::from(".")); let config = Config::load_with_root(&root); let project = config.project()?; let graph = Graph::resolve(&project.paths)?; - let (sources, _) = graph.into_sources_by_version( - project.offline, - &project.locked_versions, - &project.compiler, - )?; + let (sources, _) = graph.into_sources_by_version(&project)?; let mut output: BTreeMap> = BTreeMap::new(); for (language, sources) in sources { let mut versions_with_paths: Vec = sources .iter() - .map(|(version, sources)| { + .map(|(version, sources, _)| { let paths: Vec = sources .iter() .filter_map(|(path_file, _)| { @@ -110,7 +92,7 @@ impl ResolveArgs { }) .collect(); - let evm_version = if verbosity > 1 { + let evm_version = if shell::verbosity() > 1 { Some( EvmVersion::default() .normalize_version_solc(version) @@ -132,7 +114,7 @@ impl ResolveArgs { if !versions_with_paths.is_empty() { // Clear paths if verbosity is 0, performed only after filtering to avoid being // skipped. - if verbosity == 0 { + if shell::verbosity() == 0 { versions_with_paths.iter_mut().for_each(|version| version.paths.clear()); } @@ -140,20 +122,20 @@ impl ResolveArgs { } } - if json { + if shell::is_json() { sh_println!("{}", serde_json::to_string(&output)?)?; return Ok(()); } for (language, compilers) in &output { - match verbosity { + match shell::verbosity() { 0 => sh_println!("{language}:")?, _ => sh_println!("{language}:\n")?, } for resolved_compiler in compilers { let version = &resolved_compiler.version; - match verbosity { + match shell::verbosity() { 0 => sh_println!("- {version}")?, _ => { if let Some(evm) = &resolved_compiler.evm_version { @@ -164,7 +146,7 @@ impl ResolveArgs { } } - if verbosity > 0 { + if shell::verbosity() > 0 { let paths = &resolved_compiler.paths; for (idx, path) in paths.iter().enumerate() { if idx == paths.len() - 1 { @@ -176,7 +158,7 @@ impl ResolveArgs { } } - if verbosity == 0 { + if shell::verbosity() == 0 { sh_println!()? } } diff --git a/crates/forge/bin/cmd/config.rs b/crates/forge/bin/cmd/config.rs index 652c5a10f..36f4d1731 100644 --- a/crates/forge/bin/cmd/config.rs +++ b/crates/forge/bin/cmd/config.rs @@ -2,7 +2,7 @@ use super::build::BuildArgs; use clap::Parser; use eyre::Result; use foundry_cli::utils::LoadConfig; -use foundry_common::evm::EvmArgs; +use foundry_common::{evm::EvmArgs, shell}; use foundry_config::fix::fix_tomls; foundry_config::impl_figment_convert!(ConfigArgs, opts, evm_opts); @@ -14,10 +14,6 @@ pub struct ConfigArgs { #[arg(long)] basic: bool, - /// Print currently set config values as JSON. - #[arg(long)] - json: bool, - /// Attempt to fix any configuration warnings. #[arg(long)] fix: bool, @@ -46,12 +42,12 @@ impl ConfigArgs { let s = if self.basic { let config = config.into_basic(); - if self.json { + if shell::is_json() { serde_json::to_string_pretty(&config)? } else { config.to_string_pretty()? } - } else if self.json { + } else if shell::is_json() { serde_json::to_string_pretty(&config)? } else { config.to_string_pretty()? diff --git a/crates/forge/bin/cmd/coverage.rs b/crates/forge/bin/cmd/coverage.rs index 9cc8a69e6..c4b6451dc 100644 --- a/crates/forge/bin/cmd/coverage.rs +++ b/crates/forge/bin/cmd/coverage.rs @@ -16,7 +16,7 @@ use forge::{ use foundry_cli::utils::{LoadConfig, STATIC_FUZZ_SEED}; use foundry_common::{compile::ProjectCompiler, fs}; use foundry_compilers::{ - artifacts::{sourcemap::SourceMap, CompactBytecode, CompactDeployedBytecode}, + artifacts::{sourcemap::SourceMap, CompactBytecode, CompactDeployedBytecode, SolcLanguage}, Artifact, ArtifactId, Project, ProjectCompileOutput, }; use foundry_config::{Config, SolcReq}; @@ -95,23 +95,12 @@ impl CoverageArgs { // Set up the project let mut project = config.create_project(false, false)?; if self.ir_minimum { - // TODO: How to detect solc version if the user does not specify a solc version in - // config case1: specify local installed solc ? - // case2: multiple solc versions used and auto_detect_solc == true - if let Some(SolcReq::Version(version)) = &config.solc { - if *version < Version::new(0, 8, 13) { - return Err(eyre::eyre!( - "viaIR with minimum optimization is only available in Solidity 0.8.13 and above." - )); - } - } - // print warning message sh_warn!("{}", concat!( - "Warning! \"--ir-minimum\" flag enables viaIR with minimum optimization, \ + "`--ir-minimum` enables viaIR with minimum optimization, \ which can result in inaccurate source mappings.\n", "Only use this flag as a workaround if you are experiencing \"stack too deep\" errors.\n", - "Note that \"viaIR\" is only available in Solidity 0.8.13 and above.\n", + "Note that \"viaIR\" is production ready since Solidity 0.8.13 and above.\n", "See more: https://github.com/foundry-rs/foundry/issues/3357", ))?; @@ -120,7 +109,15 @@ impl CoverageArgs { // And also in new releases of solidity: // https://github.com/ethereum/solidity/issues/13972#issuecomment-1628632202 project.settings.solc.settings = - project.settings.solc.settings.with_via_ir_minimum_optimization() + project.settings.solc.settings.with_via_ir_minimum_optimization(); + let version = if let Some(SolcReq::Version(version)) = &config.solc { + version + } else { + // Sanitize settings for solc 0.8.4 if version cannot be detected. + // See . + &Version::new(0, 8, 4) + }; + project.settings.solc.settings.sanitize(version, SolcLanguage::Solidity); } else { project.settings.solc.optimizer.disable(); project.settings.solc.optimizer.runs = None; diff --git a/crates/forge/bin/cmd/create.rs b/crates/forge/bin/cmd/create.rs index 3721f2726..c5c34d78b 100644 --- a/crates/forge/bin/cmd/create.rs +++ b/crates/forge/bin/cmd/create.rs @@ -1,7 +1,7 @@ use alloy_chains::Chain; use alloy_dyn_abi::{DynSolValue, JsonAbiExt, Specifier}; use alloy_json_abi::{Constructor, JsonAbi}; -use alloy_network::{AnyNetwork, EthereumWallet, TransactionBuilder}; +use alloy_network::{AnyNetwork, EthereumWallet, Network, ReceiptResponse, TransactionBuilder}; use alloy_primitives::{hex, Address, Bytes}; use alloy_provider::{PendingTransactionError, Provider, ProviderBuilder}; use alloy_rpc_types::{AnyTransactionReceipt, TransactionRequest}; @@ -14,7 +14,7 @@ use alloy_zksync::{ }; use clap::{Parser, ValueHint}; use eyre::{Context, Result}; -use forge_verify::{zk_provider::CompilerVerificationContext, RetryArgs}; +use forge_verify::{zk_provider::CompilerVerificationContext, RetryArgs, VerifierArgs, VerifyArgs}; use foundry_cli::{ opts::{CoreBuildArgs, EthereumOpts, EtherscanOpts, TransactionOpts}, utils::{self, read_constructor_args_file, remove_contract, remove_zk_contract, LoadConfig}, @@ -26,7 +26,7 @@ use foundry_common::{ }; use foundry_compilers::{ artifacts::BytecodeObject, info::ContractInfo, utils::canonicalize, - zksync::artifact_output::zk::ZkContractArtifact, + zksync::artifact_output::zk::ZkContractArtifact, ArtifactId, }; use foundry_config::{ figment::{ @@ -102,7 +102,7 @@ pub struct CreateArgs { eth: EthereumOpts, #[command(flatten)] - pub verifier: forge_verify::VerifierArgs, + pub verifier: VerifierArgs, #[command(flatten)] retry: RetryArgs, @@ -152,7 +152,8 @@ impl CreateArgs { let zk_compiler = ProjectCompiler::new().files([target_path.clone()]); let mut zk_output = zk_compiler.zksync_compile(&zk_project)?; - let artifact = remove_zk_contract(&mut zk_output, &target_path, &self.contract.name)?; + let (artifact, id) = + remove_zk_contract(&mut zk_output, &target_path, &self.contract.name)?; let ZkContractArtifact { bytecode, factory_dependencies, abi, .. } = artifact; @@ -265,6 +266,7 @@ impl CreateArgs { chain_id, sender, config.transaction_timeout, + id, zk_data, ) .await @@ -285,6 +287,7 @@ impl CreateArgs { chain_id, deployer, config.transaction_timeout, + id, zk_data, ) .await @@ -297,9 +300,9 @@ impl CreateArgs { project.find_contract_path(&self.contract.name)? }; - let mut output = compile::compile_target(&target_path, &project, shell::is_json())?; + let output = compile::compile_target(&target_path, &project, shell::is_json())?; - let (abi, bin, _) = remove_contract(&mut output, &target_path, &self.contract.name)?; + let (abi, bin, id) = remove_contract(output, &target_path, &self.contract.name)?; let bin = match bin.object { BytecodeObject::Bytecode(_) => bin.object, @@ -339,8 +342,17 @@ impl CreateArgs { if self.unlocked { // Deploy with unlocked account let sender = self.eth.wallet.from.expect("required"); - self.deploy(abi, bin, params, provider, chain_id, sender, config.transaction_timeout) - .await + self.deploy( + abi, + bin, + params, + provider, + chain_id, + sender, + config.transaction_timeout, + id, + ) + .await } else { // Deploy with signer let signer = self.eth.wallet.signer().await?; @@ -348,8 +360,17 @@ impl CreateArgs { let provider = ProviderBuilder::<_, _, AnyNetwork>::default() .wallet(EthereumWallet::new(signer)) .on_provider(provider); - self.deploy(abi, bin, params, provider, chain_id, deployer, config.transaction_timeout) - .await + self.deploy( + abi, + bin, + params, + provider, + chain_id, + deployer, + config.transaction_timeout, + id, + ) + .await } } @@ -368,13 +389,14 @@ impl CreateArgs { &self, constructor_args: Option, chain: u64, + id: &ArtifactId, ) -> Result<()> { // NOTE: this does not represent the same `VerifyArgs` that would be sent after deployment, // since we don't know the address yet. - let mut verify = forge_verify::VerifyArgs { + let mut verify = VerifyArgs { address: Default::default(), contract: Some(self.contract.clone()), - compiler_version: None, + compiler_version: Some(id.version.to_string()), constructor_args, constructor_args_path: None, num_of_optimizations: None, @@ -395,6 +417,7 @@ impl CreateArgs { evm_version: self.opts.compiler.evm_version, show_standard_json_input: self.show_standard_json_input, guess_constructor_args: false, + compilation_profile: Some(id.profile.to_string()), zksync: self.opts.compiler.zk.enabled(), }; @@ -425,6 +448,7 @@ impl CreateArgs { chain: u64, deployer_address: Address, timeout: u64, + id: ArtifactId, ) -> Result<()> { let bin = bin.into_bytes().unwrap_or_else(|| { panic!("no bytecode found in bin object for {}", self.contract.name) @@ -501,7 +525,7 @@ impl CreateArgs { constructor_args = Some(hex::encode_prefixed(encoded_args)); } - self.verify_preflight_check(constructor_args.clone(), chain).await?; + self.verify_preflight_check(constructor_args.clone(), chain, &id).await?; } // Deploy the actual contract @@ -532,10 +556,10 @@ impl CreateArgs { } else { None }; - let verify = forge_verify::VerifyArgs { + let verify = VerifyArgs { address, contract: Some(self.contract), - compiler_version: None, + compiler_version: Some(id.version.to_string()), constructor_args, constructor_args_path: None, num_of_optimizations, @@ -553,9 +577,10 @@ impl CreateArgs { evm_version: self.opts.compiler.evm_version, show_standard_json_input: self.show_standard_json_input, guess_constructor_args: false, + compilation_profile: Some(id.profile.to_string()), zksync: self.opts.compiler.zk.enabled(), }; - println!("Waiting for {} to detect contract deployment...", verify.verifier.verifier); + sh_println!("Waiting for {} to detect contract deployment...", verify.verifier.verifier)?; verify.run().await } @@ -570,6 +595,7 @@ impl CreateArgs { chain: u64, deployer_address: Address, timeout: u64, + id: ArtifactId, zk_data: ZkSyncData, ) -> Result<()> { let bin = bin.into_bytes().unwrap_or_else(|| { @@ -593,7 +619,7 @@ impl CreateArgs { zk_data.factory_deps.clone().into_iter().map(|dep| dep.into()).collect(), ); if let Some(paymaster_params) = zk_data.paymaster_params { - deployer.tx.set_paymaster(paymaster_params); + deployer.tx.set_paymaster_params(paymaster_params); } deployer.tx.set_from(deployer_address); deployer.tx.set_chain_id(chain); @@ -654,24 +680,25 @@ impl CreateArgs { constructor_args = Some(hex::encode_prefixed(encoded_args)); } - self.verify_preflight_check(constructor_args.clone(), chain).await?; + self.verify_preflight_check(constructor_args.clone(), chain, &id).await?; } // Deploy the actual contract let (deployed_contract, receipt) = deployer.send_with_receipt().await?; + let tx_hash = receipt.transaction_hash(); let address = deployed_contract; if shell::is_json() { let output = json!({ "deployer": deployer_address.to_string(), "deployedTo": address.to_string(), - "transactionHash": receipt.transaction_hash + "transactionHash": tx_hash }); sh_println!("{output}")?; } else { sh_println!("Deployer: {deployer_address}")?; sh_println!("Deployed to: {address}")?; - sh_println!("Transaction hash: {:?}", receipt.transaction_hash)?; + sh_println!("Transaction hash: {:?}", tx_hash)?; }; if !self.verify { @@ -685,7 +712,7 @@ impl CreateArgs { } else { None }; - let verify = forge_verify::VerifyArgs { + let verify = VerifyArgs { address, contract: Some(self.contract), compiler_version: None, @@ -706,6 +733,7 @@ impl CreateArgs { evm_version: self.opts.compiler.evm_version, show_standard_json_input: self.show_standard_json_input, guess_constructor_args: false, + compilation_profile: None, //TODO(zk): provide comp profile zksync: self.opts.compiler.zk.enabled(), }; sh_println!("Waiting for {} to detect contract deployment...", verify.verifier.verifier)?; @@ -908,7 +936,7 @@ where /// and the corresponding [`AnyReceipt`]. pub async fn send_with_receipt( self, - ) -> Result<(Address, AnyTransactionReceipt), ContractDeploymentError> { + ) -> Result<(Address, ::ReceiptResponse), ContractDeploymentError> { let receipt = self .client .borrow() @@ -919,7 +947,7 @@ where .await?; let address = - receipt.contract_address.ok_or(ContractDeploymentError::ContractNotDeployed)?; + receipt.contract_address().ok_or(ContractDeploymentError::ContractNotDeployed)?; Ok((address, receipt)) } @@ -1080,7 +1108,11 @@ where .into(); tx = tx - .zksync_deploy(zk_data.bytecode.clone(), constructor_args, zk_data.factory_deps.clone()) + .with_create_params( + zk_data.bytecode.clone(), + constructor_args, + zk_data.factory_deps.clone(), + ) .map_err(|_| ContractDeploymentError::TransactionBuildError)?; Ok(ZkDeployer { diff --git a/crates/forge/bin/cmd/eip712.rs b/crates/forge/bin/cmd/eip712.rs index 2c125b7d0..5a7a3a229 100644 --- a/crates/forge/bin/cmd/eip712.rs +++ b/crates/forge/bin/cmd/eip712.rs @@ -2,14 +2,10 @@ use clap::{Parser, ValueHint}; use eyre::{Ok, OptionExt, Result}; use foundry_cli::{opts::CoreBuildArgs, utils::LoadConfig}; use foundry_common::compile::ProjectCompiler; -use foundry_compilers::{ - artifacts::{ - output_selection::OutputSelection, - visitor::{Visitor, Walk}, - ContractDefinition, EnumDefinition, SourceUnit, StructDefinition, TypeDescriptions, - TypeName, - }, - CompilerSettings, +use foundry_compilers::artifacts::{ + output_selection::OutputSelection, + visitor::{Visitor, Walk}, + ContractDefinition, EnumDefinition, SourceUnit, StructDefinition, TypeDescriptions, TypeName, }; use std::{collections::BTreeMap, fmt::Write, path::PathBuf}; @@ -31,7 +27,7 @@ impl Eip712Args { let config = self.try_load_config_emit_warnings()?; let mut project = config.create_project(false, true)?; let target_path = dunce::canonicalize(self.target_path)?; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::ast_output_selection(); }); @@ -126,7 +122,9 @@ impl Resolver { /// Returns `None` if struct contains any fields that are not supported by EIP-712 (e.g. /// mappings or function pointers). pub fn resolve_struct_eip712(&self, id: usize) -> Result> { - self.resolve_eip712_inner(id, &mut Default::default(), true, None) + let mut subtypes = BTreeMap::new(); + subtypes.insert(self.structs[&id].name.clone(), id); + self.resolve_eip712_inner(id, &mut subtypes, true, None) } fn resolve_eip712_inner( @@ -205,8 +203,17 @@ impl Resolver { // If we've already seen struct with this ID, just use assigned name. if let Some((name, _)) = subtypes.iter().find(|(_, id)| **id == def.id) { name.clone() - // Otherwise, try assigning a new name. } else { + // Otherwise, assign new name. + let mut i = 0; + let mut name = def.name.clone(); + while subtypes.contains_key(&name) { + i += 1; + name = format!("{}_{i}", def.name); + } + + subtypes.insert(name.clone(), def.id); + // iterate over members to check if they are resolvable and to populate subtypes for member in &def.members { if self.resolve_type( @@ -218,14 +225,6 @@ impl Resolver { return Ok(None) } } - let mut i = 0; - let mut name = def.name.clone(); - while subtypes.contains_key(&name) { - i += 1; - name = format!("{}_{i}", def.name); - } - - subtypes.insert(name.clone(), def.id); name }; diff --git a/crates/forge/bin/cmd/init.rs b/crates/forge/bin/cmd/init.rs index 94056c3db..f6df102fd 100644 --- a/crates/forge/bin/cmd/init.rs +++ b/crates/forge/bin/cmd/init.rs @@ -88,7 +88,7 @@ impl InitArgs { } } else { // if target is not empty - if root.read_dir().map_or(false, |mut i| i.next().is_some()) { + if root.read_dir().is_ok_and(|mut i| i.next().is_some()) { if !force { eyre::bail!( "Cannot run `init` on a non-empty directory.\n\ diff --git a/crates/forge/bin/cmd/install.rs b/crates/forge/bin/cmd/install.rs index ca5608ca3..60fc7f299 100644 --- a/crates/forge/bin/cmd/install.rs +++ b/crates/forge/bin/cmd/install.rs @@ -101,10 +101,8 @@ impl DependencyInstallOpts { let _ = sh_println!("Missing dependencies found. Installing now...\n"); self.no_commit = true; if self.install(config, Vec::new()).is_err() { - let _ = sh_warn!( - "{}", - "Your project has missing dependencies that could not be installed." - ); + let _ = + sh_warn!("Your project has missing dependencies that could not be installed."); } true } else { diff --git a/crates/forge/bin/cmd/soldeer.rs b/crates/forge/bin/cmd/soldeer.rs index 56b8c31f3..b2c9a77f1 100644 --- a/crates/forge/bin/cmd/soldeer.rs +++ b/crates/forge/bin/cmd/soldeer.rs @@ -1,6 +1,5 @@ use clap::Parser; use eyre::Result; - use soldeer_commands::Command; // CLI arguments for `forge soldeer`. diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 61ba99ca7..d1d510bc4 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -5,7 +5,7 @@ use clap::{Parser, ValueHint}; use eyre::{Context, OptionExt, Result}; use forge::{ decode::decode_console_logs, - gas_report::{GasReport, GasReportKind}, + gas_report::GasReport, multi_runner::matches_contract, result::{SuiteResult, TestOutcome, TestStatus}, traces::{ @@ -17,13 +17,13 @@ use forge::{ MultiContractRunner, MultiContractRunnerBuilder, TestFilter, TestOptions, TestOptionsBuilder, }; use foundry_cli::{ - opts::CoreBuildArgs, + opts::{CoreBuildArgs, GlobalOpts}, utils::{self, LoadConfig}, }; -use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell}; +use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell, TestFunctionExt}; use foundry_compilers::{ artifacts::output_selection::OutputSelection, - compilers::{multi::MultiCompilerLanguage, CompilerSettings, Language}, + compilers::{multi::MultiCompilerLanguage, Language}, utils::source_files_iter, ProjectCompileOutput, }; @@ -66,6 +66,10 @@ foundry_config::merge_impl_figment_convert!(TestArgs, opts, evm_opts); #[derive(Clone, Debug, Parser)] #[command(next_help_heading = "Test options")] pub struct TestArgs { + // Include global options for users of this struct. + #[command(flatten)] + pub global: GlobalOpts, + /// The contract file you want to test, it's a shortcut for --match-path. #[arg(value_hint = ValueHint::FilePath)] pub path: Option, @@ -146,11 +150,6 @@ pub struct TestArgs { #[arg(long)] pub fuzz_input_file: Option, - /// Max concurrent threads to use. - /// Default value is the number of available CPUs. - #[arg(long, short = 'j', visible_alias = "jobs")] - pub threads: Option, - /// Show test execution progress. #[arg(long)] pub show_progress: bool, @@ -201,7 +200,7 @@ impl TestArgs { filter: &ProjectPathsAwareFilter, ) -> Result> { let mut project = config.create_project(true, true)?; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::common_output_selection(["abi".to_string()]); }); @@ -273,13 +272,6 @@ impl TestArgs { // Merge all configs. let (mut config, mut evm_opts) = self.load_config_and_evm_opts_emit_warnings()?; - // Set number of max threads to execute tests. - // If not specified then the number of threads determined by rayon will be used. - if let Some(test_threads) = config.threads { - trace!(target: "forge::test", "execute tests with {} max threads", test_threads); - rayon::ThreadPoolBuilder::new().num_threads(test_threads).build_global()?; - } - // Explicitly enable isolation for gas reports for more correct gas accounting. if self.gas_report { evm_opts.isolate = true; @@ -604,7 +596,6 @@ impl TestArgs { config.gas_reports.clone(), config.gas_reports_ignore.clone(), config.gas_reports_include_tests, - if shell::is_json() { GasReportKind::JSON } else { GasReportKind::Markdown }, ) }); @@ -919,10 +910,6 @@ impl Provider for TestArgs { dict.insert("show_progress".to_string(), true.into()); } - if let Some(threads) = self.threads { - dict.insert("threads".to_string(), threads.into()); - } - Ok(Map::from([(Config::selected_profile(), dict)])) } } @@ -932,7 +919,7 @@ fn list(runner: MultiContractRunner, filter: &ProjectPathsAwareFilter) -> Result let results = runner.list(filter); if shell::is_json() { - println!("{}", serde_json::to_string(&results)?); + sh_println!("{}", serde_json::to_string(&results)?)?; } else { for (file, contracts) in results.iter() { sh_println!("{file}")?; @@ -959,10 +946,12 @@ fn persist_run_failures(config: &Config, outcome: &TestOutcome) { let mut filter = String::new(); let mut failures = outcome.failures().peekable(); while let Some((test_name, _)) = failures.next() { - if let Some(test_match) = test_name.split('(').next() { - filter.push_str(test_match); - if failures.peek().is_some() { - filter.push('|'); + if test_name.is_any_test() { + if let Some(test_match) = test_name.split("(").next() { + filter.push_str(test_match); + if failures.peek().is_some() { + filter.push('|'); + } } } } @@ -1015,56 +1004,34 @@ fn junit_xml_report(results: &BTreeMap, verbosity: u8) -> R #[cfg(test)] mod tests { - use crate::opts::{Forge, ForgeSubcommand}; - use super::*; use foundry_config::{Chain, InvariantConfig}; use foundry_test_utils::forgetest_async; #[test] fn watch_parse() { - let args = match Forge::parse_from(["foundry-cli", "test", "-vw"]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = TestArgs::parse_from(["foundry-cli", "-vw"]); assert!(args.watch.watch.is_some()); } #[test] fn fuzz_seed() { - let args = match Forge::parse_from(["foundry-cli", "test", "--fuzz-seed", "0x10"]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = TestArgs::parse_from(["foundry-cli", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } // #[test] fn fuzz_seed_exists() { - let args = match Forge::parse_from([ - "foundry-cli", - "test", - "-vvv", - "--gas-report", - "--fuzz-seed", - "0x10", - ]) - .cmd - { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = + TestArgs::parse_from(["foundry-cli", "-vvv", "--gas-report", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } #[test] fn extract_chain() { let test = |arg: &str, expected: Chain| { - let args = match Forge::parse_from(["foundry-cli", "test", arg]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args = TestArgs::parse_from(["foundry-cli", arg]); assert_eq!(args.evm_opts.env.chain, Some(expected)); let (config, evm_opts) = args.load_config_and_evm_opts().unwrap(); assert_eq!(config.chain, Some(expected)); @@ -1118,19 +1085,12 @@ contract FooBarTest is DSTest { ) .unwrap(); - let args = match Forge::parse_from([ + let args = TestArgs::parse_from([ "foundry-cli", - "test", "--gas-report", "--root", &prj.root().to_string_lossy(), - ]) - .cmd - { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; - + ]); let outcome = args.run().await.unwrap(); let gas_report = outcome.gas_report.unwrap(); diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index 9e4bb5499..9f1eba4b5 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -35,7 +35,7 @@ fn run() -> Result<()> { utils::enable_paint(); let args = Forge::parse(); - args.shell.shell().set(); + args.global.init()?; init_execution_context(&args.cmd); match args.cmd { diff --git a/crates/forge/bin/opts.rs b/crates/forge/bin/opts.rs index 39bc89e63..380cb61d4 100644 --- a/crates/forge/bin/opts.rs +++ b/crates/forge/bin/opts.rs @@ -8,7 +8,7 @@ use crate::cmd::{ use clap::{Parser, Subcommand, ValueHint}; use forge_script::ScriptArgs; use forge_verify::{VerifyArgs, VerifyBytecodeArgs, VerifyCheckArgs}; -use foundry_cli::opts::ShellOpts; +use foundry_cli::opts::GlobalOpts; use std::path::PathBuf; const VERSION_MESSAGE: &str = concat!( @@ -29,11 +29,12 @@ const VERSION_MESSAGE: &str = concat!( next_display_order = None, )] pub struct Forge { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(subcommand)] pub cmd: ForgeSubcommand, - - #[clap(flatten)] - pub shell: ShellOpts, } #[derive(Subcommand)] diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index 1de748107..c6ef4a120 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -6,32 +6,24 @@ use crate::{ }; use alloy_primitives::map::HashSet; use comfy_table::{presets::ASCII_MARKDOWN, *}; -use foundry_common::{calc, TestFunctionExt}; +use foundry_common::{ + calc, + reports::{report_kind, ReportKind}, + TestFunctionExt, +}; use foundry_evm::traces::CallKind; use foundry_evm_abi::HARDHAT_CONSOLE_ADDRESS; use serde::{Deserialize, Serialize}; use serde_json::json; use std::{collections::BTreeMap, fmt::Display}; -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub enum GasReportKind { - Markdown, - JSON, -} - -impl Default for GasReportKind { - fn default() -> Self { - Self::Markdown - } -} - /// Represents the gas report for a set of contracts. #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct GasReport { /// Whether to report any contracts. report_any: bool, /// What kind of report to generate. - report_type: GasReportKind, + report_kind: ReportKind, /// Contracts to generate the report for. report_for: HashSet, /// Contracts to ignore when generating the report. @@ -48,13 +40,18 @@ impl GasReport { report_for: impl IntoIterator, ignore: impl IntoIterator, include_tests: bool, - report_kind: GasReportKind, ) -> Self { let report_for = report_for.into_iter().collect::>(); let ignore = ignore.into_iter().collect::>(); let report_any = report_for.is_empty() || report_for.contains("*"); - let report_type = report_kind; - Self { report_any, report_type, report_for, ignore, include_tests, ..Default::default() } + Self { + report_any, + report_kind: report_kind(), + report_for, + ignore, + include_tests, + ..Default::default() + } } /// Whether the given contract should be reported. @@ -95,28 +92,30 @@ impl GasReport { return; } - // Only include top-level calls which account for calldata and base (21.000) cost. - // Only include Calls and Creates as only these calls are isolated in inspector. - if trace.depth > 1 && - (trace.kind == CallKind::Call || - trace.kind == CallKind::Create || - trace.kind == CallKind::Create2 || - trace.kind == CallKind::EOFCreate) - { - return; - } - let Some(name) = decoder.contracts.get(&node.trace.address) else { return }; let contract_name = name.rsplit(':').next().unwrap_or(name); if !self.should_report(contract_name) { return; } + let contract_info = self.contracts.entry(name.to_string()).or_default(); + let is_create_call = trace.kind.is_any_create(); + + // Record contract deployment size. + if is_create_call { + trace!(contract_name, "adding create size info"); + contract_info.size = trace.data.len(); + } + + // Only include top-level calls which account for calldata and base (21.000) cost. + // Only include Calls and Creates as only these calls are isolated in inspector. + if trace.depth > 1 && (trace.kind == CallKind::Call || is_create_call) { + return; + } let decoded = || decoder.decode_function(&node.trace); - let contract_info = self.contracts.entry(name.to_string()).or_default(); - if trace.kind.is_any_create() { + if is_create_call { trace!(contract_name, "adding create gas info"); contract_info.gas = trace.gas_used; contract_info.size = trace.data.len(); @@ -164,8 +163,8 @@ impl GasReport { impl Display for GasReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - match self.report_type { - GasReportKind::Markdown => { + match self.report_kind { + ReportKind::Markdown => { for (name, contract) in &self.contracts { if contract.functions.is_empty() { trace!(name, "gas report contract without functions"); @@ -177,7 +176,7 @@ impl Display for GasReport { writeln!(f, "\n")?; } } - GasReportKind::JSON => { + ReportKind::JSON => { writeln!(f, "{}", &self.format_json_output())?; } } diff --git a/crates/forge/src/multi_runner.rs b/crates/forge/src/multi_runner.rs index 2356d9b99..d195b7e96 100644 --- a/crates/forge/src/multi_runner.rs +++ b/crates/forge/src/multi_runner.rs @@ -501,7 +501,7 @@ impl MultiContractRunnerBuilder { contracts: deployable_contracts, evm_opts, env, - evm_spec: self.evm_spec.unwrap_or(SpecId::MERGE), + evm_spec: self.evm_spec.unwrap_or(SpecId::CANCUN), sender: self.sender, revert_decoder, fork: self.fork, diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index 60c07472e..7f02db577 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -13,7 +13,7 @@ use foundry_common::{evm::Breakpoints, get_contract_name, get_file_name, shell}; use foundry_evm::{ coverage::HitMaps, decode::SkipReason, - executors::{invariant::InvariantMetrics, EvmError, RawCallResult}, + executors::{invariant::InvariantMetrics, RawCallResult}, fuzz::{CounterExample, FuzzCase, FuzzFixtures, FuzzTestResult}, traces::{CallTraceArena, CallTraceDecoder, TraceKind, Traces}, }; @@ -469,7 +469,7 @@ impl TestResult { /// Creates a new test result starting from test setup results. pub fn new(setup: TestSetup) -> Self { Self { - labeled_addresses: setup.labeled_addresses, + labeled_addresses: setup.labels, logs: setup.logs, traces: setup.traces, coverage: setup.coverage, @@ -490,7 +490,7 @@ impl TestResult { logs: setup.logs, traces: setup.traces, coverage: setup.coverage, - labeled_addresses: setup.labeled_addresses, + labeled_addresses: setup.labels, ..Default::default() } } @@ -651,21 +651,17 @@ impl TestResult { format!("{self} {name} {}", self.kind.report()) } - /// Function to merge logs, addresses, traces and coverage from a call result into test result. - pub fn merge_call_result(&mut self, call_result: &RawCallResult) { - self.logs.extend(call_result.logs.clone()); - self.labeled_addresses.extend(call_result.labels.clone()); - self.traces.extend(call_result.traces.clone().map(|traces| (TraceKind::Execution, traces))); - self.merge_coverages(call_result.coverage.clone()); + /// Merges the given raw call result into `self`. + pub fn extend(&mut self, call_result: RawCallResult) { + self.logs.extend(call_result.logs); + self.labeled_addresses.extend(call_result.labels); + self.traces.extend(call_result.traces.map(|traces| (TraceKind::Execution, traces))); + self.merge_coverages(call_result.coverage); } - /// Function to merge given coverage in current test result coverage. + /// Merges the given coverage result into `self`. pub fn merge_coverages(&mut self, other_coverage: Option) { - let old_coverage = std::mem::take(&mut self.coverage); - self.coverage = match (old_coverage, other_coverage) { - (Some(old_coverage), Some(other)) => Some(old_coverage.merged(other)), - (a, b) => a.or(b), - }; + HitMaps::merge_opt(&mut self.coverage, other_coverage); } } @@ -747,77 +743,39 @@ impl TestKind { } } +/// The result of a test setup. +/// +/// Includes the deployment of the required libraries and the test contract itself, and the call to +/// the `setUp()` function. #[derive(Clone, Debug, Default)] pub struct TestSetup { - /// The address at which the test contract was deployed + /// The address at which the test contract was deployed. pub address: Address, - /// The logs emitted during setup + /// Defined fuzz test fixtures. + pub fuzz_fixtures: FuzzFixtures, + + /// The logs emitted during setup. pub logs: Vec, - /// Call traces of the setup + /// Addresses labeled during setup. + pub labels: AddressHashMap, + /// Call traces of the setup. pub traces: Traces, - /// Addresses labeled during setup - pub labeled_addresses: AddressHashMap, - /// The reason the setup failed, if it did - pub reason: Option, - /// Coverage info during setup + /// Coverage info during setup. pub coverage: Option, - /// Defined fuzz test fixtures - pub fuzz_fixtures: FuzzFixtures, + + /// The reason the setup failed, if it did. + pub reason: Option, } impl TestSetup { - pub fn from_evm_error_with( - error: EvmError, - mut logs: Vec, - mut traces: Traces, - mut labeled_addresses: AddressHashMap, - ) -> Self { - match error { - EvmError::Execution(err) => { - // force the tracekind to be setup so a trace is shown. - traces.extend(err.raw.traces.map(|traces| (TraceKind::Setup, traces))); - logs.extend(err.raw.logs); - labeled_addresses.extend(err.raw.labels); - Self::failed_with(logs, traces, labeled_addresses, err.reason) - } - e => Self::failed_with( - logs, - traces, - labeled_addresses, - format!("failed to deploy contract: {e}"), - ), - } - } - - pub fn success( - address: Address, - logs: Vec, - traces: Traces, - labeled_addresses: AddressHashMap, - coverage: Option, - fuzz_fixtures: FuzzFixtures, - ) -> Self { - Self { address, logs, traces, labeled_addresses, reason: None, coverage, fuzz_fixtures } - } - - pub fn failed_with( - logs: Vec, - traces: Traces, - labeled_addresses: AddressHashMap, - reason: String, - ) -> Self { - Self { - address: Address::ZERO, - logs, - traces, - labeled_addresses, - reason: Some(reason), - coverage: None, - fuzz_fixtures: FuzzFixtures::default(), - } - } - pub fn failed(reason: String) -> Self { Self { reason: Some(reason), ..Default::default() } } + + pub fn extend(&mut self, raw: RawCallResult, trace_kind: TraceKind) { + self.logs.extend(raw.logs); + self.labels.extend(raw.labels); + self.traces.extend(raw.traces.map(|traces| (trace_kind, traces))); + HitMaps::merge_opt(&mut self.coverage, raw.coverage); + } } diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index 474b2c72b..094ce9e67 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -24,7 +24,7 @@ use foundry_evm::{ invariant::{ check_sequence, replay_error, replay_run, InvariantExecutor, InvariantFuzzError, }, - CallResult, EvmError, ExecutionErr, Executor, ITest, RawCallResult, + CallResult, EvmError, Executor, ITest, RawCallResult, }, fuzz::{ fixture_name, @@ -88,32 +88,30 @@ impl ContractRunner<'_> { self.executor.set_balance(self.sender, U256::MAX)?; self.executor.set_balance(CALLER, U256::MAX)?; - // We set the nonce of the deployer accounts to 1 to get the same addresses as DappTools + // We set the nonce of the deployer accounts to 1 to get the same addresses as DappTools. self.executor.set_nonce(self.sender, 1)?; - // Deploy libraries + // Deploy libraries. self.executor.set_balance(LIBRARY_DEPLOYER, U256::MAX)?; - let mut logs = Vec::new(); - let mut traces = Vec::with_capacity(self.libs_to_deploy.len()); + let mut result = TestSetup::default(); for code in self.libs_to_deploy.iter() { - match self.executor.deploy( + let deploy_result = self.executor.deploy( LIBRARY_DEPLOYER, code.clone(), U256::ZERO, Some(self.revert_decoder), - ) { - Ok(d) => { - logs.extend(d.raw.logs); - traces.extend(d.raw.traces.map(|traces| (TraceKind::Deployment, traces))); - } - Err(e) => { - return Ok(TestSetup::from_evm_error_with(e, logs, traces, Default::default())) - } + ); + let (raw, reason) = RawCallResult::from_evm_result(deploy_result.map(Into::into))?; + result.extend(raw, TraceKind::Deployment); + if reason.is_some() { + result.reason = reason; + return Ok(result); } } let address = self.sender.create(self.executor.get_nonce(self.sender)?); + result.address = address; // NOTE(zk): the test contract is set here instead of where upstream does it as // the test contract address needs to be retrieved in order to skip // zkEVM mode for the creation of the test address (and for calls to it later). @@ -124,21 +122,21 @@ impl ContractRunner<'_> { self.executor.set_balance(address, self.initial_balance)?; // Deploy the test contract - match self.executor.deploy( + let deploy_result = self.executor.deploy( self.sender, self.contract.bytecode.clone(), U256::ZERO, Some(self.revert_decoder), - ) { - Ok(d) => { - logs.extend(d.raw.logs); - traces.extend(d.raw.traces.map(|traces| (TraceKind::Deployment, traces))); - d.address - } - Err(e) => { - return Ok(TestSetup::from_evm_error_with(e, logs, traces, Default::default())) - } - }; + ); + if let Ok(dr) = &deploy_result { + debug_assert_eq!(dr.address, address); + } + let (raw, reason) = RawCallResult::from_evm_result(deploy_result.map(Into::into))?; + result.extend(raw, TraceKind::Deployment); + if reason.is_some() { + result.reason = reason; + return Ok(result); + } // Reset `self.sender`s, `CALLER`s and `LIBRARY_DEPLOYER`'s balance to the initial balance. self.executor.set_balance(self.sender, self.initial_balance)?; @@ -161,51 +159,15 @@ impl ContractRunner<'_> { } // Optionally call the `setUp` function - let result = if call_setup { + if call_setup { trace!("calling setUp"); let res = self.executor.setup(None, address, Some(self.revert_decoder)); - let (setup_logs, setup_traces, labeled_addresses, reason, coverage) = match res { - Ok(RawCallResult { traces, labels, logs, coverage, .. }) => { - trace!(%address, "successfully called setUp"); - (logs, traces, labels, None, coverage) - } - Err(EvmError::Execution(err)) => { - let ExecutionErr { - raw: RawCallResult { traces, labels, logs, coverage, .. }, - reason, - } = *err; - (logs, traces, labels, Some(format!("setup failed: {reason}")), coverage) - } - Err(err) => ( - Vec::new(), - None, - HashMap::default(), - Some(format!("setup failed: {err}")), - None, - ), - }; - traces.extend(setup_traces.map(|traces| (TraceKind::Setup, traces))); - logs.extend(setup_logs); - - TestSetup { - address, - logs, - traces, - labeled_addresses, - reason, - coverage, - fuzz_fixtures: self.fuzz_fixtures(address), - } - } else { - TestSetup::success( - address, - logs, - traces, - Default::default(), - None, - self.fuzz_fixtures(address), - ) - }; + let (raw, reason) = RawCallResult::from_evm_result(res)?; + result.extend(raw, TraceKind::Setup); + result.reason = reason; + } + + result.fuzz_fixtures = self.fuzz_fixtures(address); Ok(result) } @@ -313,7 +275,7 @@ impl ContractRunner<'_> { warnings, ) } - let call_after_invariant = after_invariant_fns.first().map_or(false, |after_invariant_fn| { + let call_after_invariant = after_invariant_fns.first().is_some_and(|after_invariant_fn| { let match_sig = after_invariant_fn.name == "afterInvariant"; if !match_sig { warnings.push(format!( @@ -722,11 +684,13 @@ impl ContractRunner<'_> { // Apply before test configured calldata. match executor.to_mut().transact_raw(self.sender, address, calldata, U256::ZERO) { Ok(call_result) => { + let reverted = call_result.reverted; + // Merge tx result traces in unit test result. - test_result.merge_call_result(&call_result); + test_result.extend(call_result); // To continue unit test execution the call should not revert. - if call_result.reverted { + if reverted { return Err(test_result.single_fail(None)) } } diff --git a/crates/forge/tests/cli/build.rs b/crates/forge/tests/cli/build.rs index 2cf60fb46..43ded2945 100644 --- a/crates/forge/tests/cli/build.rs +++ b/crates/forge/tests/cli/build.rs @@ -79,10 +79,24 @@ forgetest!(initcode_size_exceeds_limit, |prj, cmd| { ... | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |--------------|------------------|-------------------|--------------------|---------------------| -| HugeContract | 202 | 49,359 | 24,374 | -207 | +| HugeContract | 194 | 49,344 | 24,382 | -192 | ... "# ]); + + cmd.forge_fuse().args(["build", "--sizes", "--json"]).assert_failure().stdout_eq( + str![[r#" +{ + "HugeContract":{ + "runtime_size":194, + "init_size":49344, + "runtime_margin":24382, + "init_margin":-192 + } +} +"#]] + .is_json(), + ); }); forgetest!(initcode_size_limit_can_be_ignored, |prj, cmd| { @@ -92,10 +106,27 @@ forgetest!(initcode_size_limit_can_be_ignored, |prj, cmd| { ... | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |--------------|------------------|-------------------|--------------------|---------------------| -| HugeContract | 202 | 49,359 | 24,374 | -207 | +| HugeContract | 194 | 49,344 | 24,382 | -192 | ... "# ]); + + cmd.forge_fuse() + .args(["build", "--sizes", "--ignore-eip-3860", "--json"]) + .assert_success() + .stdout_eq( + str![[r#" +{ + "HugeContract": { + "runtime_size": 194, + "init_size": 49344, + "runtime_margin": 24382, + "init_margin": -192 + } +} +"#]] + .is_json(), + ); }); // tests build output is as expected @@ -115,10 +146,24 @@ forgetest_init!(build_sizes_no_forge_std, |prj, cmd| { ... | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |----------|------------------|-------------------|--------------------|---------------------| -| Counter | 247 | 277 | 24,329 | 48,875 | +| Counter | 236 | 263 | 24,340 | 48,889 | ... "# ]); + + cmd.forge_fuse().args(["build", "--sizes", "--json"]).assert_success().stdout_eq( + str![[r#" +{ + "Counter": { + "runtime_size": 247, + "init_size": 277, + "runtime_margin": 24329, + "init_margin": 48875 + } +} +"#]] + .is_json(), + ); }); // tests build output is as expected in zksync mode diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index e14014155..7a376678f 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -34,12 +34,17 @@ Options: -h, --help Print help (see a summary with '-h') + -j, --threads + Number of threads to use. Specifying 0 defaults to the number of logical cores + + [aliases: jobs] + -V, --version Print version Display options: --color - Log messages coloring + The color of the log messages Possible values: - auto: Intelligently guess whether to use color output (default) @@ -52,8 +57,18 @@ Display options: -q, --quiet Do not print log messages - --verbose - Use verbose output + -v, --verbosity... + Verbosity level of the log messages. + + Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + + Depending on the context the verbosity levels have different meanings. + + For example, the verbosity levels of the EVM are: + - 2 (-vv): Print logs for all tests. + - 3 (-vvv): Print execution traces for failing tests. + - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + - 5 (-vvvvv): Print execution and setup traces for all tests. Find more information in the book: http://book.getfoundry.sh/reference/forge/forge.html @@ -1573,25 +1588,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1601,48 +1616,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1657,25 +1672,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1685,48 +1700,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1741,25 +1756,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1769,48 +1784,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1832,25 +1847,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1860,48 +1875,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1923,9 +1938,9 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | ... "#]]); @@ -1935,16 +1950,16 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } } @@ -1961,9 +1976,9 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1973,16 +1988,16 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -2002,9 +2017,9 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | ... "#]]); @@ -2014,16 +2029,16 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } } @@ -2049,17 +2064,17 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -2069,32 +2084,32 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -2116,17 +2131,17 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | ... "#]]); @@ -2136,32 +2151,32 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } } @@ -2194,25 +2209,25 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]) .stderr_eq(str![[r#" @@ -2231,48 +2246,48 @@ Warning: ContractThree is listed in both 'gas_reports' and 'gas_reports_ignore'. { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -2337,12 +2352,12 @@ contract CounterTest is DSTest { | src/Counter.sol:Counter contract | | | | | | |----------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 101137 | 250 | | | | | +| 99711 | 240 | | | | | | Function Name | min | avg | median | max | # calls | -| a | 2261 | 2261 | 2261 | 2261 | 1 | -| b | 2305 | 2305 | 2305 | 2305 | 1 | -| setNumber(int256) | 23648 | 33604 | 33604 | 43560 | 2 | -| setNumber(uint256) | 23604 | 33560 | 33560 | 43516 | 2 | +| a | 2259 | 2259 | 2259 | 2259 | 1 | +| b | 2304 | 2304 | 2304 | 2304 | 1 | +| setNumber(int256) | 23646 | 33602 | 33602 | 43558 | 2 | +| setNumber(uint256) | 23601 | 33557 | 33557 | 43513 | 2 | ... "#]]); cmd.forge_fuse().arg("test").arg("--gas-report").arg("--json").assert_success().stdout_eq( @@ -2351,37 +2366,37 @@ contract CounterTest is DSTest { { "contract": "src/Counter.sol:Counter", "deployment": { - "gas": 101137, - "size": 250 + "gas": 99711, + "size": 240 }, "functions": { "a()": { "calls": 1, - "min": 2261, - "mean": 2261, - "median": 2261, - "max": 2261 + "min": 2259, + "mean": 2259, + "median": 2259, + "max": 2259 }, "b()": { "calls": 1, - "min": 2305, - "mean": 2305, - "median": 2305, - "max": 2305 + "min": 2304, + "mean": 2304, + "median": 2304, + "max": 2304 }, "setNumber(int256)": { "calls": 2, - "min": 23648, - "mean": 33604, - "median": 33604, - "max": 43560 + "min": 23646, + "mean": 33602, + "median": 33602, + "max": 43558 }, "setNumber(uint256)": { "calls": 2, - "min": 23604, - "mean": 33560, - "median": 33560, - "max": 43516 + "min": 23601, + "mean": 33557, + "median": 33557, + "max": 43513 } } } @@ -2391,6 +2406,276 @@ contract CounterTest is DSTest { ); }); +// +forgetest_init!(gas_report_with_fallback, |prj, cmd| { + prj.add_test( + "DelegateProxyTest.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract ProxiedContract { + uint256 public amount; + + function deposit(uint256 aba) external { + amount = amount * 2; + } + + function deposit() external { + } +} + +contract DelegateProxy { + address internal implementation; + + constructor(address counter) { + implementation = counter; + } + + function deposit() external { + } + + fallback() external payable { + address addr = implementation; + + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), addr, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } +} + +contract GasReportFallbackTest is Test { + function test_fallback_gas_report() public { + ProxiedContract proxied = ProxiedContract(address(new DelegateProxy(address(new ProxiedContract())))); + proxied.deposit(100); + proxied.deposit(); + } +} +"#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_fallback_gas_report", "-vvvv", "--gas-report"]) + .assert_success() + .stdout_eq(str![[r#" +... +Ran 1 test for test/DelegateProxyTest.sol:GasReportFallbackTest +[PASS] test_fallback_gas_report() ([GAS]) +Traces: + [327404] GasReportFallbackTest::test_fallback_gas_report() + ├─ [104475] → new ProxiedContract@[..] + │ └─ ← [Return] 236 bytes of code + ├─ [107054] → new DelegateProxy@[..] + │ └─ ← [Return] 135 bytes of code + ├─ [29384] DelegateProxy::fallback(100) + │ ├─ [3316] ProxiedContract::deposit(100) [delegatecall] + │ │ └─ ← [Stop] + │ └─ ← [Return] + ├─ [21159] DelegateProxy::deposit() + │ └─ ← [Stop] + └─ ← [Stop] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] +| test/DelegateProxyTest.sol:DelegateProxy contract | | | | | | +|---------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 107054 | 300 | | | | | +| Function Name | min | avg | median | max | # calls | +| deposit | 21159 | 21159 | 21159 | 21159 | 1 | +| fallback | 29384 | 29384 | 29384 | 29384 | 1 | + + +| test/DelegateProxyTest.sol:ProxiedContract contract | | | | | | +|-----------------------------------------------------|-----------------|------|--------|------|---------| +| Deployment Cost | Deployment Size | | | | | +| 104475 | 263 | | | | | +| Function Name | min | avg | median | max | # calls | +| deposit | 3316 | 3316 | 3316 | 3316 | 1 | +... + +"#]]); + + cmd.forge_fuse() + .args(["test", "--mt", "test_fallback_gas_report", "--gas-report", "--json"]) + .assert_success() + .stdout_eq( + str![[r#" +[ + { + "contract": "test/DelegateProxyTest.sol:DelegateProxy", + "deployment": { + "gas": 107054, + "size": 300 + }, + "functions": { + "deposit()": { + "calls": 1, + "min": 21159, + "mean": 21159, + "median": 21159, + "max": 21159 + }, + "fallback()": { + "calls": 1, + "min": 29384, + "mean": 29384, + "median": 29384, + "max": 29384 + } + } + }, + { + "contract": "test/DelegateProxyTest.sol:ProxiedContract", + "deployment": { + "gas": 104475, + "size": 263 + }, + "functions": { + "deposit(uint256)": { + "calls": 1, + "min": 3316, + "mean": 3316, + "median": 3316, + "max": 3316 + } + } + } +] +"#]] + .is_json(), + ); +}); + +// +forgetest_init!(gas_report_size_for_nested_create, |prj, cmd| { + prj.add_test( + "NestedDeployTest.sol", + r#" +import {Test} from "forge-std/Test.sol"; +contract Child { + AnotherChild public child; + constructor() { + child = new AnotherChild(); + } + function w() external { + child.w(); + } +} +contract AnotherChild { + function w() external {} +} +contract Parent { + Child public immutable child; + constructor() { + child = new Child(); + } +} +contract NestedDeploy is Test { + function test_nested_create_gas_report() external { + Parent p = new Parent(); + p.child().child().w(); + } +} +"#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_nested_create_gas_report", "--gas-report"]) + .assert_success() + .stdout_eq(str![[r#" +... +Ran 1 test for test/NestedDeployTest.sol:NestedDeploy +[PASS] test_nested_create_gas_report() ([GAS]) +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] +| test/NestedDeployTest.sol:AnotherChild contract | | | | | | +|-------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 0 | 124 | | | | | +| Function Name | min | avg | median | max | # calls | +| w | 21161 | 21161 | 21161 | 21161 | 1 | + + +| test/NestedDeployTest.sol:Child contract | | | | | | +|------------------------------------------|-----------------|-----|--------|-----|---------| +| Deployment Cost | Deployment Size | | | | | +| 0 | 477 | | | | | +| Function Name | min | avg | median | max | # calls | +| child | 323 | 323 | 323 | 323 | 1 | + + +| test/NestedDeployTest.sol:Parent contract | | | | | | +|-------------------------------------------|-----------------|-----|--------|-----|---------| +| Deployment Cost | Deployment Size | | | | | +| 251997 | 739 | | | | | +| Function Name | min | avg | median | max | # calls | +| child | 181 | 181 | 181 | 181 | 1 | +... +"#]]); + + cmd.forge_fuse() + .args(["test", "--mt", "test_nested_create_gas_report", "--gas-report", "--json"]) + .assert_success() + .stdout_eq( + str![[r#" +[ + { + "contract": "test/NestedDeployTest.sol:AnotherChild", + "deployment": { + "gas": 0, + "size": 124 + }, + "functions": { + "w()": { + "calls": 1, + "min": 21161, + "mean": 21161, + "median": 21161, + "max": 21161 + } + } + }, + { + "contract": "test/NestedDeployTest.sol:Child", + "deployment": { + "gas": 0, + "size": 477 + }, + "functions": { + "child()": { + "calls": 1, + "min": 323, + "mean": 323, + "median": 323, + "max": 323 + } + } + }, + { + "contract": "test/NestedDeployTest.sol:Parent", + "deployment": { + "gas": 251997, + "size": 739 + }, + "functions": { + "child()": { + "calls": 1, + "min": 181, + "mean": 181, + "median": 181, + "max": 181 + } + } + } +] +"#]] + .is_json(), + ); +}); + forgetest!(zk_gas_report, |prj, cmd| { prj.insert_ds_test(); prj.add_source( @@ -2622,7 +2907,7 @@ Compiler run successful! "#]]); // Expect compilation to be skipped as no files have changed - cmd.arg("build").assert_success().stdout_eq(str![[r#" + cmd.forge_fuse().arg("build").assert_success().stdout_eq(str![[r#" No files changed, compilation skipped "#]]); @@ -2745,6 +3030,14 @@ Compiler run successful! [SOLC_VERSION] [ELAPSED] Compiler run successful! +"#]]); + + // Fail if no source file found. + prj.clear(); + cmd.forge_fuse(); + cmd.args(["build", "test/Dummy.sol", "--force"]).assert_failure().stderr_eq(str![[r#" +Error: No source files found in specified build paths. + "#]]); }); @@ -2758,10 +3051,24 @@ forgetest_init!(can_build_sizes_repeatedly, |prj, cmd| { Compiler run successful! | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |----------|------------------|-------------------|--------------------|---------------------| -| Counter | 247 | 277 | 24,329 | 48,875 | +| Counter | 236 | 263 | 24,340 | 48,889 | "#]]); + + cmd.forge_fuse().args(["build", "--sizes", "--json"]).assert_success().stdout_eq( + str![[r#" +{ + "Counter": { + "runtime_size": 236, + "init_size": 263, + "runtime_margin": 24340, + "init_margin": 48889 + } +} +"#]] + .is_json(), + ); }); // checks that build --names includes all contracts even if unchanged @@ -2777,6 +3084,11 @@ Compiler run successful! ... "#]]); + + cmd.forge_fuse() + .args(["build", "--names", "--json"]) + .assert_success() + .stdout_eq(str![[r#""{...}""#]].is_json()); }); // @@ -2808,20 +3120,20 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { | src/Counter.sol:Counter contract | | | | | | |----------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 106715 | 277 | | | | | +| 104475 | 263 | | | | | | Function Name | min | avg | median | max | # calls | -| increment | 43404 | 43404 | 43404 | 43404 | 1 | -| number | 283 | 283 | 283 | 283 | 1 | -| setNumber | 23582 | 23582 | 23582 | 23582 | 1 | +| increment | 43401 | 43401 | 43401 | 43401 | 1 | +| number | 281 | 281 | 281 | 281 | 1 | +| setNumber | 23579 | 23579 | 23579 | 23579 | 1 | | test/Counter.t.sol:CounterTest contract | | | | | | |-----------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 965418 | 4661 | | | | | +| 938190 | 4522 | | | | | | Function Name | min | avg | median | max | # calls | -| setUp | 168064 | 168064 | 168064 | 168064 | 1 | -| test_Increment | 52367 | 52367 | 52367 | 52367 | 1 | +| setUp | 165834 | 165834 | 165834 | 165834 | 1 | +| test_Increment | 52357 | 52357 | 52357 | 52357 | 1 | ... "#] @@ -2836,53 +3148,53 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { { "contract": "src/Counter.sol:Counter", "deployment": { - "gas": 106715, - "size": 277 + "gas": 104475, + "size": 263 }, "functions": { "increment()": { "calls": 1, - "min": 43404, - "mean": 43404, - "median": 43404, - "max": 43404 + "min": 43401, + "mean": 43401, + "median": 43401, + "max": 43401 }, "number()": { "calls": 1, - "min": 283, - "mean": 283, - "median": 283, - "max": 283 + "min": 281, + "mean": 281, + "median": 281, + "max": 281 }, "setNumber(uint256)": { "calls": 1, - "min": 23582, - "mean": 23582, - "median": 23582, - "max": 23582 + "min": 23579, + "mean": 23579, + "median": 23579, + "max": 23579 } } }, { "contract": "test/Counter.t.sol:CounterTest", "deployment": { - "gas": 965418, - "size": 4661 + "gas": 938190, + "size": 4522 }, "functions": { "setUp()": { "calls": 1, - "min": 168064, - "mean": 168064, - "median": 168064, - "max": 168064 + "min": 165834, + "mean": 165834, + "median": 165834, + "max": 165834 }, "test_Increment()": { "calls": 1, - "min": 52367, - "mean": 52367, - "median": 52367, - "max": 52367 + "min": 52357, + "mean": 52357, + "median": 52357, + "max": 52357 } } } diff --git a/crates/forge/tests/cli/compiler.rs b/crates/forge/tests/cli/compiler.rs index b8453b67b..0b58221f2 100644 --- a/crates/forge/tests/cli/compiler.rs +++ b/crates/forge/tests/cli/compiler.rs @@ -242,7 +242,7 @@ Solidity: Vyper: -0.4.0 (<= [..]): +0.4.0 (<= cancun): ├── src/Counter.vy └── src/ICounter.vyi diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 28b43dbfd..a45120b26 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -154,6 +154,8 @@ forgetest!(can_extract_config_values, |prj, cmd| { eof_version: None, alphanet: false, transaction_timeout: 120, + additional_compiler_profiles: Default::default(), + compilation_restrictions: Default::default(), eof: false, _non_exhaustive: (), zksync: Default::default(), @@ -570,6 +572,25 @@ forgetest_init!(can_detect_lib_foundry_toml, |prj, cmd| { "nested/=lib/nested-lib/lib/nested/".parse().unwrap(), ] ); + + // check if lib path is absolute, it should deteect nested lib + let mut config = cmd.config(); + config.libs = vec![nested]; + + let remappings = config.remappings.iter().cloned().map(Remapping::from).collect::>(); + similar_asserts::assert_eq!( + remappings, + vec![ + // local to the lib + "another-lib/=lib/nested-lib/lib/another-lib/custom-source-dir/".parse().unwrap(), + // global + "forge-std/=lib/forge-std/src/".parse().unwrap(), + "nested-lib/=lib/nested-lib/src/".parse().unwrap(), + // remappings local to the lib + "nested-twice/=lib/nested-lib/lib/another-lib/lib/nested-twice/".parse().unwrap(), + "nested/=lib/nested-lib/lib/nested/".parse().unwrap(), + ] + ); }); // test remappings with closer paths are prioritised @@ -796,4 +817,77 @@ forgetest!(normalize_config_evm_version, |_prj, cmd| { .stdout_lossy(); let config: Config = serde_json::from_str(&output).unwrap(); assert_eq!(config.evm_version, EvmVersion::Istanbul); + + // See + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.17", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::London); + + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.18", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Paris); + + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.23", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Shanghai); + + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.26", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Cancun); +}); + +// Tests that root paths are properly resolved even if submodule specifies remappings for them. +// See +forgetest_init!(test_submodule_root_path_remappings, |prj, cmd| { + prj.add_script( + "BaseScript.sol", + r#" +import "forge-std/Script.sol"; + +contract BaseScript is Script { +} + "#, + ) + .unwrap(); + prj.add_script( + "MyScript.sol", + r#" +import "script/BaseScript.sol"; + +contract MyScript is BaseScript { +} + "#, + ) + .unwrap(); + + let nested = prj.paths().libraries[0].join("another-dep"); + pretty_err(&nested, fs::create_dir_all(&nested)); + let mut lib_config = Config::load_with_root(&nested); + lib_config.remappings = vec![ + Remapping::from_str("test/=test/").unwrap().into(), + Remapping::from_str("script/=script/").unwrap().into(), + ]; + let lib_toml_file = nested.join("foundry.toml"); + pretty_err(&lib_toml_file, fs::write(&lib_toml_file, lib_config.to_string_pretty().unwrap())); + cmd.forge_fuse().args(["build"]).assert_success(); }); diff --git a/crates/forge/tests/cli/coverage.rs b/crates/forge/tests/cli/coverage.rs index 381a31c12..65900c592 100644 --- a/crates/forge/tests/cli/coverage.rs +++ b/crates/forge/tests/cli/coverage.rs @@ -1321,3 +1321,129 @@ contract AContractTest is DSTest { "#]]); }); + +// +// Test that constructor with no statements is not counted in functions coverage. +forgetest!(test_ignore_empty_constructors_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +contract AContract { + constructor() {} + + function increment() public {} +} + "#, + ) + .unwrap(); + + prj.add_source( + "AContractTest.sol", + r#" +import "./test.sol"; +import "./AContract.sol"; + +contract AContractTest is DSTest { + function test_constructors() public { + AContract a = new AContract(); + a.increment(); + } +} + "#, + ) + .unwrap(); + + // Assert there's only one function (`increment`) reported. + cmd.arg("coverage").args(["--summary".to_string()]).assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|---------------|---------------|---------------|---------------| +| src/AContract.sol | 100.00% (0/0) | 100.00% (0/0) | 100.00% (0/0) | 100.00% (1/1) | +| Total | 100.00% (0/0) | 100.00% (0/0) | 100.00% (0/0) | 100.00% (1/1) | + +"#]]); +}); + +// Test coverage for `receive` functions. +forgetest!(test_receive_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +contract AContract { + uint256 public counter = 0; + + constructor() { + counter = 1; + } + + receive() external payable { + counter = msg.value; + } +} + "#, + ) + .unwrap(); + + prj.add_source( + "AContractTest.sol", + r#" +import "./test.sol"; +import "./AContract.sol"; + +contract AContractTest is DSTest { + function test_constructors() public { + AContract a = new AContract(); + address(a).call{value: 5}(""); + require(a.counter() == 5); + } +} + "#, + ) + .unwrap(); + + // Assert both constructor and receive functions coverage reported. + cmd.arg("coverage").args(["--summary".to_string()]).assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|---------------|---------------|---------------|---------------| +| src/AContract.sol | 100.00% (2/2) | 100.00% (2/2) | 100.00% (0/0) | 100.00% (2/2) | +| Total | 100.00% (2/2) | 100.00% (2/2) | 100.00% (0/0) | 100.00% (2/2) | + +"#]]); +}); + +// +// Test coverage with `--ir-minimum` for solidity < 0.8.5. +forgetest!(test_ir_minimum_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +pragma solidity 0.8.4; + +contract AContract { + function isContract(address account) internal view returns (bool) { + bytes32 codehash; + bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + assembly { + codehash := extcodehash(account) + } + return (codehash != accountHash && codehash != 0x0); + } +} + "#, + ) + .unwrap(); + + // Assert coverage doesn't fail with `Error: Unknown key "inliner"`. + cmd.arg("coverage").arg("--ir-minimum").assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|-------------|--------------|---------------|-------------| +| src/AContract.sol | 0.00% (0/4) | 0.00% (0/4) | 100.00% (0/0) | 0.00% (0/1) | +| Total | 0.00% (0/4) | 0.00% (0/4) | 100.00% (0/0) | 0.00% (0/1) | + +"#]]); +}); diff --git a/crates/forge/tests/cli/eip712.rs b/crates/forge/tests/cli/eip712.rs index 2f832ae31..9ec944631 100644 --- a/crates/forge/tests/cli/eip712.rs +++ b/crates/forge/tests/cli/eip712.rs @@ -19,6 +19,11 @@ library Structs { struct Complex { Structs2.Foo foo2; Foo[] foos; + Rec[][] recs; + } + + struct Rec { + Rec[] rec; } } @@ -26,6 +31,23 @@ library Structs2 { struct Foo { uint256 id; } + + struct Rec { + Bar[] bar; + } + + struct Bar { + Rec rec; + } + + struct FooBar { + Foo[] foos; + Bar[] bars; + Structs.Foo foo; + Structs.Bar bar; + Rec[] recs; + Structs.Rec rec; + } } "#, ) @@ -42,10 +64,18 @@ Bar(Art art)Art(uint256 id) Art(uint256 id) -Complex(Foo foo2,Foo_1[] foos)Art(uint256 id)Bar(Art art)Foo(uint256 id)Foo_1(Bar bar) +Complex(Foo foo2,Foo_1[] foos,Rec[][] recs)Art(uint256 id)Bar(Art art)Foo(uint256 id)Foo_1(Bar bar)Rec(Rec[] rec) + +Rec(Rec[] rec) Foo(uint256 id) +Rec(Bar[] bar)Bar(Rec rec) + +Bar(Rec rec)Rec(Bar[] bar) + +FooBar(Foo[] foos,Bar[] bars,Foo_1 foo,Bar_1 bar,Rec[] recs,Rec_1 rec)Art(uint256 id)Bar(Rec rec)Bar_1(Art art)Foo(uint256 id)Foo_1(Bar_1 bar)Rec(Bar[] bar)Rec_1(Rec_1[] rec) + "#]], ); diff --git a/crates/forge/tests/cli/ext_integration.rs b/crates/forge/tests/cli/ext_integration.rs index 9a4c85f14..af0f74dde 100644 --- a/crates/forge/tests/cli/ext_integration.rs +++ b/crates/forge/tests/cli/ext_integration.rs @@ -2,7 +2,7 @@ use foundry_test_utils::util::ExtTester; #[test] fn forge_std() { - ExtTester::new("foundry-rs", "forge-std", "1d0766bc5d814f117c7b1e643828f7d85024fb51") + ExtTester::new("foundry-rs", "forge-std", "2b59872eee0b8088ddcade39fe8c041e17bb79c0") // Skip fork tests. .args(["--nmc", "Fork"]) .run(); @@ -89,6 +89,7 @@ fn stringutils() { fn lootloose() { ExtTester::new("gakonst", "lootloose", "7b639efe97836155a6a6fc626bf1018d4f8b2495") .install_command(&["make", "install"]) + .args(["--evm-version", "paris"]) .run(); } diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index 4b4e89bdd..0de0e744f 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -230,7 +230,7 @@ Traces: ├─ [0] VM::startBroadcast() │ └─ ← [Return] ├─ [..] → new GasWaster@[..] - │ └─ ← [Return] 226 bytes of code + │ └─ ← [Return] 221 bytes of code ├─ [..] GasWaster::wasteGas(200000 [2e5]) │ └─ ← [Stop] └─ ← [Stop] @@ -242,10 +242,10 @@ Script ran successfully. ========================== Simulated On-chain Traces: - [45299] → new GasWaster@[..] - └─ ← [Return] 226 bytes of code + [44291] → new GasWaster@[..] + └─ ← [Return] 221 bytes of code - [226] GasWaster::wasteGas(200000 [2e5]) + [224] GasWaster::wasteGas(200000 [2e5]) └─ ← [Stop] @@ -337,7 +337,7 @@ Traces: ├─ [0] VM::startBroadcast() │ └─ ← [Return] ├─ [..] → new GasWaster@[..] - │ └─ ← [Return] 226 bytes of code + │ └─ ← [Return] 221 bytes of code ├─ [..] GasWaster::wasteGas(200000 [2e5]) │ └─ ← [Stop] └─ ← [Stop] @@ -349,10 +349,10 @@ Script ran successfully. ========================== Simulated On-chain Traces: - [45299] → new GasWaster@[..] - └─ ← [Return] 226 bytes of code + [44291] → new GasWaster@[..] + └─ ← [Return] 221 bytes of code - [226] GasWaster::wasteGas(200000 [2e5]) + [224] GasWaster::wasteGas(200000 [2e5]) └─ ← [Stop] @@ -522,7 +522,7 @@ Traces: ├─ [0] VM::startBroadcast() │ └─ ← [Return] ├─ [..] → new HashChecker@[..] - │ └─ ← [Return] 378 bytes of code + │ └─ ← [Return] 368 bytes of code └─ ← [Stop] @@ -2327,15 +2327,15 @@ contract SimpleScript is Script { [SOLC_VERSION] [ELAPSED] Compiler run successful! Traces: - [104553] SimpleScript::run() + [103771] SimpleScript::run() ├─ [0] VM::startBroadcast() │ └─ ← [Return] - ├─ [23875] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 - │ └─ ← [Return] 119 bytes of code - ├─ [13367] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 - │ ├─ [146] A::getValue() [staticcall] + ├─ [23273] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 + │ └─ ← [Return] 116 bytes of code + ├─ [13162] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + │ ├─ [145] A::getValue() [staticcall] │ │ └─ ← [Return] 100 - │ └─ ← [Return] 63 bytes of code + │ └─ ← [Return] 62 bytes of code └─ ← [Stop] @@ -2345,13 +2345,13 @@ Script ran successfully. ========================== Simulated On-chain Traces: - [23875] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 - └─ ← [Return] 119 bytes of code + [23273] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 + └─ ← [Return] 116 bytes of code - [15867] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 - ├─ [146] A::getValue() [staticcall] + [15662] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + ├─ [145] A::getValue() [staticcall] │ └─ ← [Return] 100 - └─ ← [Return] 63 bytes of code + └─ ← [Return] 62 bytes of code ... "#]]); }); diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 9381a7d05..96c89953a 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -575,7 +575,7 @@ Compiler run successful! Ran 1 test for test/Contract.t.sol:USDTCallingTest [PASS] test() ([GAS]) Traces: - [9516] USDTCallingTest::test() + [..] USDTCallingTest::test() ├─ [0] VM::createSelectFork("[..]") │ └─ ← [Return] 0 ├─ [3110] 0xdAC17F958D2ee523a2206206994597C13D831ec7::name() [staticcall] @@ -621,12 +621,12 @@ Compiler run successful! Ran 2 tests for test/Contract.t.sol:CustomTypesTest [FAIL: PoolNotInitialized()] testErr() ([GAS]) Traces: - [254] CustomTypesTest::testErr() + [253] CustomTypesTest::testErr() └─ ← [Revert] PoolNotInitialized() [PASS] testEvent() ([GAS]) Traces: - [1268] CustomTypesTest::testEvent() + [1267] CustomTypesTest::testEvent() ├─ emit MyEvent(a: 100) └─ ← [Stop] @@ -932,6 +932,30 @@ Encountered a total of 2 failing tests, 0 tests succeeded "#]]); }); +// +forgetest_init!(should_not_record_setup_failures, |prj, cmd| { + prj.add_test( + "ReplayFailures.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract SetupFailureTest is Test { + function setUp() public { + require(2 > 1); + } + + function testA() public pure { + } +} + "#, + ) + .unwrap(); + + cmd.args(["test"]).assert_success(); + // Test failure filter should not be persisted if `setUp` failed. + assert!(!prj.root().join("cache/test-failures").exists()); +}); + // https://github.com/foundry-rs/foundry/issues/7530 forgetest_init!(should_show_precompile_labels, |prj, cmd| { prj.wipe_contracts(); @@ -972,7 +996,7 @@ Compiler run successful! Ran 1 test for test/Contract.t.sol:PrecompileLabelsTest [PASS] testPrecompileLabels() ([GAS]) Traces: - [9474] PrecompileLabelsTest::testPrecompileLabels() + [9383] PrecompileLabelsTest::testPrecompileLabels() ├─ [0] VM::deal(VM: [0x7109709ECfa91a80626fF3989D68f67F5b1DD12D], 1000000000000000000 [1e18]) │ └─ ← [Return] ├─ [0] VM::deal(console: [0x000000000000000000636F6e736F6c652e6c6f67], 1000000000000000000 [1e18]) @@ -1240,17 +1264,17 @@ Compiler run successful! Ran 1 test for test/Simple.sol:SimpleContractTest [PASS] test() ([GAS]) Traces: - [250463] SimpleContractTest::test() - ├─ [171014] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 854 bytes of code - ├─ [22638] SimpleContract::increment() - │ ├─ [20150] SimpleContract::_setNum(1) + [244864] SimpleContractTest::test() + ├─ [165406] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 826 bytes of code + ├─ [22630] SimpleContract::increment() + │ ├─ [20147] SimpleContract::_setNum(1) │ │ └─ ← 0 │ └─ ← [Stop] - ├─ [23219] SimpleContract::setValues(100, 0x0000000000000000000000000000000000000123) - │ ├─ [250] SimpleContract::_setNum(100) + ├─ [23204] SimpleContract::setValues(100, 0x0000000000000000000000000000000000000123) + │ ├─ [247] SimpleContract::_setNum(100) │ │ └─ ← 1 - │ ├─ [22339] SimpleContract::_setAddr(0x0000000000000000000000000000000000000123) + │ ├─ [22336] SimpleContract::_setAddr(0x0000000000000000000000000000000000000123) │ │ └─ ← 0x0000000000000000000000000000000000000000 │ └─ ← [Stop] └─ ← [Stop] @@ -1302,11 +1326,11 @@ contract SimpleContractTest is Test { r#" ... Traces: - [421947] SimpleContractTest::test() - ├─ [385978] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 1814 bytes of code - ├─ [2534] SimpleContract::setStr("new value") - │ ├─ [1600] SimpleContract::_setStr("new value") + [406629] SimpleContractTest::test() + ├─ [370554] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 1737 bytes of code + ├─ [2511] SimpleContract::setStr("new value") + │ ├─ [1588] SimpleContract::_setStr("new value") │ │ └─ ← "initial value" │ └─ ← [Stop] └─ ← [Stop] @@ -1470,10 +1494,10 @@ contract ATest is Test { cmd.args(["test"]).with_no_redact().assert_success().stdout_eq(str![[r#" ... -[PASS] testNormalGas() (gas: 3202) -[PASS] testWeirdGas1() (gas: 3040) -[PASS] testWeirdGas2() (gas: 3148) -[PASS] testWithAssembly() (gas: 3083) +[PASS] testNormalGas() (gas: 3194) +[PASS] testWeirdGas1() (gas: 3032) +[PASS] testWeirdGas2() (gas: 3139) +[PASS] testWithAssembly() (gas: 3075) ... "#]]); }); @@ -1558,9 +1582,9 @@ contract ATest is Test { cmd.args(["test", "-vvvv"]).with_no_redact().assert_success().stdout_eq(str![[r#" ... Logs: - Gas cost: 34468 + Gas cost: 34367 ... -[PASS] test_GasMeter() (gas: 37512) +[PASS] test_GasMeter() (gas: 37407) ... "#]]); }); @@ -1645,33 +1669,33 @@ contract PauseTracingTest is DSTest { cmd.args(["test", "-vvvvv"]).assert_success().stdout_eq(str![[r#" ... Traces: - [7285] PauseTracingTest::setUp() + [7282] PauseTracingTest::setUp() ├─ emit DummyEvent(i: 1) ├─ [0] VM::pauseTracing() [staticcall] │ └─ ← [Return] └─ ← [Stop] - [294725] PauseTracingTest::test() + [282512] PauseTracingTest::test() ├─ [0] VM::resumeTracing() [staticcall] │ └─ ← [Return] - ├─ [18373] TraceGenerator::generate() - │ ├─ [1280] TraceGenerator::call(0) + ├─ [18327] TraceGenerator::generate() + │ ├─ [1278] TraceGenerator::call(0) │ │ ├─ emit DummyEvent(i: 0) │ │ └─ ← [Stop] - │ ├─ [1280] TraceGenerator::call(1) + │ ├─ [1278] TraceGenerator::call(1) │ │ ├─ emit DummyEvent(i: 1) │ │ └─ ← [Stop] - │ ├─ [1280] TraceGenerator::call(2) + │ ├─ [1278] TraceGenerator::call(2) │ │ ├─ emit DummyEvent(i: 2) │ │ └─ ← [Stop] │ ├─ [0] VM::pauseTracing() [staticcall] │ │ └─ ← [Return] │ ├─ [0] VM::resumeTracing() [staticcall] │ │ └─ ← [Return] - │ ├─ [1280] TraceGenerator::call(8) + │ ├─ [1278] TraceGenerator::call(8) │ │ ├─ emit DummyEvent(i: 8) │ │ └─ ← [Stop] - │ ├─ [1280] TraceGenerator::call(9) + │ ├─ [1278] TraceGenerator::call(9) │ │ ├─ emit DummyEvent(i: 9) │ │ └─ ← [Stop] │ └─ ← [Stop] @@ -2367,11 +2391,11 @@ Compiler run successful! Ran 1 test for test/MetadataTraceTest.t.sol:MetadataTraceTest [PASS] test_proxy_trace() ([GAS]) Traces: - [152142] MetadataTraceTest::test_proxy_trace() - ├─ [49499] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 247 bytes of code - ├─ [37978] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b - │ └─ ← [Return] 63 bytes of code + [149783] MetadataTraceTest::test_proxy_trace() + ├─ [47297] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 236 bytes of code + ├─ [37762] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b + │ └─ ← [Return] 62 bytes of code └─ ← [Stop] Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] @@ -2392,11 +2416,11 @@ Compiler run successful! Ran 1 test for test/MetadataTraceTest.t.sol:MetadataTraceTest [PASS] test_proxy_trace() ([GAS]) Traces: - [130521] MetadataTraceTest::test_proxy_trace() - ├─ [38693] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 193 bytes of code - ├─ [27175] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b - │ └─ ← [Return] 9 bytes of code + [128142] MetadataTraceTest::test_proxy_trace() + ├─ [36485] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 182 bytes of code + ├─ [26959] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b + │ └─ ← [Return] 8 bytes of code └─ ← [Stop] Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] @@ -2571,7 +2595,7 @@ forgetest_async!(can_get_broadcast_txs, |prj, cmd| { 31337 ); - assertEq(deployedAddress, address(0x030D07c16e2c0a77f74ab16f3C8F10ACeF89FF81)); + assertEq(deployedAddress, address(0x78280279172ED4C0E65BCE5Ee9DFdcd828f837DB)); } function test_getDeployments() public { @@ -2581,7 +2605,7 @@ forgetest_async!(can_get_broadcast_txs, |prj, cmd| { ); assertEq(deployments.length, 2); - assertEq(deployments[0], address(0x030D07c16e2c0a77f74ab16f3C8F10ACeF89FF81)); // Create2 address - latest deployment + assertEq(deployments[0], address(0x78280279172ED4C0E65BCE5Ee9DFdcd828f837DB)); // Create2 address - latest deployment assertEq(deployments[1], address(0x5FbDB2315678afecb367f032d93F642f64180aa3)); // Create address - oldest deployment } @@ -2626,3 +2650,52 @@ forgetest_async!(can_get_broadcast_txs, |prj, cmd| { cmd.forge_fuse().args(["test", "--mc", "GetBroadcastTest", "-vvv"]).assert_success(); }); + +// See +forgetest_init!(test_roll_scroll_fork_with_cancun, |prj, cmd| { + prj.add_test( + "ScrollForkTest.t.sol", + r#" + +import {Test} from "forge-std/Test.sol"; + +contract ScrollForkTest is Test { + function test_roll_scroll_fork_to_tx() public { + vm.createSelectFork("https://scroll-mainnet.chainstacklabs.com/"); + bytes32 targetTxHash = 0xf94774a1f69bba76892141190293ffe85dd8d9ac90a0a2e2b114b8c65764014c; + vm.rollFork(targetTxHash); + } +} + "#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_roll_scroll_fork_to_tx", "--evm-version", "cancun"]) + .assert_success(); +}); + +// Test that only provider is included in failed fork error. +forgetest_init!(test_display_provider_on_error, |prj, cmd| { + prj.add_test( + "ForkTest.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract ForkTest is Test { + function test_fork_err_message() public { + vm.createSelectFork("https://eth-mainnet.g.alchemy.com/v2/DUMMY_KEY"); + } +} + "#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_fork_err_message"]).assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/ForkTest.t.sol:ForkTest +[FAIL: vm.createSelectFork: Could not instantiate forked environment with provider eth-mainnet.g.alchemy.com;] test_fork_err_message() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] +... + +"#]]); +}); diff --git a/crates/forge/tests/it/cheats.rs b/crates/forge/tests/it/cheats.rs index a60602cbc..871cda045 100644 --- a/crates/forge/tests/it/cheats.rs +++ b/crates/forge/tests/it/cheats.rs @@ -3,8 +3,8 @@ use crate::{ config::*, test_helpers::{ - ForgeTestData, RE_PATH_SEPARATOR, TEST_DATA_CANCUN, TEST_DATA_DEFAULT, - TEST_DATA_MULTI_VERSION, + ForgeTestData, RE_PATH_SEPARATOR, TEST_DATA_DEFAULT, TEST_DATA_MULTI_VERSION, + TEST_DATA_PARIS, }, }; use alloy_primitives::U256; @@ -77,6 +77,6 @@ async fn test_cheats_local_multi_version() { } #[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_cancun() { - test_cheats_local(&TEST_DATA_CANCUN).await +async fn test_cheats_local_paris() { + test_cheats_local(&TEST_DATA_PARIS).await } diff --git a/crates/forge/tests/it/core.rs b/crates/forge/tests/it/core.rs index 17d9f59d8..c8a599195 100644 --- a/crates/forge/tests/it/core.rs +++ b/crates/forge/tests/it/core.rs @@ -1,6 +1,9 @@ //! Forge tests for core functionality. -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; +use crate::{ + config::*, + test_helpers::{TEST_DATA_DEFAULT, TEST_DATA_PARIS}, +}; use forge::result::SuiteResult; use foundry_evm::traces::TraceKind; use foundry_test_utils::Filter; @@ -20,7 +23,7 @@ async fn test_core() { vec![( "setUp()", false, - Some("setup failed: revert: setup failed predictably".to_string()), + Some("revert: setup failed predictably".to_string()), None, None, )], @@ -67,13 +70,7 @@ async fn test_core() { ), ( "default/core/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest", - vec![( - "setUp()", - false, - Some("setup failed: execution error".to_string()), - None, - None, - )], + vec![("setUp()", false, Some("execution error".to_string()), None, None)], ), ( "default/core/MultipleAfterInvariant.t.sol:MultipleAfterInvariant", @@ -803,3 +800,25 @@ async fn test_legacy_assertions() { )]), ); } + +/// Test `beforeTest` functionality and `selfdestruct`. +/// See +#[tokio::test(flavor = "multi_thread")] +async fn test_before_setup_with_selfdestruct() { + let filter = Filter::new(".*", ".*BeforeTestSelfDestructTest", ".*"); + let results = TEST_DATA_PARIS.runner().test_collect(&filter); + + assert_multiple( + &results, + BTreeMap::from([( + "paris/core/BeforeTest.t.sol:BeforeTestSelfDestructTest", + vec![ + ("testKill()", true, None, None, None), + ("testA()", true, None, None, None), + ("testSimpleA()", true, None, None, None), + ("testB()", true, None, None, None), + ("testC(uint256)", true, None, None, None), + ], + )]), + ); +} diff --git a/crates/forge/tests/it/fork.rs b/crates/forge/tests/it/fork.rs index 26c45aa18..8dc637528 100644 --- a/crates/forge/tests/it/fork.rs +++ b/crates/forge/tests/it/fork.rs @@ -2,7 +2,7 @@ use crate::{ config::*, - test_helpers::{RE_PATH_SEPARATOR, TEST_DATA_DEFAULT}, + test_helpers::{RE_PATH_SEPARATOR, TEST_DATA_DEFAULT, TEST_DATA_PARIS}, }; use alloy_chains::Chain; use forge::result::SuiteResult; @@ -35,9 +35,9 @@ async fn test_cheats_fork_revert() { /// Executes all non-reverting fork cheatcodes #[tokio::test(flavor = "multi_thread")] async fn test_cheats_fork() { - let mut config = TEST_DATA_DEFAULT.config.clone(); + let mut config = TEST_DATA_PARIS.config.clone(); config.fs_permissions = FsPermissions::new(vec![PathPermission::read("./fixtures")]); - let runner = TEST_DATA_DEFAULT.runner_with_config(config); + let runner = TEST_DATA_PARIS.runner_with_config(config); let filter = Filter::new(".*", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}Fork")) .exclude_tests(".*Revert"); TestConfig::with_filter(runner, filter).run().await; @@ -86,7 +86,7 @@ async fn test_launch_fork_ws() { /// Tests that we can transact transactions in forking mode #[tokio::test(flavor = "multi_thread")] async fn test_transact_fork() { - let runner = TEST_DATA_DEFAULT.runner(); + let runner = TEST_DATA_PARIS.runner(); let filter = Filter::new(".*", ".*", &format!(".*fork{RE_PATH_SEPARATOR}Transact")); TestConfig::with_filter(runner, filter).run().await; } diff --git a/crates/forge/tests/it/fuzz.rs b/crates/forge/tests/it/fuzz.rs index d6b047a17..8972c9bd9 100644 --- a/crates/forge/tests/it/fuzz.rs +++ b/crates/forge/tests/it/fuzz.rs @@ -203,10 +203,10 @@ contract FuzzerDictTest is Test { .unwrap(); // Test that immutable address is used as fuzzed input, causing test to fail. - cmd.args(["test", "--fuzz-seed", "100", "--mt", "testImmutableOwner"]).assert_failure(); + cmd.args(["test", "--fuzz-seed", "119", "--mt", "testImmutableOwner"]).assert_failure(); // Test that storage address is used as fuzzed input, causing test to fail. cmd.forge_fuse() - .args(["test", "--fuzz-seed", "100", "--mt", "testStorageOwner"]) + .args(["test", "--fuzz-seed", "119", "--mt", "testStorageOwner"]) .assert_failure(); }); diff --git a/crates/forge/tests/it/repros.rs b/crates/forge/tests/it/repros.rs index c2154b6aa..f3c623b38 100644 --- a/crates/forge/tests/it/repros.rs +++ b/crates/forge/tests/it/repros.rs @@ -376,14 +376,11 @@ test_repro!(8383, false, None, |res| { let test = res.test_results.remove("testP256VerifyOutOfBounds()").unwrap(); assert_eq!(test.status, TestStatus::Success); match test.kind { - TestKind::Unit { gas } => assert_eq!(gas, 3103), + TestKind::Unit { gas } => assert_eq!(gas, 3101), _ => panic!("not a unit test kind"), } }); -// https://github.com/foundry-rs/foundry/issues/1543 -test_repro!(1543); - // https://github.com/foundry-rs/foundry/issues/6643 test_repro!(6643); diff --git a/crates/forge/tests/it/spec.rs b/crates/forge/tests/it/spec.rs index db98a15d1..aed2063a0 100644 --- a/crates/forge/tests/it/spec.rs +++ b/crates/forge/tests/it/spec.rs @@ -1,13 +1,13 @@ //! Integration tests for EVM specifications. -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; +use crate::{config::*, test_helpers::TEST_DATA_PARIS}; use foundry_evm::revm::primitives::SpecId; use foundry_test_utils::Filter; #[tokio::test(flavor = "multi_thread")] async fn test_shanghai_compat() { let filter = Filter::new("", "ShanghaiCompat", ".*spec"); - TestConfig::with_filter(TEST_DATA_DEFAULT.runner(), filter) + TestConfig::with_filter(TEST_DATA_PARIS.runner(), filter) .evm_spec(SpecId::SHANGHAI) .run() .await; diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs index 350da4d51..fe06d785f 100644 --- a/crates/forge/tests/it/test_helpers.rs +++ b/crates/forge/tests/it/test_helpers.rs @@ -47,7 +47,7 @@ static VYPER: LazyLock = LazyLock::new(|| std::env::temp_dir().join("vy /// Profile for the tests group. Used to configure separate configurations for test runs. pub enum ForgeTestProfile { Default, - Cancun, + Paris, MultiVersion, } @@ -55,16 +55,16 @@ impl fmt::Display for ForgeTestProfile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Default => write!(f, "default"), - Self::Cancun => write!(f, "cancun"), + Self::Paris => write!(f, "paris"), Self::MultiVersion => write!(f, "multi-version"), } } } impl ForgeTestProfile { - /// Returns true if the profile is Cancun. - pub fn is_cancun(&self) -> bool { - matches!(self, Self::Cancun) + /// Returns true if the profile is Paris. + pub fn is_paris(&self) -> bool { + matches!(self, Self::Paris) } pub fn root(&self) -> PathBuf { @@ -79,8 +79,8 @@ impl ForgeTestProfile { let mut settings = Settings { libraries: Libraries::parse(&libs).unwrap(), ..Default::default() }; - if matches!(self, Self::Cancun) { - settings.evm_version = Some(EvmVersion::Cancun); + if matches!(self, Self::Paris) { + settings.evm_version = Some(EvmVersion::Paris); } let settings = SolcConfig::builder().settings(settings).build(); @@ -186,8 +186,8 @@ impl ForgeTestProfile { "fork/Fork.t.sol:DssExecLib:0xfD88CeE74f7D78697775aBDAE53f9Da1559728E4".to_string(), ]; - if self.is_cancun() { - config.evm_version = EvmVersion::Cancun; + if self.is_paris() { + config.evm_version = EvmVersion::Paris; } config @@ -278,8 +278,8 @@ impl ForgeTestData { let mut runner = MultiContractRunnerBuilder::new(Arc::new(self.config.clone())) .sender(self.evm_opts.sender) .with_test_options(self.test_opts.clone()); - if self.profile.is_cancun() { - runner = runner.evm_spec(SpecId::CANCUN); + if self.profile.is_paris() { + runner = runner.evm_spec(SpecId::MERGE); } runner @@ -523,9 +523,9 @@ pub static EVM_OPTS: LazyLock = LazyLock::new(|| EvmOpts { pub static TEST_DATA_DEFAULT: LazyLock = LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Default)); -/// Data for tests requiring Cancun support on Solc and EVM level. -pub static TEST_DATA_CANCUN: LazyLock = - LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Cancun)); +/// Data for tests requiring Paris support on Solc and EVM level. +pub static TEST_DATA_PARIS: LazyLock = + LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Paris)); /// Data for tests requiring Cancun support on Solc and EVM level. pub static TEST_DATA_MULTI_VERSION: LazyLock = diff --git a/crates/forge/tests/it/zk/traces.rs b/crates/forge/tests/it/zk/traces.rs index 09f87520b..e02d3cc6f 100644 --- a/crates/forge/tests/it/zk/traces.rs +++ b/crates/forge/tests/it/zk/traces.rs @@ -8,7 +8,7 @@ use forge::{ revm::primitives::SpecId, traces::{CallKind, CallTraceNode, SparsedTraceArena, TraceKind}, }; -use foundry_common::fs; +use foundry_common::{fs, sh_println}; use foundry_test_utils::Filter; use itertools::Itertools; use serde::Deserialize; @@ -335,14 +335,14 @@ fn assert_execution_trace( let actual = decode_first_execution_trace(traces); if let Some(failure) = assert_recursive(&expected, &actual) { - println!("---"); - println!("{failure:#?}"); - println!("---"); - println!("Trace:"); + let _ = sh_println!("---"); + let _ = sh_println!("{failure:#?}"); + let _ = sh_println!("---"); + let _ = sh_println!("Trace:"); let mut actual = &actual; for (depth, idx) in failure.path.iter().enumerate() { let trace = &actual[*idx]; - println!( + let _ = sh_println!( "{}{:?} {:?} {:?} {:?}", " ".repeat(depth), trace.kind, @@ -353,7 +353,7 @@ fn assert_execution_trace( actual = &trace.children; } - println!("---\n"); + let _ = sh_println!("---\n"); panic!("trace assertion failure"); } } diff --git a/crates/script/src/broadcast.rs b/crates/script/src/broadcast.rs index 38e279910..0b958894e 100644 --- a/crates/script/src/broadcast.rs +++ b/crates/script/src/broadcast.rs @@ -126,7 +126,7 @@ pub async fn send_transaction( zk_tx.set_factory_deps(zk.factory_deps.iter().map(Bytes::from_iter).collect()); } if let Some(paymaster_data) = &zk.paymaster_data { - zk_tx.set_paymaster( + zk_tx.set_paymaster_params( alloy_zksync::network::unsigned_tx::eip712::PaymasterParams { paymaster: paymaster_data.paymaster.to_address(), paymaster_input: paymaster_data.paymaster_input.clone().into(), diff --git a/crates/script/src/execute.rs b/crates/script/src/execute.rs index 8f6e86f41..c47c8ac4c 100644 --- a/crates/script/src/execute.rs +++ b/crates/script/src/execute.rs @@ -257,7 +257,7 @@ For more information, please see https://eips.ethereum.org/EIPS/eip-3855", .map(|(_, chain)| *chain as u64) .format(", ") ); - sh_warn!("{}", msg)?; + sh_warn!("{msg}")?; } Ok(()) } diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 46b387e20..113ed9006 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -26,7 +26,10 @@ use dialoguer::Confirm; use eyre::{ContextCompat, Result}; use forge_script_sequence::{AdditionalContract, NestedValue}; use forge_verify::RetryArgs; -use foundry_cli::{opts::CoreBuildArgs, utils::LoadConfig}; +use foundry_cli::{ + opts::{CoreBuildArgs, GlobalOpts}, + utils::LoadConfig, +}; use foundry_common::{ abi::{encode_function_args, get_func}, evm::{Breakpoints, EvmArgs}, @@ -76,6 +79,10 @@ foundry_config::merge_impl_figment_convert!(ScriptArgs, opts, evm_opts); /// CLI arguments for `forge script`. #[derive(Clone, Debug, Default, Parser)] pub struct ScriptArgs { + // Include global options for users of this struct. + #[command(flatten)] + pub global: GlobalOpts, + /// The contract you want to run. Either the file path or contract name. /// /// If multiple contracts exist in the same file you must specify the target contract with diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index af80734c5..c11fdd71a 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -72,7 +72,7 @@ pub fn format_receipt(chain: Chain, receipt: &AnyTransactionReceipt) -> String { let gas_used = receipt.gas_used; let gas_price = receipt.effective_gas_price; format!( - "\n##### {chain}\n{status}Hash: {tx_hash:?}{caddr}\nBlock: {bn}\n{gas}\n\n", + "\n##### {chain}\n{status} Hash: {tx_hash:?}{caddr}\nBlock: {bn}\n{gas}\n\n", status = if !receipt.inner.inner.inner.receipt.status.coerce_status() { "❌ [Failed]" } else { diff --git a/crates/script/src/runner.rs b/crates/script/src/runner.rs index 99bafee63..34cc54e28 100644 --- a/crates/script/src/runner.rs +++ b/crates/script/src/runner.rs @@ -1,5 +1,6 @@ use super::ScriptResult; use crate::build::ScriptPredeployLibraries; +use alloy_eips::eip7702::SignedAuthorization; use alloy_primitives::{Address, Bytes, TxKind, U256}; use alloy_rpc_types::TransactionRequest; use eyre::Result; @@ -14,7 +15,6 @@ use foundry_evm::{ }; use foundry_zksync_core::ZkTransactionMetadata; use std::collections::VecDeque; -use yansi::Paint; /// Drives script execution #[derive(Debug)] @@ -249,7 +249,7 @@ impl ScriptRunner { /// Executes the method that will collect all broadcastable transactions. pub fn script(&mut self, address: Address, calldata: Bytes) -> Result { - self.call(self.evm_opts.sender, address, calldata, U256::ZERO, false) + self.call(self.evm_opts.sender, address, calldata, U256::ZERO, None, false) } /// Runs a broadcastable transaction locally and persists its state. @@ -259,6 +259,7 @@ impl ScriptRunner { to: Option
, calldata: Option, value: Option, + authorization_list: Option>, (use_zk, zk_tx): (bool, Option), ) -> Result { self.executor.use_zk = use_zk; @@ -267,7 +268,14 @@ impl ScriptRunner { } if let Some(to) = to { - self.call(from, to, calldata.unwrap_or_default(), value.unwrap_or(U256::ZERO), true) + self.call( + from, + to, + calldata.unwrap_or_default(), + value.unwrap_or(U256::ZERO), + authorization_list, + true, + ) } else if to.is_none() { let res = self.executor.deploy( from, @@ -279,7 +287,7 @@ impl ScriptRunner { Ok(DeployResult { address, raw }) => (address, raw), Err(EvmError::Execution(err)) => { let ExecutionErr { raw, reason } = *err; - println!("{}", format!("\nFailed with `{reason}`:\n").red()); + sh_err!("Failed with `{reason}`:\n")?; (Address::ZERO, raw) } Err(e) => eyre::bail!("Failed deploying contract: {e:?}"), @@ -314,9 +322,20 @@ impl ScriptRunner { to: Address, calldata: Bytes, value: U256, + authorization_list: Option>, commit: bool, ) -> Result { - let mut res = self.executor.call_raw(from, to, calldata.clone(), value)?; + let mut res = if let Some(authorization_list) = authorization_list { + self.executor.call_raw_with_authorization( + from, + to, + calldata.clone(), + value, + authorization_list, + )? + } else { + self.executor.call_raw(from, to, calldata.clone(), value)? + }; let mut gas_used = res.gas_used; // We should only need to calculate realistic gas costs when preparing to broadcast diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index 478f766fa..2b6012b10 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -16,7 +16,7 @@ use eyre::{Context, Result}; use forge_script_sequence::{ScriptSequence, TransactionWithMetadata}; use foundry_cheatcodes::Wallets; use foundry_cli::utils::{has_different_gas_calc, now}; -use foundry_common::{get_contract_name, ContractData}; +use foundry_common::ContractData; use foundry_evm::traces::{decode_trace_arena, render_trace_arena}; use futures::future::{join_all, try_join_all}; use parking_lot::RwLock; @@ -112,11 +112,11 @@ impl PreSimulationState { // Executes all transactions from the different forks concurrently. let futs = transactions .into_iter() - .map(|transaction| async { + .map(|mut transaction| async { let mut runner = runners.get(&transaction.rpc).expect("invalid rpc url").write(); - let zk_metadata = transaction.zk.clone(); - let tx = transaction.tx(); + let tx = transaction.tx_mut(); + let to = if let Some(TxKind::Call(to)) = tx.to() { Some(to) } else { None }; let result = runner .simulate( @@ -125,6 +125,7 @@ impl PreSimulationState { to, tx.input().map(Bytes::copy_from_slice), tx.value(), + tx.authorization_list(), (self.script_config.config.zksync.run_in_zk_mode(), zk_metadata), ) .wrap_err("Internal EVM error during simulation")?; @@ -153,8 +154,8 @@ impl PreSimulationState { .collect::>(); if self.script_config.evm_opts.verbosity > 3 { - println!("=========================="); - println!("Simulated On-chain Traces:\n"); + sh_println!("==========================")?; + sh_println!("Simulated On-chain Traces:\n")?; } let mut abort = false; @@ -165,7 +166,7 @@ impl PreSimulationState { if tx.is_none() || self.script_config.evm_opts.verbosity > 3 { for (_, trace) in &mut traces { decode_trace_arena(trace, &self.execution_artifacts.decoder).await?; - println!("{}", render_trace_arena(trace)); + sh_println!("{}", render_trace_arena(trace))?; } } @@ -207,9 +208,8 @@ impl PreSimulationState { .contracts .iter() .filter_map(move |(addr, contract_id)| { - let contract_name = get_contract_name(contract_id); if let Ok(Some((_, data))) = - self.build_data.known_contracts.find_by_name_or_identifier(contract_name) + self.build_data.known_contracts.find_by_name_or_identifier(contract_id) { return Some((*addr, data)); } diff --git a/crates/script/src/transaction.rs b/crates/script/src/transaction.rs index 87bcdec56..4bef28d57 100644 --- a/crates/script/src/transaction.rs +++ b/crates/script/src/transaction.rs @@ -158,7 +158,7 @@ impl ScriptTransactionBuilder { // Add the additional contracts created in this transaction, so we can verify them later. created_contracts.retain(|contract| { // Filter out the contract that was created by the transaction itself. - self.transaction.contract_address.map_or(true, |addr| addr != contract.address) + self.transaction.contract_address != Some(contract.address) }); self.transaction.additional_contracts = created_contracts; diff --git a/crates/script/src/verify.rs b/crates/script/src/verify.rs index 68b28a1ce..a7e7fcdc7 100644 --- a/crates/script/src/verify.rs +++ b/crates/script/src/verify.rs @@ -13,7 +13,6 @@ use foundry_compilers::{info::ContractInfo, Project}; use foundry_config::{Chain, Config}; use foundry_zksync_compiler::ZKSYNC_ARTIFACTS_DIR; use semver::Version; -use yansi::Paint; /// State after we have broadcasted the script. /// It is assumed that at this point [BroadcastedState::sequence] contains receipts for all @@ -121,7 +120,7 @@ impl VerifyBundle { if data.split_at(create2_offset).1.starts_with(bytecode) { let constructor_args = data.split_at(create2_offset + bytecode.len()).1.to_vec(); - if artifact.source.extension().map_or(false, |e| e.to_str() == Some("vy")) { + if artifact.source.extension().is_some_and(|e| e.to_str() == Some("vy")) { warn!("Skipping verification of Vyper contract: {}", artifact.name); } @@ -160,6 +159,7 @@ impl VerifyBundle { evm_version: None, show_standard_json_input: false, guess_constructor_args: false, + compilation_profile: Some(artifact.profile.to_string()), zksync: self.zksync, }; @@ -250,6 +250,7 @@ impl VerifyBundle { evm_version: None, show_standard_json_input: false, guess_constructor_args: false, + compilation_profile: None, //TODO(zk): get compilation profile zksync: self.zksync, }; @@ -321,13 +322,15 @@ async fn verify_contracts( let num_verifications = future_verifications.len(); let mut num_of_successful_verifications = 0; - println!("##\nStart verification for ({num_verifications}) contracts"); + sh_println!("##\nStart verification for ({num_verifications}) contracts")?; for verification in future_verifications { match verification.await { Ok(_) => { num_of_successful_verifications += 1; } - Err(err) => eprintln!("Error during verification: {err:#}"), + Err(err) => { + sh_err!("Failed to verify contract: {err:#}")?; + } } } @@ -335,7 +338,7 @@ async fn verify_contracts( return Err(eyre!("Not all ({num_of_successful_verifications} / {num_verifications}) contracts were verified!")) } - println!("All ({num_verifications}) contracts were verified!"); + sh_println!("All ({num_verifications}) contracts were verified!")?; } Ok(()) @@ -347,15 +350,9 @@ fn check_unverified( verify: VerifyBundle, ) { if !unverifiable_contracts.is_empty() { - println!( - "\n{}", - format!( - "We haven't found any matching bytecode for the following contracts: {:?}.\n\n{}", - unverifiable_contracts, - "This may occur when resuming a verification, but the underlying source code or compiler version has changed." - ) - .yellow() - .bold(), + let _ = sh_warn!( + "We haven't found any matching bytecode for the following contracts: {:?}.\n\nThis may occur when resuming a verification, but the underlying source code or compiler version has changed.", + unverifiable_contracts ); if let Some(commit) = &sequence.commit { @@ -366,7 +363,9 @@ fn check_unverified( .unwrap_or_default(); if ¤t_commit != commit { - println!("\tScript was broadcasted on commit `{commit}`, but we are at `{current_commit}`."); + let _ = sh_warn!( + "Script was broadcasted on commit `{commit}`, but we are at `{current_commit}`." + ); } } } diff --git a/crates/sol-macro-gen/src/sol_macro_gen.rs b/crates/sol-macro-gen/src/sol_macro_gen.rs index 7309104fe..8c146aa05 100644 --- a/crates/sol-macro-gen/src/sol_macro_gen.rs +++ b/crates/sol-macro-gen/src/sol_macro_gen.rs @@ -11,7 +11,7 @@ use alloy_sol_macro_expander::expand::expand; use alloy_sol_macro_input::{SolInput, SolInputKind}; -use eyre::{Context, Ok, OptionExt, Result}; +use eyre::{Context, OptionExt, Result}; use foundry_common::fs; use proc_macro2::{Span, TokenStream}; use std::{ @@ -39,7 +39,7 @@ impl SolMacroGen { #path }; - let sol_input: SolInput = syn::parse2(tokens).wrap_err("Failed to parse SolInput {e}")?; + let sol_input: SolInput = syn::parse2(tokens).wrap_err("failed to parse input")?; Ok(sol_input) } @@ -69,24 +69,35 @@ impl MultiSolMacroGen { pub fn generate_bindings(&mut self) -> Result<()> { for instance in &mut self.instances { - let input = instance.get_sol_input()?.normalize_json()?; + Self::generate_binding(instance).wrap_err_with(|| { + format!( + "failed to generate bindings for {}:{}", + instance.path.display(), + instance.name + ) + })?; + } - let SolInput { attrs: _attrs, path: _path, kind } = input; + Ok(()) + } - let tokens = match kind { - SolInputKind::Sol(mut file) => { - let sol_attr: syn::Attribute = syn::parse_quote! { - #[sol(rpc, alloy_sol_types = alloy::sol_types, alloy_contract = alloy::contract)] - }; - file.attrs.push(sol_attr); - expand(file).wrap_err("Failed to expand SolInput")? - } - _ => unreachable!(), - }; + fn generate_binding(instance: &mut SolMacroGen) -> Result<()> { + let input = instance.get_sol_input()?.normalize_json()?; - instance.expansion = Some(tokens); - } + let SolInput { attrs: _, path: _, kind } = input; + let tokens = match kind { + SolInputKind::Sol(mut file) => { + let sol_attr: syn::Attribute = syn::parse_quote! { + #[sol(rpc, alloy_sol_types = alloy::sol_types, alloy_contract = alloy::contract)] + }; + file.attrs.push(sol_attr); + expand(file).wrap_err("failed to expand")? + } + _ => unreachable!(), + }; + + instance.expansion = Some(tokens); Ok(()) } @@ -139,27 +150,28 @@ edition = "2021" )?; // Write src + let parse_error = |name: &str| { + format!("failed to parse generated tokens as an AST for {name};\nthis is likely a bug") + }; for instance in &self.instances { - let name = instance.name.to_lowercase(); - let contents = instance.expansion.as_ref().unwrap().to_string(); + let contents = instance.expansion.as_ref().unwrap(); - if !single_file { - let path = src.join(format!("{name}.rs")); - let file = syn::parse_file(&contents)?; - let contents = prettyplease::unparse(&file); - - fs::write(path.clone(), contents).wrap_err("Failed to write file")?; - writeln!(&mut lib_contents, "pub mod {name};")?; - } else { + let name = instance.name.to_lowercase(); + let path = src.join(format!("{name}.rs")); + let file = syn::parse2(contents.clone()) + .wrap_err_with(|| parse_error(&format!("{}:{}", path.display(), name)))?; + let contents = prettyplease::unparse(&file); + if single_file { write!(&mut lib_contents, "{contents}")?; + } else { + fs::write(path, contents).wrap_err("failed to write to file")?; + writeln!(&mut lib_contents, "pub mod {name};")?; } } let lib_path = src.join("lib.rs"); - let lib_file = syn::parse_file(&lib_contents)?; - + let lib_file = syn::parse_file(&lib_contents).wrap_err_with(|| parse_error("lib.rs"))?; let lib_contents = prettyplease::unparse(&lib_file); - fs::write(lib_path, lib_contents).wrap_err("Failed to write lib.rs")?; Ok(()) diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs index f3f944618..e51f5e831 100644 --- a/crates/test-utils/src/lib.rs +++ b/crates/test-utils/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index a9ff6a7e6..361bf56c2 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -1,15 +1,26 @@ //! RPC API keys utilities. -use foundry_config::NamedChain; +use foundry_config::{NamedChain, NamedChain::Optimism}; use rand::seq::SliceRandom; -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - LazyLock, +use std::{ + env, + sync::{ + atomic::{AtomicUsize, Ordering}, + LazyLock, + }, }; +/// Env var key for ws archive endpoints. +const ENV_WS_ARCHIVE_ENDPOINTS: &str = "WS_ARCHIVE_URLS"; +/// Env var key for http archive endpoints. +const ENV_HTTP_ARCHIVE_ENDPOINTS: &str = "HTTP_ARCHIVE_URLS"; + // List of general purpose infura keys to rotate through static INFURA_KEYS: LazyLock> = LazyLock::new(|| { let mut keys = vec![ + // "6cb19d07ca2d44f59befd61563b1037b", + // "6d46c0cca653407b861f3f93f7b0236a", + // "69a36846dec146e3a2898429be60be85", // "16a8be88795540b9b3903d8de0f7baa5", // "f4a0bdad42674adab5fc0ac077ffab2b", // "5c812e02193c4ba793f8c214317582bd", @@ -28,11 +39,11 @@ static ALCHEMY_KEYS: LazyLock> = LazyLock::new(|| { "GL4M0hfzSYGU5e1_t804HoUDOObWP-FA", "WV407BEiBmjNJfKo9Uo_55u0z0ITyCOX", "Ge56dH9siMF4T0whP99sQXOcr2mFs8wZ", - "QC55XC151AgkS3FNtWvz9VZGeu9Xd9lb", - "pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP", - "A5sZ85MIr4SzCMkT0zXh2eeamGIq3vGL", - "9VWGraLx0tMiSWx05WH-ywgSVmMxs66W", - "U4hsGWgl9lBM1j3jhSgJ4gbjHg2jRwKy", + // "QC55XC151AgkS3FNtWvz9VZGeu9Xd9lb", + // "pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP", + // "A5sZ85MIr4SzCMkT0zXh2eeamGIq3vGL", + // "9VWGraLx0tMiSWx05WH-ywgSVmMxs66W", + // "U4hsGWgl9lBM1j3jhSgJ4gbjHg2jRwKy", "K-uNlqYoYCO9cdBHcifwCDAcEjDy1UHL", "GWdgwabOE2XfBdLp_gIq-q6QHa7DSoag", "Uz0cF5HCXFtpZlvd9NR7kHxfB_Wdpsx7", @@ -75,14 +86,19 @@ static ETHERSCAN_MAINNET_KEYS: LazyLock> = LazyLock::new(|| { keys }); +// List of etherscan keys for Optimism. +static ETHERSCAN_OPTIMISM_KEYS: LazyLock> = + LazyLock::new(|| vec!["JQNGFHINKS1W7Y5FRXU4SPBYF43J3NYK46"]); + /// Returns the next index to use. -fn next() -> usize { +fn next_idx() -> usize { static NEXT_INDEX: AtomicUsize = AtomicUsize::new(0); NEXT_INDEX.fetch_add(1, Ordering::SeqCst) } -fn num_keys() -> usize { - INFURA_KEYS.len() + ALCHEMY_KEYS.len() +/// Returns the next item in the list to use. +fn next(list: &[T]) -> &T { + &list[next_idx() % list.len()] } /// Returns the next _mainnet_ rpc endpoint in inline @@ -111,20 +127,42 @@ pub fn next_ws_endpoint(chain: NamedChain) -> String { /// Returns endpoint that has access to archive state pub fn next_http_archive_rpc_endpoint() -> String { - let idx = next() % ALCHEMY_KEYS.len(); - format!("https://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + next_archive_endpoint(false) } /// Returns endpoint that has access to archive state pub fn next_ws_archive_rpc_endpoint() -> String { - let idx = next() % ALCHEMY_KEYS.len(); - format!("wss://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + next_archive_endpoint(true) +} + +/// Returns endpoint that has access to archive state, http or ws. +/// Use env vars (comma separated urls) or default inline keys (Alchemy for ws, Infura for http). +fn next_archive_endpoint(is_ws: bool) -> String { + let env_urls = if is_ws { ENV_WS_ARCHIVE_ENDPOINTS } else { ENV_HTTP_ARCHIVE_ENDPOINTS }; + + let rpc_env_vars = env::var(env_urls).unwrap_or_default(); + if !rpc_env_vars.is_empty() { + let urls = rpc_env_vars.split(',').collect::>(); + next(&urls).to_string() + } else if is_ws { + format!("wss://eth-mainnet.g.alchemy.com/v2/{}", next(&ALCHEMY_KEYS)) + } else { + format!("https://eth-mainnet.g.alchemy.com/v2/{}", next(&ALCHEMY_KEYS)) + } } /// Returns the next etherscan api key pub fn next_mainnet_etherscan_api_key() -> String { - let idx = next() % ETHERSCAN_MAINNET_KEYS.len(); - ETHERSCAN_MAINNET_KEYS[idx].to_string() + next_etherscan_api_key(NamedChain::Mainnet) +} + +/// Returns the next etherscan api key for given chain. +pub fn next_etherscan_api_key(chain: NamedChain) -> String { + let keys = match chain { + Optimism => ÐERSCAN_OPTIMISM_KEYS, + _ => ÐERSCAN_MAINNET_KEYS, + }; + next(keys).to_string() } fn next_url(is_ws: bool, chain: NamedChain) -> String { @@ -134,7 +172,7 @@ fn next_url(is_ws: bool, chain: NamedChain) -> String { return "https://mainnet.base.org".to_string(); } - let idx = next() % num_keys(); + let idx = next_idx() % (INFURA_KEYS.len() + ALCHEMY_KEYS.len()); let is_infura = idx < INFURA_KEYS.len(); let key = if is_infura { INFURA_KEYS[idx] } else { ALCHEMY_KEYS[idx - INFURA_KEYS.len()] }; @@ -170,14 +208,14 @@ fn next_url(is_ws: bool, chain: NamedChain) -> String { match (is_ws, is_infura) { (false, true) => format!("https://{full}.infura.io/v3/{key}"), - (true, true) => format!("wss://{full}.infura.io/v3/{key}"), + (true, true) => format!("wss://{full}.infura.io/ws/v3/{key}"), (false, false) => format!("https://{full}.g.alchemy.com/v2/{key}"), (true, false) => format!("wss://{full}.g.alchemy.com/v2/{key}"), } } #[cfg(test)] -#[allow(clippy::needless_return)] +#[allow(clippy::needless_return, clippy::disallowed_macros)] mod tests { use super::*; use alloy_primitives::address; @@ -190,7 +228,7 @@ mod tests { let mut first_abi = None; let mut failed = Vec::new(); for (i, &key) in ETHERSCAN_MAINNET_KEYS.iter().enumerate() { - eprintln!("trying key {i} ({key})"); + println!("trying key {i} ({key})"); let client = foundry_block_explorers::Client::builder() .chain(Chain::mainnet()) diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 11757978a..8d7f6cbb5 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -11,7 +11,7 @@ use foundry_compilers::{ use foundry_config::Config; use parking_lot::Mutex; use regex::Regex; -use snapbox::{cmd::OutputAssert, str}; +use snapbox::{assert_data_eq, cmd::OutputAssert, str, IntoData}; use std::{ env, ffi::OsStr, @@ -141,7 +141,7 @@ impl ExtTester { pub fn run(&self) { // Skip fork tests if the RPC url is not set. if self.fork_block.is_some() && std::env::var_os("ETH_RPC_URL").is_none() { - eprintln!("ETH_RPC_URL is not set; skipping"); + let _ = sh_eprintln!("ETH_RPC_URL is not set; skipping"); return; } @@ -159,7 +159,7 @@ impl ExtTester { if self.rev.is_empty() { let mut git = Command::new("git"); git.current_dir(root).args(["log", "-n", "1"]); - eprintln!("$ {git:?}"); + let _ = sh_println!("$ {git:?}"); let output = git.output().unwrap(); if !output.status.success() { panic!("git log failed: {output:?}"); @@ -170,7 +170,7 @@ impl ExtTester { } else { let mut git = Command::new("git"); git.current_dir(root).args(["checkout", self.rev]); - eprintln!("$ {git:?}"); + let _ = sh_println!("$ {git:?}"); let status = git.status().unwrap(); if !status.success() { panic!("git checkout failed: {status}"); @@ -181,15 +181,17 @@ impl ExtTester { for install_command in &self.install_commands { let mut install_cmd = Command::new(&install_command[0]); install_cmd.args(&install_command[1..]).current_dir(root); - eprintln!("cd {root}; {install_cmd:?}"); + let _ = sh_println!("cd {root}; {install_cmd:?}"); match install_cmd.status() { Ok(s) => { - eprintln!("\n\n{install_cmd:?}: {s}"); + let _ = sh_println!("\n\n{install_cmd:?}: {s}"); if s.success() { break; } } - Err(e) => eprintln!("\n\n{install_cmd:?}: {e}"), + Err(e) => { + let _ = sh_eprintln!("\n\n{install_cmd:?}: {e}"); + } } } @@ -222,8 +224,9 @@ impl ExtTester { /// This used to use a `static` `Lazy`, but this approach does not with `cargo-nextest` because it /// runs each test in a separate process. Instead, we use a global lock file to ensure that only one /// test can initialize the template at a time. +#[allow(clippy::disallowed_macros)] pub fn initialize(target: &Path) { - eprintln!("initializing {}", target.display()); + println!("initializing {}", target.display()); let tpath = TEMPLATE_PATH.as_path(); pretty_err(tpath, fs::create_dir_all(tpath)); @@ -251,7 +254,7 @@ pub fn initialize(target: &Path) { if data != "1" { // Initialize and build. let (prj, mut cmd) = setup_forge("template", foundry_compilers::PathStyle::Dapptools); - eprintln!("- initializing template dir in {}", prj.root().display()); + println!("- initializing template dir in {}", prj.root().display()); cmd.args(["init", "--force"]).assert_success(); // checkout forge-std @@ -281,7 +284,7 @@ pub fn initialize(target: &Path) { _read = Some(lock.read().unwrap()); } - eprintln!("- copying template dir from {}", tpath.display()); + println!("- copying template dir from {}", tpath.display()); pretty_err(target, fs::create_dir_all(target)); pretty_err(target, copy_dir(tpath, target)); } @@ -291,12 +294,12 @@ pub fn clone_remote(repo_url: &str, target_dir: &str) { let mut cmd = Command::new("git"); cmd.args(["clone", "--no-tags", "--recursive", "--shallow-submodules"]); cmd.args([repo_url, target_dir]); - eprintln!("{cmd:?}"); + let _ = sh_println!("{cmd:?}"); let status = cmd.status().unwrap(); if !status.success() { panic!("git clone failed: {status}"); } - eprintln!(); + let _ = sh_println!(); } /// Setup an empty test project and return a command pointing to the forge @@ -890,6 +893,15 @@ impl TestCommand { self.assert().success() } + /// Runs the command and asserts that it resulted in success, with expected JSON data. + #[track_caller] + pub fn assert_json_stdout(&mut self, expected: impl IntoData) { + let expected = expected.is(snapbox::data::DataFormat::Json).unordered(); + let stdout = self.assert_success().get_output().stdout.clone(); + let actual = stdout.into_data().is(snapbox::data::DataFormat::Json).unordered(); + assert_data_eq!(actual, expected); + } + /// Runs the command and asserts that it **failed** nothing was printed to stdout. #[track_caller] pub fn assert_empty_stdout(&mut self) { @@ -922,7 +934,7 @@ impl TestCommand { #[track_caller] pub fn try_execute(&mut self) -> std::io::Result { - eprintln!("executing {:?}", self.cmd); + let _ = sh_println!("executing {:?}", self.cmd); let mut child = self.cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::piped()).spawn()?; if let Some(fun) = self.stdin_fun.take() { diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index a4f368a96..d3079fae7 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -8,10 +8,13 @@ use crate::{ verify::VerifierArgs, }; use alloy_primitives::{hex, Address, Bytes, U256}; -use alloy_provider::Provider; -use alloy_rpc_types::{BlockId, BlockNumberOrTag, Transaction}; +use alloy_provider::{ + network::{AnyTxEnvelope, TransactionBuilder}, + Provider, +}; +use alloy_rpc_types::{BlockId, BlockNumberOrTag, TransactionInput, TransactionRequest}; use clap::{Parser, ValueHint}; -use eyre::{OptionExt, Result}; +use eyre::{Context, OptionExt, Result}; use foundry_cli::{ opts::EtherscanOpts, utils::{self, read_constructor_args_file, LoadConfig}, @@ -19,10 +22,9 @@ use foundry_cli::{ use foundry_common::shell; use foundry_compilers::{artifacts::EvmVersion, info::ContractInfo}; use foundry_config::{figment, impl_figment_convert, Config}; -use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, utils::configure_tx_env}; -use revm_primitives::AccountInfo; +use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, utils::configure_tx_req_env}; +use revm_primitives::{AccountInfo, TxKind}; use std::path::PathBuf; -use yansi::Paint; impl_figment_convert!(VerifyBytecodeArgs); @@ -36,11 +38,11 @@ pub struct VerifyBytecodeArgs { pub contract: ContractInfo, /// The block at which the bytecode should be verified. - #[clap(long, value_name = "BLOCK")] + #[arg(long, value_name = "BLOCK")] pub block: Option, /// The constructor args to generate the creation code. - #[clap( + #[arg( long, num_args(1..), conflicts_with_all = &["constructor_args_path", "encoded_constructor_args"], @@ -66,14 +68,15 @@ pub struct VerifyBytecodeArgs { pub constructor_args_path: Option, /// The rpc url to use for verification. - #[clap(short = 'r', long, value_name = "RPC_URL", env = "ETH_RPC_URL")] + #[arg(short = 'r', long, value_name = "RPC_URL", env = "ETH_RPC_URL")] pub rpc_url: Option, - #[clap(flatten)] + /// Etherscan options. + #[command(flatten)] pub etherscan: EtherscanOpts, /// Verifier options. - #[clap(flatten)] + #[command(flatten)] pub verifier: VerifierArgs, /// The project's root path. @@ -84,7 +87,7 @@ pub struct VerifyBytecodeArgs { pub root: Option, /// Ignore verification for creation or runtime bytecode. - #[clap(long, value_name = "BYTECODE_TYPE")] + #[arg(long, value_name = "BYTECODE_TYPE")] pub ignore: Option, } @@ -97,6 +100,11 @@ impl figment::Provider for VerifyBytecodeArgs { &self, ) -> Result, figment::Error> { let mut dict = self.etherscan.dict(); + + if let Some(api_key) = &self.verifier.verifier_api_key { + dict.insert("etherscan_api_key".into(), api_key.as_str().into()); + } + if let Some(block) = &self.block { dict.insert("block".into(), figment::value::Value::serialize(block)?); } @@ -142,11 +150,11 @@ impl VerifyBytecodeArgs { } if !shell::is_json() { - println!( + sh_println!( "Verifying bytecode for contract {} at address {}", - self.contract.name.clone().green(), - self.address.green() - ); + self.contract.name, + self.address + )?; } let mut json_results: Vec = vec![]; @@ -212,12 +220,10 @@ impl VerifyBytecodeArgs { if maybe_predeploy { if !shell::is_json() { - println!( - "{}", - format!("Attempting to verify predeployed contract at {:?}. Ignoring creation code verification.", self.address) - .yellow() - .bold() - ) + sh_warn!( + "Attempting to verify predeployed contract at {:?}. Ignoring creation code verification.", + self.address + )?; } // Append constructor args to the local_bytecode. @@ -241,21 +247,22 @@ impl VerifyBytecodeArgs { // Setup genesis tx and env. let deployer = Address::with_last_byte(0x1); - let mut gen_tx = Transaction { - from: deployer, - to: None, - input: Bytes::from(local_bytecode_vec), - ..Default::default() - }; + let mut gen_tx_req = TransactionRequest::default() + .with_from(deployer) + .with_input(Bytes::from(local_bytecode_vec)) + .into_create(); if let Some(ref block) = genesis_block { configure_env_block(&mut env, block); - gen_tx.max_fee_per_gas = block.header.base_fee_per_gas.map(|g| g as u128); - gen_tx.gas = block.header.gas_limit; - gen_tx.gas_price = block.header.base_fee_per_gas.map(|g| g as u128); + gen_tx_req.max_fee_per_gas = block.header.base_fee_per_gas.map(|g| g as u128); + gen_tx_req.gas = Some(block.header.gas_limit); + gen_tx_req.gas_price = block.header.base_fee_per_gas.map(|g| g as u128); } - configure_tx_env(&mut env, &gen_tx); + // configure_tx_rq_env(&mut env, &gen_tx); + + configure_tx_req_env(&mut env, &gen_tx_req) + .wrap_err("Failed to configure tx request env")?; // Seed deployer account with funds let account_info = AccountInfo { @@ -265,8 +272,12 @@ impl VerifyBytecodeArgs { }; executor.backend_mut().insert_account_info(deployer, account_info); - let fork_address = - crate::utils::deploy_contract(&mut executor, &env, config.evm_spec_id(), &gen_tx)?; + let fork_address = crate::utils::deploy_contract( + &mut executor, + &env, + config.evm_spec_id(), + gen_tx_req.to, + )?; // Compare runtime bytecode let (deployed_bytecode, onchain_runtime_code) = crate::utils::get_runtime_codes( @@ -305,7 +316,7 @@ impl VerifyBytecodeArgs { let creation_data = creation_data.unwrap(); // Get transaction and receipt. trace!(creation_tx_hash = ?creation_data.transaction_hash); - let mut transaction = provider + let transaction = provider .get_transaction_by_hash(creation_data.transaction_hash) .await .or_else(|e| eyre::bail!("Couldn't fetch transaction from RPC: {:?}", e))? @@ -325,12 +336,23 @@ impl VerifyBytecodeArgs { ); }; + let mut transaction: TransactionRequest = match transaction.inner.inner { + AnyTxEnvelope::Ethereum(tx) => tx.into(), + AnyTxEnvelope::Unknown(_) => unreachable!("Unknown transaction type"), + }; + // Extract creation code from creation tx input. let maybe_creation_code = if receipt.to.is_none() && receipt.contract_address == Some(self.address) { - &transaction.input + match &transaction.input.input { + Some(input) => &input[..], + None => unreachable!("creation tx input is None"), + } } else if receipt.to == Some(DEFAULT_CREATE2_DEPLOYER) { - &transaction.input[32..] + match &transaction.input.input { + Some(input) => &input[32..], + None => unreachable!("creation tx input is None"), + } } else { eyre::bail!( "Could not extract the creation code for contract at address {}", @@ -431,35 +453,39 @@ impl VerifyBytecodeArgs { // Use `transaction.from` instead of `creation_data.contract_creator` to resolve // blockscout creation data discrepancy in case of CREATE2. - let prev_block_nonce = - provider.get_transaction_count(transaction.from).block_id(prev_block_id).await?; - transaction.nonce = prev_block_nonce; + let prev_block_nonce = provider + .get_transaction_count(transaction.from.unwrap()) + .block_id(prev_block_id) + .await?; + transaction.set_nonce(prev_block_nonce); if let Some(ref block) = block { configure_env_block(&mut env, block) } // Replace the `input` with local creation code in the creation tx. - if let Some(to) = transaction.to { + if let Some(TxKind::Call(to)) = transaction.kind() { if to == DEFAULT_CREATE2_DEPLOYER { - let mut input = transaction.input[..32].to_vec(); // Salt + let mut input = transaction.input.input.unwrap()[..32].to_vec(); // Salt input.extend_from_slice(&local_bytecode_vec); - transaction.input = Bytes::from(input); + transaction.input = TransactionInput::both(Bytes::from(input)); // Deploy default CREATE2 deployer executor.deploy_create2_deployer()?; } } else { - transaction.input = Bytes::from(local_bytecode_vec); + transaction.input = TransactionInput::both(Bytes::from(local_bytecode_vec)); } - configure_tx_env(&mut env, &transaction.inner); + // configure_req__env(&mut env, &transaction.inner); + configure_tx_req_env(&mut env, &transaction) + .wrap_err("Failed to configure tx request env")?; let fork_address = crate::utils::deploy_contract( &mut executor, &env, config.evm_spec_id(), - &transaction, + transaction.to, )?; // State committed using deploy_with_env, now get the runtime bytecode from the db. diff --git a/crates/verify/src/etherscan/flatten.rs b/crates/verify/src/etherscan/flatten.rs index 84013560b..19b6feeb1 100644 --- a/crates/verify/src/etherscan/flatten.rs +++ b/crates/verify/src/etherscan/flatten.rs @@ -141,7 +141,7 @@ impl EtherscanFlattenedSource { let out = SolcCompiler::Specific(solc).compile(&input)?; if out.errors.iter().any(|e| e.is_error()) { let mut o = AggregatedCompilerOutput::::default(); - o.extend(version, RawBuildInfo::new(&input, &out, false)?, out); + o.extend(version, RawBuildInfo::new(&input, &out, false)?, "default", out); let diags = o.diagnostics(&[], &[], Default::default()); eyre::bail!( @@ -208,7 +208,7 @@ Diagnostics: {diags}", let out = zksolc.compile(&input.input)?; if out.has_error() { let mut o = ZkAggregatedCompilerOutput::default(); - o.extend(solc_version, raw_build_info_new(&input, &out, false)?, out); + o.extend(solc_version, raw_build_info_new(&input, &out, false)?, "default", out); let diags = o.diagnostics(&[], &[], Default::default()); eyre::bail!( diff --git a/crates/verify/src/etherscan/mod.rs b/crates/verify/src/etherscan/mod.rs index 2517d106d..c19862504 100644 --- a/crates/verify/src/etherscan/mod.rs +++ b/crates/verify/src/etherscan/mod.rs @@ -7,6 +7,7 @@ use crate::{ use alloy_json_abi::Function; use alloy_primitives::hex; use alloy_provider::Provider; +use alloy_rpc_types::TransactionTrait; use eyre::{eyre, Context, OptionExt, Result}; use foundry_block_explorers::{ errors::EtherscanError, @@ -76,11 +77,11 @@ impl VerificationProvider for EtherscanVerificationProvider { if !args.skip_is_verified_check && self.is_contract_verified(ðerscan, &verify_args).await? { - println!( + sh_println!( "\nContract [{}] {:?} is already verified. Skipping verification.", verify_args.contract_name, verify_args.address.to_checksum(None) - ); + )?; return Ok(()) } @@ -90,10 +91,11 @@ impl VerificationProvider for EtherscanVerificationProvider { let retry: Retry = args.retry.into(); let resp = retry .run_async(|| async { - println!( + sh_println!( "\nSubmitting verification for [{}] {}.", - verify_args.contract_name, verify_args.address - ); + verify_args.contract_name, + verify_args.address + )?; let resp = etherscan .submit_contract_verification(&verify_args) .await @@ -120,10 +122,12 @@ impl VerificationProvider for EtherscanVerificationProvider { } warn!("Failed verify submission: {:?}", resp); - eprintln!( - "Encountered an error verifying this contract:\nResponse: `{}`\nDetails: `{}`", - resp.message, resp.result - ); + sh_err!( + "Encountered an error verifying this contract:\nResponse: `{}`\nDetails: + `{}`", + resp.message, + resp.result + )?; std::process::exit(1); } @@ -132,12 +136,12 @@ impl VerificationProvider for EtherscanVerificationProvider { .await?; if let Some(resp) = resp { - println!( + sh_println!( "Submitted contract for verification:\n\tResponse: `{}`\n\tGUID: `{}`\n\tURL: {}", resp.message, resp.result, etherscan.address_url(args.address) - ); + )?; if args.watch { let check_args = VerifyCheckArgs { @@ -150,7 +154,7 @@ impl VerificationProvider for EtherscanVerificationProvider { return self.check(check_args).await } } else { - println!("Contract source code already verified"); + sh_println!("Contract source code already verified")?; } Ok(()) @@ -177,9 +181,10 @@ impl VerificationProvider for EtherscanVerificationProvider { trace!(?resp, "Received verification response"); - eprintln!( + let _ = sh_println!( "Contract verification status:\nResponse: `{}`\nDetails: `{}`", - resp.message, resp.result + resp.message, + resp.result ); if resp.result == "Pending in queue" { @@ -195,7 +200,7 @@ impl VerificationProvider for EtherscanVerificationProvider { } if resp.result == "Already Verified" { - println!("Contract source code already verified"); + let _ = sh_println!("Contract source code already verified"); return Ok(()) } @@ -204,7 +209,7 @@ impl VerificationProvider for EtherscanVerificationProvider { } if resp.result == "Pass - Verified" { - println!("Contract successfully verified"); + let _ = sh_println!("Contract successfully verified"); } Ok(()) @@ -439,9 +444,9 @@ impl EtherscanVerificationProvider { .ok_or_eyre("Couldn't fetch transaction receipt from RPC")?; let maybe_creation_code = if receipt.contract_address == Some(args.address) { - &transaction.input - } else if transaction.to == Some(DEFAULT_CREATE2_DEPLOYER) { - &transaction.input[32..] + transaction.inner.inner.input() + } else if transaction.to() == Some(DEFAULT_CREATE2_DEPLOYER) { + &transaction.inner.inner.input()[32..] } else { eyre::bail!("Fetching of constructor arguments is not supported for contracts created by contracts") }; diff --git a/crates/verify/src/etherscan/standard_json.rs b/crates/verify/src/etherscan/standard_json.rs index 068dde857..26a0bfcd1 100644 --- a/crates/verify/src/etherscan/standard_json.rs +++ b/crates/verify/src/etherscan/standard_json.rs @@ -18,7 +18,8 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { .wrap_err("Failed to get standard json input")? .normalize_evm_version(&context.compiler_version); - input.settings.libraries.libs = input + let mut settings = context.compiler_settings.solc.settings.clone(); + settings.libraries.libs = input .settings .libraries .libs @@ -28,8 +29,12 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { }) .collect(); + settings.remappings = input.settings.remappings; + // remove all incompatible settings - input.settings.sanitize(&context.compiler_version, SolcLanguage::Solidity); + settings.sanitize(&context.compiler_version, SolcLanguage::Solidity); + + input.settings = settings; let source = serde_json::to_string(&input).wrap_err("Failed to parse standard json input")?; diff --git a/crates/verify/src/provider.rs b/crates/verify/src/provider.rs index 69c85f9ee..4aa95e7ba 100644 --- a/crates/verify/src/provider.rs +++ b/crates/verify/src/provider.rs @@ -11,7 +11,8 @@ use eyre::{OptionExt, Result}; use foundry_common::compile::ProjectCompiler; use foundry_compilers::{ artifacts::{output_selection::OutputSelection, Metadata, Source}, - compilers::{multi::MultiCompilerParsedSource, solc::SolcCompiler, CompilerSettings}, + compilers::{multi::MultiCompilerParsedSource, solc::SolcCompiler}, + multi::MultiCompilerSettings, solc::Solc, Graph, Project, }; @@ -27,6 +28,7 @@ pub struct VerificationContext { pub target_path: PathBuf, pub target_name: String, pub compiler_version: Version, + pub compiler_settings: MultiCompilerSettings, } impl VerificationContext { @@ -35,6 +37,7 @@ impl VerificationContext { target_name: String, compiler_version: Version, config: Config, + compiler_settings: MultiCompilerSettings, ) -> Result { let mut project = config.project()?; project.no_artifacts = true; @@ -42,13 +45,13 @@ impl VerificationContext { let solc = Solc::find_or_install(&compiler_version)?; project.compiler.solc = Some(SolcCompiler::Specific(solc)); - Ok(Self { config, project, target_name, target_path, compiler_version }) + Ok(Self { config, project, target_name, target_path, compiler_version, compiler_settings }) } /// Compiles target contract requesting only ABI and returns it. pub fn get_target_abi(&self) -> Result { let mut project = self.project.clone(); - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::common_output_selection(["abi".to_string()]) }); @@ -67,7 +70,7 @@ impl VerificationContext { /// Compiles target file requesting only metadata and returns it. pub fn get_target_metadata(&self) -> Result { let mut project = self.project.clone(); - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::common_output_selection(["metadata".to_string()]); }); @@ -131,6 +134,7 @@ impl FromStr for VerificationProviderType { "b" | "blockscout" => Ok(Self::Blockscout), "o" | "oklink" => Ok(Self::Oklink), "z" | "zksync" => Ok(Self::ZKsync), + "c" | "custom" => Ok(Self::Custom), _ => Err(format!("Unknown provider: {s}")), } } @@ -154,6 +158,9 @@ impl fmt::Display for VerificationProviderType { Self::ZKsync => { write!(f, "zksync")?; } + Self::Custom => { + write!(f, "custom")?; + } }; Ok(()) } @@ -168,6 +175,8 @@ pub enum VerificationProviderType { Oklink, #[clap(name = "zksync")] ZKsync, + /// Custom verification provider, requires compatibility with the Etherscan API. + Custom, } impl VerificationProviderType { @@ -184,6 +193,7 @@ impl VerificationProviderType { Self::Blockscout => Ok(Box::::default()), Self::Oklink => Ok(Box::::default()), Self::ZKsync => Ok(Box::::default()), + Self::Custom => Ok(Box::::default()), } } } diff --git a/crates/verify/src/sourcify.rs b/crates/verify/src/sourcify.rs index d798ed03c..0cb4443b4 100644 --- a/crates/verify/src/sourcify.rs +++ b/crates/verify/src/sourcify.rs @@ -45,11 +45,11 @@ impl VerificationProvider for SourcifyVerificationProvider { let resp = retry .run_async(|| { async { - println!( + sh_println!( "\nSubmitting verification for [{}] {:?}.", context.target_name(), args.address.to_string() - ); + )?; let response = client .post(args.verifier.verifier_url.as_deref().unwrap_or(SOURCIFY_URL)) .header("Content-Type", "application/json") @@ -150,15 +150,15 @@ impl SourcifyVerificationProvider { match response.status.as_str() { "perfect" => { if let Some(ts) = &response.storage_timestamp { - println!("Contract source code already verified. Storage Timestamp: {ts}"); + sh_println!("Contract source code already verified. Storage Timestamp: {ts}")?; } else { - println!("Contract successfully verified"); + sh_println!("Contract successfully verified")?; } } "partial" => { - println!("The recompiled contract partially matches the deployed version"); + sh_println!("The recompiled contract partially matches the deployed version")?; } - "false" => println!("Contract source code is not verified"), + "false" => sh_println!("Contract source code is not verified")?, s => eyre::bail!("Unknown status from sourcify. Status: {s:?}"), } Ok(()) diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index e3065aca0..a14d6af6d 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -1,8 +1,8 @@ use crate::{bytecode::VerifyBytecodeArgs, types::VerificationType}; use alloy_dyn_abi::DynSolValue; use alloy_primitives::{Address, Bytes, U256}; -use alloy_provider::Provider; -use alloy_rpc_types::{AnyNetworkBlock, BlockId, Transaction}; +use alloy_provider::{network::AnyRpcBlock, Provider}; +use alloy_rpc_types::BlockId; use clap::ValueEnum; use eyre::{OptionExt, Result}; use foundry_block_explorers::{ @@ -17,7 +17,7 @@ use reqwest::Url; use revm_primitives::{ db::Database, env::{EnvWithHandlerCfg, HandlerCfg}, - Bytecode, Env, SpecId, + Bytecode, Env, SpecId, TxKind, }; use semver::Version; use serde::{Deserialize, Serialize}; @@ -145,7 +145,7 @@ pub fn print_result( ) { if let Some(res) = res { if !shell::is_json() { - println!( + let _ = sh_println!( "{} with status {}", format!("{bytecode_type:?} code matched").green().bold(), res.green().bold() @@ -155,17 +155,12 @@ pub fn print_result( json_results.push(json_res); } } else if !shell::is_json() { - println!( - "{}", - format!( - "{bytecode_type:?} code did not match - this may be due to varying compiler settings" - ) - .red() - .bold() + let _ = sh_err!( + "{bytecode_type:?} code did not match - this may be due to varying compiler settings" ); let mismatches = find_mismatch_in_settings(etherscan_config, config); for mismatch in mismatches { - println!("{}", mismatch.red().bold()); + let _ = sh_eprintln!("{}", mismatch.red().bold()); } } else { let json_res = JsonResult { @@ -345,9 +340,9 @@ pub async fn get_tracing_executor( Ok((env, executor)) } -pub fn configure_env_block(env: &mut Env, block: &AnyNetworkBlock) { +pub fn configure_env_block(env: &mut Env, block: &AnyRpcBlock) { env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.miner; + env.block.coinbase = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); @@ -358,11 +353,12 @@ pub fn deploy_contract( executor: &mut TracingExecutor, env: &Env, spec_id: SpecId, - transaction: &Transaction, + to: Option, ) -> Result { let env_with_handler = EnvWithHandlerCfg::new(Box::new(env.clone()), HandlerCfg::new(spec_id)); - if let Some(to) = transaction.to { + if to.is_some_and(|to| to.is_call()) { + let TxKind::Call(to) = to.unwrap() else { unreachable!() }; if to != DEFAULT_CREATE2_DEPLOYER { eyre::bail!("Transaction `to` address is not the default create2 deployer i.e the tx is not a contract creation tx."); } diff --git a/crates/verify/src/verify.rs b/crates/verify/src/verify.rs index e3724a7f2..784261eeb 100644 --- a/crates/verify/src/verify.rs +++ b/crates/verify/src/verify.rs @@ -30,14 +30,22 @@ pub struct VerifierArgs { #[arg(long, help_heading = "Verifier options", default_value = "etherscan", value_enum)] pub verifier: VerificationProviderType, - /// The verifier URL, if using a custom provider + /// The verifier API KEY, if using a custom provider. + #[arg(long, help_heading = "Verifier options", env = "VERIFIER_API_KEY")] + pub verifier_api_key: Option, + + /// The verifier URL, if using a custom provider. #[arg(long, help_heading = "Verifier options", env = "VERIFIER_URL")] pub verifier_url: Option, } impl Default for VerifierArgs { fn default() -> Self { - Self { verifier: VerificationProviderType::Etherscan, verifier_url: None } + Self { + verifier: VerificationProviderType::Etherscan, + verifier_api_key: None, + verifier_url: None, + } } } @@ -71,6 +79,10 @@ pub struct VerifyArgs { #[arg(long, value_name = "VERSION")] pub compiler_version: Option, + /// The compilation profile to use to build the smart contract. + #[arg(long, value_name = "PROFILE_NAME")] + pub compilation_profile: Option, + /// The number of optimization runs used to build the smart contract. #[arg(long, visible_alias = "optimizer-runs", value_name = "NUM")] pub num_of_optimizations: Option, @@ -165,6 +177,11 @@ impl figment::Provider for VerifyArgs { if self.via_ir { dict.insert("via_ir".to_string(), figment::value::Value::serialize(self.via_ir)?); } + + if let Some(api_key) = &self.verifier.verifier_api_key { + dict.insert("etherscan_api_key".into(), api_key.as_str().into()); + } + Ok(figment::value::Map::from([(Config::selected_profile(), dict)])) } } @@ -204,12 +221,12 @@ impl VerifyArgs { let args = EtherscanVerificationProvider::default() .create_verify_request(&self, &context) .await?; - println!("{}", args.source); + sh_println!("{}", args.source)?; return Ok(()) } let verifier_url = self.verifier.verifier_url.clone(); - println!("Start verifying contract `{}` deployed on {chain}", self.address); + sh_println!("Start verifying contract `{}` deployed on {chain}", self.address)?; self.verifier.verifier.client(&self.etherscan.key())?.verify(self, context).await.map_err(|err| { if let Some(verifier_url) = verifier_url { match Url::parse(&verifier_url) { @@ -252,6 +269,8 @@ impl VerifyArgs { project.find_contract_path(&contract.name)? }; + let cache = project.read_cache_file().ok(); + let version = if let Some(ref version) = self.compiler_version { version.trim_start_matches('v').parse()? } else if let Some(ref solc) = config.solc { @@ -259,10 +278,8 @@ impl VerifyArgs { SolcReq::Version(version) => version.to_owned(), SolcReq::Local(solc) => Solc::new(solc)?.version, } - } else if let Some(entry) = project - .read_cache_file() - .ok() - .and_then(|mut cache| cache.files.remove(&contract_path)) + } else if let Some(entry) = + cache.as_ref().and_then(|cache| cache.files.get(&contract_path).cloned()) { let unique_versions = entry .artifacts @@ -285,7 +302,48 @@ impl VerifyArgs { eyre::bail!("If cache is disabled, compiler version must be either provided with `--compiler-version` option or set in foundry.toml") }; - VerificationContext::new(contract_path, contract.name.clone(), version, config) + let settings = if let Some(profile) = &self.compilation_profile { + if profile == "default" { + &project.settings + } else if let Some(settings) = project.additional_settings.get(profile.as_str()) { + settings + } else { + eyre::bail!("Unknown compilation profile: {}", profile) + } + } else if let Some((cache, entry)) = cache + .as_ref() + .and_then(|cache| Some((cache, cache.files.get(&contract_path)?.clone()))) + { + let profiles = entry + .artifacts + .get(&contract.name) + .and_then(|artifacts| artifacts.get(&version)) + .map(|artifacts| artifacts.keys().collect::>()) + .unwrap_or_default(); + + if profiles.is_empty() { + eyre::bail!("No matching artifact found for {}", contract.name); + } else if profiles.len() > 1 { + eyre::bail!("Ambiguous compilation profiles found in cache: {}, please specify the profile through `--compilation-profile` flag", profiles.iter().join(", ")) + } + + let profile = profiles.into_iter().next().unwrap().to_owned(); + let settings = cache.profiles.get(&profile).expect("must be present"); + + settings + } else if project.additional_settings.is_empty() { + &project.settings + } else { + eyre::bail!("If cache is disabled, compilation profile must be provided with `--compiler-version` option or set in foundry.toml") + }; + + VerificationContext::new( + contract_path, + contract.name.clone(), + version, + config, + settings.clone(), + ) } else { if config.get_rpc_url().is_none() { eyre::bail!("You have to provide a contract name or a valid RPC URL") @@ -305,11 +363,19 @@ impl VerifyArgs { )) }; + let settings = project + .settings_profiles() + .find_map(|(name, settings)| { + (name == artifact_id.profile.as_str()).then_some(settings) + }) + .expect("must be present"); + VerificationContext::new( artifact_id.source.clone(), artifact_id.name.split('.').next().unwrap().to_owned(), artifact_id.version.clone(), config, + settings.clone(), ) } } @@ -415,7 +481,10 @@ impl_figment_convert_cast!(VerifyCheckArgs); impl VerifyCheckArgs { /// Run the verify command to submit the contract's source code for verification on etherscan pub async fn run(self) -> Result<()> { - println!("Checking verification status on {}", self.etherscan.chain.unwrap_or_default()); + sh_println!( + "Checking verification status on {}", + self.etherscan.chain.unwrap_or_default() + )?; self.verifier.verifier.client(&self.etherscan.key())?.check(self).await } } diff --git a/crates/verify/src/zksync/mod.rs b/crates/verify/src/zksync/mod.rs index 4784435d4..164b13f64 100644 --- a/crates/verify/src/zksync/mod.rs +++ b/crates/verify/src/zksync/mod.rs @@ -48,10 +48,10 @@ impl VerificationProvider for ZkVerificationProvider { let verification_id: u64 = retry .run_async(|| { async { - println!( + sh_println!( "\nSubmitting verification for [{}] at address {}.", request.contract_name, request.contract_address - ); + )?; let verifier_url = args .verifier @@ -88,7 +88,10 @@ impl VerificationProvider for ZkVerificationProvider { }) .await?; - println!("Verification submitted successfully. Verification ID: {}", verification_id); + let _ = sh_println!( + "Verification submitted successfully. Verification ID: {}", + verification_id + ); self.check(VerifyCheckArgs { id: verification_id.to_string(), @@ -102,12 +105,12 @@ impl VerificationProvider for ZkVerificationProvider { } async fn check(&self, args: VerifyCheckArgs) -> Result<()> { - println!( + sh_println!( "Checking verification status for ID: {} using verifier: {} at URL: {}", args.id, args.verifier.verifier, args.verifier.verifier_url.as_deref().unwrap_or("URL not specified") - ); + )?; let max_retries = args.retry.retries; let delay_in_seconds = args.retry.delay; @@ -236,7 +239,8 @@ impl ZkVerificationProvider { if resp.is_pending() || resp.is_queued() { if retries >= max_retries { - println!("Verification is still pending after {max_retries} retries."); + let _ = + sh_println!("Verification is still pending after {max_retries} retries."); return Ok(resp); } @@ -263,17 +267,17 @@ impl ZkVerificationProvider { if let Some(resp) = response { match resp.status { VerificationStatusEnum::Successful => { - println!("Verification was successful."); + let _ = sh_println!("Verification was successful."); } VerificationStatusEnum::Failed => { let error_message = resp.get_error(verification_url); eyre::bail!("Verification failed:\n\n{}", error_message); } VerificationStatusEnum::Queued => { - println!("Verification is queued."); + let _ = sh_println!("Verification is queued."); } VerificationStatusEnum::InProgress => { - println!("Verification is in progress."); + let _ = sh_println!("Verification is in progress."); } } } else { diff --git a/crates/wallets/src/wallet_signer.rs b/crates/wallets/src/wallet_signer.rs index a7bc1a312..812df9863 100644 --- a/crates/wallets/src/wallet_signer.rs +++ b/crates/wallets/src/wallet_signer.rs @@ -2,8 +2,8 @@ use crate::error::WalletSignerError; use alloy_consensus::SignableTransaction; use alloy_dyn_abi::TypedData; use alloy_network::TxSigner; -use alloy_primitives::{hex, Address, ChainId, B256}; -use alloy_signer::{Signature, Signer}; +use alloy_primitives::{hex, Address, ChainId, PrimitiveSignature, B256}; +use alloy_signer::Signer; use alloy_signer_ledger::{HDPath as LedgerHDPath, LedgerSigner}; use alloy_signer_local::{coins_bip39::English, MnemonicBuilder, PrivateKeySigner}; use alloy_signer_trezor::{HDPath as TrezorHDPath, TrezorSigner}; @@ -198,11 +198,11 @@ macro_rules! delegate { #[async_trait] impl Signer for WalletSigner { /// Signs the given hash. - async fn sign_hash(&self, hash: &B256) -> alloy_signer::Result { + async fn sign_hash(&self, hash: &B256) -> alloy_signer::Result { delegate!(self, inner => inner.sign_hash(hash)).await } - async fn sign_message(&self, message: &[u8]) -> alloy_signer::Result { + async fn sign_message(&self, message: &[u8]) -> alloy_signer::Result { delegate!(self, inner => inner.sign_message(message)).await } @@ -222,7 +222,7 @@ impl Signer for WalletSigner { &self, payload: &T, domain: &Eip712Domain, - ) -> alloy_signer::Result + ) -> alloy_signer::Result where Self: Sized, { @@ -232,21 +232,21 @@ impl Signer for WalletSigner { async fn sign_dynamic_typed_data( &self, payload: &TypedData, - ) -> alloy_signer::Result { + ) -> alloy_signer::Result { delegate!(self, inner => inner.sign_dynamic_typed_data(payload)).await } } #[async_trait] -impl TxSigner for WalletSigner { +impl TxSigner for WalletSigner { fn address(&self) -> Address { delegate!(self, inner => alloy_signer::Signer::address(inner)) } async fn sign_transaction( &self, - tx: &mut dyn SignableTransaction, - ) -> alloy_signer::Result { + tx: &mut dyn SignableTransaction, + ) -> alloy_signer::Result { delegate!(self, inner => inner.sign_transaction(tx)).await } } diff --git a/deny.toml b/deny.toml index 4f69208b8..f0992c98a 100644 --- a/deny.toml +++ b/deny.toml @@ -5,16 +5,6 @@ version = 2 yanked = "warn" ignore = [ - # https://github.com/watchexec/watchexec/issues/852 - "RUSTSEC-2024-0350", - "RUSTSEC-2024-0351", - "RUSTSEC-2022-0041", - "RUSTSEC-2023-0045", - "RUSTSEC-2020-0016", - # https://github.com/launchbadge/sqlx/issues/3440 - # Should remove once we can update sqlx which is used by some zksync dependencies - "RUSTSEC-2024-0363", - # Used by alloy # proc-macro-error is unmaintained "RUSTSEC-2024-0370", # instant is unmaintained @@ -24,6 +14,9 @@ ignore = [ # Used by boojum # derivative is unmaintained "RUSTSEC-2024-0388", + # Used by era-test-node + # net2 is unmaintained + "RUSTSEC-2020-0016" ] # This section is considered when running `cargo deny check bans`. @@ -62,6 +55,9 @@ allow = [ "BSD-2-Clause", "BSD-3-Clause", "Zlib", + "ISC", + "Unicode-3.0", + "Unicode-DFS-2016", "OpenSSL", "Apache-2.0 WITH LLVM-exception", "BSL-1.0", @@ -84,9 +80,6 @@ exceptions = [ { allow = ["CC0-1.0"], name = "notify" }, { allow = ["CC0-1.0"], name = "dunce" }, { allow = ["CC0-1.0"], name = "aurora-engine-modexp" }, - { allow = ["CC0-1.0"], name = "constant_time_eq" }, - { allow = ["CC0-1.0"], name = "secp256k1" }, - { allow = ["CC0-1.0"], name = "secp256k1-sys" }, ] #copyleft = "deny" @@ -118,7 +111,6 @@ allow-git = [ "https://github.com/paradigmxyz/revm-inspectors", "https://github.com/bluealloy/revm", "https://github.com/RustCrypto/hashes", - "https://github.com/Karrq/alloy", ] [sources.allow-org] diff --git a/foundryup-zksync/install b/foundryup-zksync/install index 8bf36687e..c2c6ec802 100755 --- a/foundryup-zksync/install +++ b/foundryup-zksync/install @@ -4,7 +4,7 @@ set -eo pipefail echo "Installing foundryup-zksync..." BASE_DIR="${XDG_CONFIG_HOME:-$HOME}" -FOUNDRY_DIR="${FOUNDRY_DIR-"$BASE_DIR/.foundry"}" +FOUNDRY_DIR="${FOUNDRY_DIR:-"$BASE_DIR/.foundry"}" FOUNDRY_BIN_DIR="$FOUNDRY_DIR/bin" FOUNDRY_MAN_DIR="$FOUNDRY_DIR/share/man/man1" diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index cd71f12e3..a34eac3d0 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -23,6 +23,7 @@ interface Vm { struct Gas { uint64 gasLimit; uint64 gasTotalUsed; uint64 gasMemoryUsed; int64 gasRefunded; uint64 gasRemaining; } struct DebugStep { uint256[] stack; bytes memoryInput; uint8 opcode; uint64 depth; bool isOutOfGas; address contractAddr; } struct BroadcastTxSummary { bytes32 txHash; BroadcastTxType txType; address contractAddress; uint64 blockNumber; bool success; } + struct SignedDelegation { uint8 v; bytes32 r; bytes32 s; uint64 nonce; address implementation; } function _expectCheatcodeRevert() external; function _expectCheatcodeRevert(bytes4 revertData) external; function _expectCheatcodeRevert(bytes calldata revertData) external; @@ -148,6 +149,7 @@ interface Vm { function assertTrue(bool condition, string calldata error) external pure; function assume(bool condition) external pure; function assumeNoRevert() external pure; + function attachDelegation(SignedDelegation memory signedDelegation) external; function blobBaseFee(uint256 newBlobBaseFee) external; function blobhashes(bytes32[] calldata hashes) external; function breakpoint(string calldata char) external pure; @@ -223,7 +225,7 @@ interface Vm { function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); function etch(address target, bytes calldata newRuntimeBytecode) external; function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] memory topics) external returns (EthGetLogs[] memory logs); - function exists(string calldata path) external returns (bool result); + function exists(string calldata path) external view returns (bool result); function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) external; function expectCall(address callee, bytes calldata data) external; @@ -259,14 +261,14 @@ interface Vm { function getBlobhashes() external view returns (bytes32[] memory hashes); function getBlockNumber() external view returns (uint256 height); function getBlockTimestamp() external view returns (uint256 timestamp); - function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory); - function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory); - function getBroadcasts(string memory contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory); + function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary memory); + function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary[] memory); + function getBroadcasts(string memory contractName, uint64 chainId) external view returns (BroadcastTxSummary[] memory); function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); - function getDeployment(string memory contractName) external returns (address deployedAddress); - function getDeployment(string memory contractName, uint64 chainId) external returns (address deployedAddress); - function getDeployments(string memory contractName, uint64 chainId) external returns (address[] memory deployedAddresses); + function getDeployment(string memory contractName) external view returns (address deployedAddress); + function getDeployment(string memory contractName, uint64 chainId) external view returns (address deployedAddress); + function getDeployments(string memory contractName, uint64 chainId) external view returns (address[] memory deployedAddresses); function getFoundryVersion() external view returns (string memory version); function getLabel(address account) external view returns (string memory currentLabel); function getMappingKeyAndParentOf(address target, bytes32 elementSlot) external returns (bool found, bytes32 key, bytes32 parent); @@ -278,8 +280,8 @@ interface Vm { function getWallets() external returns (address[] memory wallets); function indexOf(string calldata input, string calldata key) external pure returns (uint256); function isContext(ForgeContext context) external view returns (bool result); - function isDir(string calldata path) external returns (bool result); - function isFile(string calldata path) external returns (bool result); + function isDir(string calldata path) external view returns (bool result); + function isFile(string calldata path) external view returns (bool result); function isPersistent(address account) external view returns (bool persistent); function keyExists(string calldata json, string calldata key) external view returns (bool); function keyExistsJson(string calldata json, string calldata key) external view returns (bool); @@ -294,8 +296,12 @@ interface Vm { function makePersistent(address[] calldata accounts) external; function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) external; + function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external; + function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) external; function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + function mockCall(address callee, bytes4 data, bytes calldata returnData) external; + function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external; function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external; function mockCalls(address callee, uint256 msgValue, bytes calldata data, bytes[] calldata returnData) external; function mockFunction(address callee, address target, bytes calldata data) external; @@ -349,6 +355,8 @@ interface Vm { function pauseTracing() external view; function prank(address msgSender) external; function prank(address msgSender, address txOrigin) external; + function prank(address msgSender, bool delegateCall) external; + function prank(address msgSender, address txOrigin, bool delegateCall) external; function prevrandao(bytes32 newPrevrandao) external; function prevrandao(uint256 newPrevrandao) external; function projectRoot() external view returns (string memory path); @@ -428,10 +436,12 @@ interface Vm { function setEnv(string calldata name, string calldata value) external; function setNonce(address account, uint64 newNonce) external; function setNonceUnsafe(address account, uint64 newNonce) external; + function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); @@ -454,6 +464,8 @@ interface Vm { function startMappingRecording() external; function startPrank(address msgSender) external; function startPrank(address msgSender, address txOrigin) external; + function startPrank(address msgSender, bool delegateCall) external; + function startPrank(address msgSender, address txOrigin, bool delegateCall) external; function startSnapshotGas(string calldata name) external; function startSnapshotGas(string calldata group, string calldata name) external; function startStateDiffRecording() external; @@ -484,7 +496,7 @@ interface Vm { function trim(string calldata input) external pure returns (string memory output); function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); function txGasPrice(uint256 newGasPrice) external; - function unixTime() external returns (uint256 milliseconds); + function unixTime() external view returns (uint256 milliseconds); function warp(uint256 newTimestamp) external; function writeFile(string calldata path, string calldata data) external; function writeFileBinary(string calldata path, bytes calldata data) external; diff --git a/testdata/default/cheats/AttachDelegation.t.sol b/testdata/default/cheats/AttachDelegation.t.sol new file mode 100644 index 000000000..7befc9a32 --- /dev/null +++ b/testdata/default/cheats/AttachDelegation.t.sol @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +contract AttachDelegationTest is DSTest { + event ExecutedBy(uint256 id); + + Vm constant vm = Vm(HEVM_ADDRESS); + uint256 alice_pk = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; + address payable alice = payable(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); + uint256 bob_pk = 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a; + address bob = 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC; + + SimpleDelegateContract implementation; + SimpleDelegateContract implementation2; + ERC20 token; + + function setUp() public { + implementation = new SimpleDelegateContract(1); + implementation2 = new SimpleDelegateContract(2); + token = new ERC20(alice); + } + + function testCallSingleAttachDelegation() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + // executing as bob to make clear that we don't need to execute the tx as alice + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation); + + bytes memory code = address(alice).code; + require(code.length > 0, "no code written to alice"); + SimpleDelegateContract(alice).execute(calls); + + assertEq(token.balanceOf(bob), 100); + } + + function testMultiCallAttachDelegation() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation); + + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](2); + calls[0] = + SimpleDelegateContract.Call({to: address(token), data: abi.encodeCall(ERC20.mint, (50, bob)), value: 0}); + calls[1] = SimpleDelegateContract.Call({ + to: address(token), + data: abi.encodeCall(ERC20.mint, (50, address(this))), + value: 0 + }); + + SimpleDelegateContract(alice).execute(calls); + + assertEq(token.balanceOf(bob), 50); + assertEq(token.balanceOf(address(this)), 50); + } + + function testSwitchAttachDelegation() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation); + + vm.expectEmit(true, true, true, true); + emit ExecutedBy(1); + SimpleDelegateContract(alice).execute(calls); + + // switch to implementation2 + Vm.SignedDelegation memory signedDelegation2 = vm.signDelegation(address(implementation2), alice_pk); + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation2); + + vm.expectEmit(true, true, true, true); + emit ExecutedBy(2); + SimpleDelegateContract(alice).execute(calls); + + // verify final state + assertEq(token.balanceOf(bob), 200); + } + + function testAttachDelegationRevertInvalidSignature() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + // change v from 1 to 0 + signedDelegation.v = (signedDelegation.v + 1) % 2; + vm.attachDelegation(signedDelegation); + + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + + vm.broadcast(alice_pk); + // empty revert because no bytecode was set to Alice's account + vm.expectRevert(); + SimpleDelegateContract(alice).execute(calls); + } + + function testAttachDelegationRevertsAfterNonceChange() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + + vm.broadcast(alice_pk); + // send tx to increment alice's nonce + token.mint(1, bob); + + vm.expectRevert("vm.attachDelegation: invalid nonce"); + vm.attachDelegation(signedDelegation); + } + + function testCallSingleSignAndAttachDelegation() public { + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + vm.signAndAttachDelegation(address(implementation), alice_pk); + bytes memory code = address(alice).code; + require(code.length > 0, "no code written to alice"); + vm.broadcast(bob_pk); + SimpleDelegateContract(alice).execute(calls); + + assertEq(token.balanceOf(bob), 100); + } +} + +contract SimpleDelegateContract { + event Executed(address indexed to, uint256 value, bytes data); + event ExecutedBy(uint256 id); + + struct Call { + bytes data; + address to; + uint256 value; + } + + uint256 public immutable id; + + constructor(uint256 _id) { + id = _id; + } + + function execute(Call[] memory calls) external payable { + for (uint256 i = 0; i < calls.length; i++) { + Call memory call = calls[i]; + (bool success, bytes memory result) = call.to.call{value: call.value}(call.data); + require(success, string(result)); + emit Executed(call.to, call.value, call.data); + emit ExecutedBy(id); + } + } + + receive() external payable {} +} + +contract ERC20 { + address public minter; + mapping(address => uint256) private _balances; + + constructor(address _minter) { + minter = _minter; + } + + function mint(uint256 amount, address to) public { + _mint(to, amount); + } + + function balanceOf(address account) public view returns (uint256) { + return _balances[account]; + } + + function _mint(address account, uint256 amount) internal { + require(msg.sender == minter, "ERC20: msg.sender is not minter"); + require(account != address(0), "ERC20: mint to the zero address"); + unchecked { + _balances[account] += amount; + } + } +} diff --git a/testdata/cancun/cheats/BlobBaseFee.t.sol b/testdata/default/cheats/BlobBaseFee.t.sol similarity index 100% rename from testdata/cancun/cheats/BlobBaseFee.t.sol rename to testdata/default/cheats/BlobBaseFee.t.sol diff --git a/testdata/cancun/cheats/Blobhashes.t.sol b/testdata/default/cheats/Blobhashes.t.sol similarity index 100% rename from testdata/cancun/cheats/Blobhashes.t.sol rename to testdata/default/cheats/Blobhashes.t.sol diff --git a/testdata/default/cheats/Etch.t.sol b/testdata/default/cheats/Etch.t.sol index 33eaaf44e..f60ea4cad 100644 --- a/testdata/default/cheats/Etch.t.sol +++ b/testdata/default/cheats/Etch.t.sol @@ -8,7 +8,7 @@ contract EtchTest is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function testEtch() public { - address target = address(10); + address target = address(11); bytes memory code = hex"1010"; vm.etch(target, code); assertEq(string(code), string(target.code)); diff --git a/testdata/default/cheats/GetArtifactPath.t.sol b/testdata/default/cheats/GetArtifactPath.t.sol index 538c2e6c9..4b0df4ba6 100644 --- a/testdata/default/cheats/GetArtifactPath.t.sol +++ b/testdata/default/cheats/GetArtifactPath.t.sol @@ -13,25 +13,15 @@ contract GetArtifactPathTest is DSTest { DummyForGetArtifactPath dummy = new DummyForGetArtifactPath(); bytes memory dummyCreationCode = type(DummyForGetArtifactPath).creationCode; - string memory root = vm.projectRoot(); string memory path = vm.getArtifactPathByCode(dummyCreationCode); - - string memory expectedPath = - string.concat(root, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json"); - - assertEq(path, expectedPath); + assertTrue(vm.contains(path, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); } function testGetArtifactPathByDeployedCode() public { DummyForGetArtifactPath dummy = new DummyForGetArtifactPath(); bytes memory dummyRuntimeCode = address(dummy).code; - string memory root = vm.projectRoot(); string memory path = vm.getArtifactPathByDeployedCode(dummyRuntimeCode); - - string memory expectedPath = - string.concat(root, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json"); - - assertEq(path, expectedPath); + assertTrue(vm.contains(path, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); } } diff --git a/testdata/default/cheats/MockCall.t.sol b/testdata/default/cheats/MockCall.t.sol index 940e5e78c..f85e9c823 100644 --- a/testdata/default/cheats/MockCall.t.sol +++ b/testdata/default/cheats/MockCall.t.sol @@ -176,7 +176,7 @@ contract MockCallTest is DSTest { Mock mock = Mock(address(100)); vm.mockCall(address(mock), abi.encodeWithSelector(mock.add.selector), abi.encode(10)); - vm.mockCall(address(mock), abi.encodeWithSelector(mock.noReturnValue.selector), abi.encode()); + vm.mockCall(address(mock), mock.noReturnValue.selector, abi.encode()); assertEq(mock.add(1, 2), 10); mock.noReturnValue(); @@ -197,7 +197,7 @@ contract MockCallRevertTest is DSTest { assertEq(target.numberA(), 1); assertEq(target.numberB(), 2); - vm.mockCallRevert(address(target), abi.encodeWithSelector(target.numberB.selector), ERROR_MESSAGE); + vm.mockCallRevert(address(target), target.numberB.selector, ERROR_MESSAGE); // post-mock assertEq(target.numberA(), 1); diff --git a/testdata/default/cheats/Prank.t.sol b/testdata/default/cheats/Prank.t.sol index d833c0513..130e81960 100644 --- a/testdata/default/cheats/Prank.t.sol +++ b/testdata/default/cheats/Prank.t.sol @@ -85,9 +85,123 @@ contract NestedPranker { } } +contract ImplementationTest { + uint256 public num; + address public sender; + + function assertCorrectCaller(address expectedSender) public { + require(msg.sender == expectedSender); + } + + function assertCorrectOrigin(address expectedOrigin) public { + require(tx.origin == expectedOrigin); + } + + function setNum(uint256 _num) public { + num = _num; + } +} + +contract ProxyTest { + uint256 public num; + address public sender; +} + contract PrankTest is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); + function testPrankDelegateCallPrank2() public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.prank(address(proxy), true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "prank2: delegate call failed assertCorrectCaller"); + + // Assert storage updates + uint256 num = 42; + vm.prank(address(proxy), true); + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successTwo, "prank2: delegate call failed setNum"); + require(proxy.num() == num, "prank2: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testPrankDelegateCallStartPrank2() public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.startPrank(address(proxy), true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "startPrank2: delegate call failed assertCorrectCaller"); + + // Assert storage updates + uint256 num = 42; + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successTwo, "startPrank2: delegate call failed setNum"); + require(proxy.num() == num, "startPrank2: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testPrankDelegateCallPrank3(address origin) public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.prank(address(proxy), origin, true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "prank3: delegate call failed assertCorrectCaller"); + + // Assert correct `tx.origin` + vm.prank(address(proxy), origin, true); + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("assertCorrectOrigin(address)", origin)); + require(successTwo, "prank3: delegate call failed assertCorrectOrigin"); + + // Assert storage updates + uint256 num = 42; + vm.prank(address(proxy), address(origin), true); + (bool successThree,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successThree, "prank3: delegate call failed setNum"); + require(proxy.num() == num, "prank3: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testPrankDelegateCallStartPrank3(address origin) public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.startPrank(address(proxy), origin, true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "startPrank3: delegate call failed assertCorrectCaller"); + + // Assert correct `tx.origin` + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("assertCorrectOrigin(address)", origin)); + require(successTwo, "startPrank3: delegate call failed assertCorrectOrigin"); + + // Assert storage updates + uint256 num = 42; + (bool successThree,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successThree, "startPrank3: delegate call failed setNum"); + require(proxy.num() == num, "startPrank3: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testFailPrankDelegateCallToEOA() public { + uint256 privateKey = uint256(keccak256(abi.encodePacked("alice"))); + address alice = vm.addr(privateKey); + ImplementationTest impl = new ImplementationTest(); + vm.prank(alice, true); + // Should fail when EOA pranked with delegatecall. + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", alice)); + } + function testPrankSender(address sender) public { // Perform the prank Victim victim = new Victim(); diff --git a/testdata/default/cheats/RpcUrls.t.sol b/testdata/default/cheats/RpcUrls.t.sol index 7976fa572..9425d5963 100644 --- a/testdata/default/cheats/RpcUrls.t.sol +++ b/testdata/default/cheats/RpcUrls.t.sol @@ -10,7 +10,7 @@ contract RpcUrlTest is DSTest { // returns the correct url function testCanGetRpcUrl() public { string memory url = vm.rpcUrl("mainnet"); - assertEq(bytes(url).length, 69); + assertTrue(bytes(url).length == 61 || bytes(url).length == 69); } // returns an error if env alias does not exist @@ -22,9 +22,7 @@ contract RpcUrlTest is DSTest { // can set env and return correct url function testCanSetAndGetURLAndAllUrls() public { // this will fail because alias is not set - vm._expectCheatcodeRevert( - "Failed to resolve env var `RPC_ENV_ALIAS` in `${RPC_ENV_ALIAS}`: environment variable not found" - ); + vm._expectCheatcodeRevert("environment variable `RPC_ENV_ALIAS` not found"); string[2][] memory _urls = vm.rpcUrls(); string memory url = vm.rpcUrl("mainnet"); diff --git a/testdata/default/repros/Issue5929.t.sol b/testdata/default/repros/Issue5929.t.sol index 70c5a4f4f..ced9d6d9b 100644 --- a/testdata/default/repros/Issue5929.t.sol +++ b/testdata/default/repros/Issue5929.t.sol @@ -9,8 +9,8 @@ contract Issue5929Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function test_transact_not_working() public { - vm.createSelectFork("mainnet", 15625301); + vm.createSelectFork("mainnet", 21134547); // https://etherscan.io/tx/0x96a129768ec66fd7d65114bf182f4e173bf0b73a44219adaf71f01381a3d0143 - vm.transact(hex"96a129768ec66fd7d65114bf182f4e173bf0b73a44219adaf71f01381a3d0143"); + vm.transact(hex"7dcff74771babf9c23363c4228e55a27f50224d4596b1ba6608b0b45712f94ba"); } } diff --git a/testdata/default/repros/Issue6538.t.sol b/testdata/default/repros/Issue6538.t.sol index 5b318a04c..34c4e2253 100644 --- a/testdata/default/repros/Issue6538.t.sol +++ b/testdata/default/repros/Issue6538.t.sol @@ -9,9 +9,9 @@ contract Issue6538Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function test_transact() public { - bytes32 lastHash = 0xdbdce1d5c14a6ca17f0e527ab762589d6a73f68697606ae0bb90df7ac9ec5087; + bytes32 lastHash = 0x4b70ca8c5a0990b43df3064372d424d46efa41dfaab961754b86c5afb2df4f61; vm.createSelectFork("mainnet", lastHash); - bytes32 txhash = 0xadbe5cf9269a001d50990d0c29075b402bcc3a0b0f3258821881621b787b35c6; + bytes32 txhash = 0x7dcff74771babf9c23363c4228e55a27f50224d4596b1ba6608b0b45712f94ba; vm.transact(txhash); } } diff --git a/testdata/default/repros/Issue8006.t.sol b/testdata/default/repros/Issue8006.t.sol index 95b16e6f6..efe339d9f 100644 --- a/testdata/default/repros/Issue8006.t.sol +++ b/testdata/default/repros/Issue8006.t.sol @@ -18,10 +18,10 @@ contract Mock { contract Issue8006Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); IERC20 dai; - bytes32 transaction = 0x67cbad73764049e228495a3f90144aab4a37cb4b5fd697dffc234aa5ed811ace; + bytes32 transaction = 0xb23f389b26eb6f95c08e275ec2c360ab3990169492ff0d3e7b7233a3f81d299f; function setUp() public { - vm.createSelectFork("mainnet", 16261704); + vm.createSelectFork("mainnet", 21134541); dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); } @@ -30,7 +30,7 @@ contract Issue8006Test is DSTest { vm.etch(address(dai), address(new Mock()).code); assertEq(dai.totalSupply(), 1); vm.rollFork(transaction); - assertEq(dai.totalSupply(), 5155217627191887307044676292); + assertEq(dai.totalSupply(), 3324657947511778619416491233); } function testRollForkEtchCalled() public { diff --git a/testdata/paris/cheats/Fork.t.sol b/testdata/paris/cheats/Fork.t.sol new file mode 100644 index 000000000..2f2e627de --- /dev/null +++ b/testdata/paris/cheats/Fork.t.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +interface IWETH { + function deposit() external payable; + function balanceOf(address) external view returns (uint256); +} + +contract ForkTest is DSTest { + address constant WETH_TOKEN_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + uint256 constant mainblock = 14_608_400; + + Vm constant vm = Vm(HEVM_ADDRESS); + IWETH WETH = IWETH(WETH_TOKEN_ADDR); + + uint256 forkA; + uint256 forkB; + + uint256 testValue; + + // this will create two _different_ forks during setup + function setUp() public { + forkA = vm.createFork("mainnet", mainblock); + forkB = vm.createFork("mainnet2", mainblock - 1); + testValue = 999; + } + + // ensures forks use different ids + function testForkIdDiffer() public { + assert(forkA != forkB); + } + + // ensures we can create and select in one step + function testCreateSelect() public { + uint256 fork = vm.createSelectFork("mainnet"); + assertEq(fork, vm.activeFork()); + } + + // ensures forks use different ids + function testCanSwitchForks() public { + vm.selectFork(forkA); + vm.selectFork(forkB); + vm.selectFork(forkB); + vm.selectFork(forkA); + } + + function testForksHaveSeparatedStorage() public { + vm.selectFork(forkA); + // read state from forkA + assert(WETH.balanceOf(0x0000000000000000000000000000000000000000) != 1); + + vm.selectFork(forkB); + // read state from forkB + uint256 forkBbalance = WETH.balanceOf(0x0000000000000000000000000000000000000000); + assert(forkBbalance != 1); + + vm.selectFork(forkA); + + // modify state + bytes32 value = bytes32(uint256(1)); + // "0x3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff" is the slot storing the balance of zero address for the weth contract + // `cast index address uint 0x0000000000000000000000000000000000000000 3` + bytes32 zero_address_balance_slot = 0x3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff; + vm.store(WETH_TOKEN_ADDR, zero_address_balance_slot, value); + assertEq( + WETH.balanceOf(0x0000000000000000000000000000000000000000), + 1, + "Cheatcode did not change value at the storage slot." + ); + + // switch forks and ensure the balance on forkB remains untouched + vm.selectFork(forkB); + assert(forkBbalance != 1); + // balance of forkB is untouched + assertEq( + WETH.balanceOf(0x0000000000000000000000000000000000000000), + forkBbalance, + "Cheatcode did not change value at the storage slot." + ); + } + + function testCanShareDataAcrossSwaps() public { + assertEq(testValue, 999); + + uint256 val = 300; + vm.selectFork(forkA); + assertEq(val, 300); + + testValue = 100; + + vm.selectFork(forkB); + assertEq(val, 300); + assertEq(testValue, 100); + + val = 99; + testValue = 300; + + vm.selectFork(forkA); + assertEq(val, 99); + assertEq(testValue, 300); + } + + // ensures forks use different ids + function testCanChangeChainId() public { + vm.selectFork(forkA); + uint256 newChainId = 1337; + vm.chainId(newChainId); + uint256 expected = block.chainid; + assertEq(newChainId, expected); + } + + // ensures forks change chain ids automatically + function testCanAutoUpdateChainId() public { + vm.createSelectFork("sepolia"); + assertEq(block.chainid, 11155111); + } + + // ensures forks storage is cached at block + function testStorageCaching() public { + vm.createSelectFork("mainnet", 19800000); + } +} diff --git a/testdata/default/cheats/GasSnapshots.t.sol b/testdata/paris/cheats/GasSnapshots.t.sol similarity index 100% rename from testdata/default/cheats/GasSnapshots.t.sol rename to testdata/paris/cheats/GasSnapshots.t.sol diff --git a/testdata/default/cheats/LastCallGas.t.sol b/testdata/paris/cheats/LastCallGas.t.sol similarity index 100% rename from testdata/default/cheats/LastCallGas.t.sol rename to testdata/paris/cheats/LastCallGas.t.sol diff --git a/testdata/default/repros/Issue1543.t.sol b/testdata/paris/core/BeforeTest.t.sol similarity index 98% rename from testdata/default/repros/Issue1543.t.sol rename to testdata/paris/core/BeforeTest.t.sol index e58f331c4..2b14bcad1 100644 --- a/testdata/default/repros/Issue1543.t.sol +++ b/testdata/paris/core/BeforeTest.t.sol @@ -10,7 +10,7 @@ contract SelfDestructor { } // https://github.com/foundry-rs/foundry/issues/1543 -contract Issue1543Test is DSTest { +contract BeforeTestSelfDestructTest is DSTest { SelfDestructor killer; uint256 a; uint256 b; diff --git a/testdata/default/fork/Transact.t.sol b/testdata/paris/fork/Transact.t.sol similarity index 99% rename from testdata/default/fork/Transact.t.sol rename to testdata/paris/fork/Transact.t.sol index 375658772..92d595f98 100644 --- a/testdata/default/fork/Transact.t.sol +++ b/testdata/paris/fork/Transact.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.18; import "ds-test/test.sol"; import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "../../default/logs/console.sol"; interface IERC20 { function transfer(address to, uint256 amount) external returns (bool); diff --git a/testdata/paris/spec/ShanghaiCompat.t.sol b/testdata/paris/spec/ShanghaiCompat.t.sol new file mode 100644 index 000000000..fd7213b3d --- /dev/null +++ b/testdata/paris/spec/ShanghaiCompat.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +contract ShanghaiCompat is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testPush0() public { + address target = address(uint160(uint256(0xc4f3))); + + bytes memory bytecode = hex"365f5f37365ff3"; + // 36 CALLDATASIZE + // 5F PUSH0 + // 5F PUSH0 + // 37 CALLDATACOPY -> copies calldata at mem[0..calldatasize] + + // 36 CALLDATASIZE + // 5F PUSH0 + // F3 RETURN -> returns mem[0..calldatasize] + + vm.etch(target, bytecode); + + (bool success, bytes memory result) = target.call(bytes("hello PUSH0")); + assertTrue(success); + assertEq(string(result), "hello PUSH0"); + } +}